diff options
author | Hajime Nakagami <nakagami@gmail.com> | 2014-10-16 22:11:14 +0900 |
---|---|---|
committer | Hajime Nakagami <nakagami@gmail.com> | 2014-10-16 22:11:14 +0900 |
commit | 2e598f63eb318e97995fb90bde35495dd85b6aaf (patch) | |
tree | 2cffb1ae89e73d23709abbc7bd318f3cdb4ebd98 | |
parent | d06e9c361fe0abd7bfdc7ecaceda931d981344db (diff) | |
download | sqlalchemy-pr/143.tar.gz |
minipg supportpr/143
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/__init__.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/minipg.py | 118 | ||||
-rw-r--r-- | test/dialect/postgresql/test_query.py | 8 | ||||
-rw-r--r-- | test/dialect/postgresql/test_types.py | 4 | ||||
-rw-r--r-- | test/engine/test_transaction.py | 1 | ||||
-rw-r--r-- | test/requirements.py | 2 | ||||
-rw-r--r-- | test/sql/test_types.py | 1 |
7 files changed, 133 insertions, 3 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/__init__.py b/lib/sqlalchemy/dialects/postgresql/__init__.py index 1cff8e3a0..aed82edce 100644 --- a/lib/sqlalchemy/dialects/postgresql/__init__.py +++ b/lib/sqlalchemy/dialects/postgresql/__init__.py @@ -5,7 +5,7 @@ # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php -from . import base, psycopg2, pg8000, pypostgresql, zxjdbc +from . import base, psycopg2, pg8000, pypostgresql, zxjdbc, minipg base.dialect = psycopg2.dialect diff --git a/lib/sqlalchemy/dialects/postgresql/minipg.py b/lib/sqlalchemy/dialects/postgresql/minipg.py new file mode 100644 index 000000000..b3f184abf --- /dev/null +++ b/lib/sqlalchemy/dialects/postgresql/minipg.py @@ -0,0 +1,118 @@ +# postgresql/minipg.py +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors +# <see AUTHORS file> +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + +""" +.. dialect:: postgresql+minipg + :name: minipg + :dbapi: minipg + :connectstring: postgresql+minipg://user:password@host:port/dbname\ +[?key=value&key=value...] + :url: https://github.com/nakagami/minipg + + +""" +import decimal +from ... import util, exc +from ... import types as sqltypes +from .base import PGDialect, PGCompiler, \ + PGExecutionContext, _DECIMAL_TYPES, _FLOAT_TYPES, _INT_TYPES +from ... import processors + +class _PGNumeric(sqltypes.Numeric): + def bind_processor(self, dialect): + return None + + def result_processor(self, dialect, coltype): + if self.asdecimal: + if coltype in _FLOAT_TYPES: + return processors.to_decimal_processor_factory( + decimal.Decimal, + self._effective_decimal_return_scale) + elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES: + # minipg returns Decimal natively for 1700 + return None + else: + raise exc.InvalidRequestError( + "Unknown PG numeric type: %d" % coltype) + else: + if coltype in _FLOAT_TYPES: + # minipg returns float natively for 701 + return None + elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES: + return processors.to_float + else: + raise exc.InvalidRequestError( + "Unknown PG numeric type: %d" % coltype) + + + +class PGCompiler_minipg(PGCompiler): + def visit_match_op_binary(self, binary, operator, **kw): + v = __import__('minipg').escape_parameter(binary.right) + return "%s=%s" % (self.process(binary.left, **kw), v) + +class PGDialect_minipg(PGDialect): + driver = 'minipg' + + default_paramstyle = 'format' + supports_sane_multi_rowcount = True + supports_unicode_statements = True + supports_unicode_binds = True + description_encoding = 'use_encoding' + statement_compiler = PGCompiler_minipg + + colspecs = util.update_copy( + PGDialect.colspecs, + { + sqltypes.Numeric: _PGNumeric, + } + ) + + @classmethod + def dbapi(cls): + return __import__('minipg') + + def create_connect_args(self, url): + opts = url.translate_connect_args(username='user') + if 'port' in opts: + opts['port'] = int(opts['port']) + else: + opts['port'] = 5432 + opts.update(url.query) + return ([], opts) + + def is_disconnect(self, e, connection, cursor): + if not connection: + return False + return not connection.is_connect() + + def set_isolation_level(self, connection, level): + level = level.replace('_', ' ') + + # adjust for ConnectionFairy possibly being present + if hasattr(connection, 'connection'): + connection = connection.connection + + if level == 'AUTOCOMMIT': + connection.autocommit = True + elif level in self._isolation_lookup: + connection.autocommit = False + cursor = connection.cursor() + cursor.execute( + "SET SESSION CHARACTERISTICS AS TRANSACTION " + "ISOLATION LEVEL %s" % level) + cursor.execute("COMMIT") + cursor.close() + else: + raise exc.ArgumentError( + "Invalid value '%s' for isolation_level. " + "Valid isolation levels for %s are %s or AUTOCOMMIT" % + (level, self.name, ", ".join(self._isolation_lookup)) + ) + + +dialect = PGDialect_minipg diff --git a/test/dialect/postgresql/test_query.py b/test/dialect/postgresql/test_query.py index a512b56fa..3ec3bd3f2 100644 --- a/test/dialect/postgresql/test_query.py +++ b/test/dialect/postgresql/test_query.py @@ -684,6 +684,7 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL): metadata.drop_all() @testing.fails_on('postgresql+pg8000', 'uses positional') + @testing.fails_on('postgresql+minipg', 'uses format') @testing.fails_on('postgresql+zxjdbc', 'uses qmark') def test_expression_pyformat(self): self.assert_compile(matchtable.c.title.match('somstr'), @@ -692,27 +693,32 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL): @testing.fails_on('postgresql+psycopg2', 'uses pyformat') @testing.fails_on('postgresql+pypostgresql', 'uses pyformat') + @testing.fails_on('postgresql+minipg', 'uses format') @testing.fails_on('postgresql+zxjdbc', 'uses qmark') def test_expression_positional(self): self.assert_compile(matchtable.c.title.match('somstr'), 'matchtable.title @@ to_tsquery(%s)') + @testing.fails_on('postgresql+minipg', 'uses format') def test_simple_match(self): results = matchtable.select().where( matchtable.c.title.match('python')).order_by( matchtable.c.id).execute().fetchall() eq_([2, 5], [r.id for r in results]) + @testing.fails_on('postgresql+minipg', 'uses format') def test_simple_match_with_apostrophe(self): results = matchtable.select().where( matchtable.c.title.match("Matz's")).execute().fetchall() eq_([3], [r.id for r in results]) + @testing.fails_on('postgresql+minipg', 'uses format') def test_simple_derivative_match(self): results = matchtable.select().where( matchtable.c.title.match('nutshells')).execute().fetchall() eq_([5], [r.id for r in results]) + @testing.fails_on('postgresql+minipg', 'uses format') def test_or_match(self): results1 = matchtable.select().where( or_( @@ -725,6 +731,7 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL): matchtable.c.id).execute().fetchall() eq_([3, 5], [r.id for r in results2]) + @testing.fails_on('postgresql+minipg', 'uses format') def test_and_match(self): results1 = matchtable.select().where( and_( @@ -737,6 +744,7 @@ class MatchTest(fixtures.TestBase, AssertsCompiledSQL): )).execute().fetchall() eq_([5], [r.id for r in results2]) + @testing.fails_on('postgresql+minipg', 'uses format') def test_match_across_joins(self): results = matchtable.select().where( and_( diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py index 5c5da59b1..d6533e0ea 100644 --- a/test/dialect/postgresql/test_types.py +++ b/test/dialect/postgresql/test_types.py @@ -81,6 +81,8 @@ class FloatCoercionTest(fixtures.TablesTest, AssertsExecutionResults): @testing.fails_on('postgresql+zxjdbc', 'zxjdbc has no support for PG arrays') + @testing.fails_on('postgresql+minipg', + 'minipg has no support for PG arrays') @testing.provide_metadata def test_arrays(self): metadata = self.metadata @@ -561,7 +563,7 @@ class ArrayTest(fixtures.TablesTest, AssertsExecutionResults): __only_on__ = 'postgresql' __backend__ = True - __unsupported_on__ = 'postgresql+pg8000', 'postgresql+zxjdbc' + __unsupported_on__ = 'postgresql+pg8000', 'postgresql+minipg', 'postgresql+zxjdbc' @classmethod def define_tables(cls, metadata): diff --git a/test/engine/test_transaction.py b/test/engine/test_transaction.py index b3b17e75a..56f18e305 100644 --- a/test/engine/test_transaction.py +++ b/test/engine/test_transaction.py @@ -1211,7 +1211,6 @@ class TLTransactionTest(fixtures.TestBase): order_by(users.c.user_id)).fetchall(), [(1, ), (2, )]) - class IsolationLevelTest(fixtures.TestBase): __requires__ = ('isolation_level', 'ad_hoc_engines') __backend__ = True diff --git a/test/requirements.py b/test/requirements.py index 0a695b641..d93637cbe 100644 --- a/test/requirements.py +++ b/test/requirements.py @@ -267,6 +267,7 @@ class DefaultRequirements(SuiteRequirements): "sqlite", "sybase", ("mysql", "<", (5, 0, 3)), + "postgresql+minipg", ], "savepoints not supported") @@ -369,6 +370,7 @@ class DefaultRequirements(SuiteRequirements): no_support('drizzle', 'two-phase xact not supported by database'), no_support('sqlite', 'two-phase xact not supported by database'), no_support('sybase', 'two-phase xact not supported by drivers/SQLA'), + no_support('postgresql+minipg', 'two-phase xact not supported by minipg'), no_support('postgresql+zxjdbc', 'FIXME: JDBC driver confuses the transaction state, may ' 'need separate XA implementation'), diff --git a/test/sql/test_types.py b/test/sql/test_types.py index efa0f90ae..a884fd082 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -934,6 +934,7 @@ class UnicodeTest(fixtures.TestBase): ('postgresql', 'psycopg2'), ('postgresql', 'pypostgresql'), ('postgresql', 'pg8000'), + ('postgresql', 'minipg'), ('postgresql', 'zxjdbc'), ('mysql', 'oursql'), ('mysql', 'zxjdbc'), |