From: Mike Bayer Date: Thu, 18 Nov 2010 23:10:03 +0000 (-0500) Subject: - Ensured every numeric, float, int code, scalar + array, X-Git-Tag: rel_0_7b1~259 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34cb747f647747fc1685156d28166ab33da81ae8;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Ensured every numeric, float, int code, scalar + array, are recognized by psycopg2 and pg8000's "numeric" base type. [ticket:1955] --- diff --git a/CHANGES b/CHANGES index d7f9dd2769..4f65434559 100644 --- a/CHANGES +++ b/CHANGES @@ -52,6 +52,11 @@ CHANGES version of RowProxy, as well as 2.7 style "collections.Sequence" registration for RowProxy. [ticket:1871] + +- postgresql + - Ensured every numeric, float, int code, scalar + array, + are recognized by psycopg2 and pg8000's "numeric" + base type. [ticket:1955] - mysql - Fixed error handling for Jython + zxjdbc, such that diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 0d103cb0dc..6eec651b1b 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -98,9 +98,9 @@ from sqlalchemy.types import INTEGER, BIGINT, SMALLINT, VARCHAR, \ CHAR, TEXT, FLOAT, NUMERIC, \ DATE, BOOLEAN -_DECIMAL_TYPES = (1700, 1231) +_DECIMAL_TYPES = (1231, 1700) _FLOAT_TYPES = (700, 701, 1021, 1022) - +_INT_TYPES = (20, 21, 23, 26, 1005, 1007, 1016) class REAL(sqltypes.Float): __visit_name__ = "REAL" diff --git a/lib/sqlalchemy/dialects/postgresql/pg8000.py b/lib/sqlalchemy/dialects/postgresql/pg8000.py index 6af2cbd76d..7b1d8e6a74 100644 --- a/lib/sqlalchemy/dialects/postgresql/pg8000.py +++ b/lib/sqlalchemy/dialects/postgresql/pg8000.py @@ -9,14 +9,16 @@ URLs are of the form Unicode ------- -pg8000 requires that the postgresql client encoding be configured in the postgresql.conf file -in order to use encodings other than ascii. Set this value to the same value as -the "encoding" parameter on create_engine(), usually "utf-8". +pg8000 requires that the postgresql client encoding be +configured in the postgresql.conf file in order to use encodings +other than ascii. Set this value to the same value as the +"encoding" parameter on create_engine(), usually "utf-8". Interval -------- -Passing data from/to the Interval type is not supported as of yet. +Passing data from/to the Interval type is not supported as of +yet. """ import decimal @@ -27,26 +29,28 @@ from sqlalchemy import processors from sqlalchemy import types as sqltypes from sqlalchemy.dialects.postgresql.base import PGDialect, \ PGCompiler, PGIdentifierPreparer, PGExecutionContext,\ - _DECIMAL_TYPES, _FLOAT_TYPES + _DECIMAL_TYPES, _FLOAT_TYPES, _INT_TYPES class _PGNumeric(sqltypes.Numeric): def result_processor(self, dialect, coltype): if self.asdecimal: if coltype in _FLOAT_TYPES: return processors.to_decimal_processor_factory(decimal.Decimal) - elif coltype in _DECIMAL_TYPES: + elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES: # pg8000 returns Decimal natively for 1700 return None else: - raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype) + raise exc.InvalidRequestError( + "Unknown PG numeric type: %d" % coltype) else: if coltype in _FLOAT_TYPES: # pg8000 returns float natively for 701 return None - elif coltype in _DECIMAL_TYPES: + elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES: return processors.to_float else: - raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype) + raise exc.InvalidRequestError( + "Unknown PG numeric type: %d" % coltype) class PGExecutionContext_pg8000(PGExecutionContext): pass diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index 04b4e1fb76..7c5562064d 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -96,8 +96,9 @@ from sqlalchemy.sql import expression from sqlalchemy.sql import operators as sql_operators from sqlalchemy import types as sqltypes from sqlalchemy.dialects.postgresql.base import PGDialect, PGCompiler, \ - PGIdentifierPreparer, PGExecutionContext, \ - ENUM, ARRAY, _DECIMAL_TYPES, _FLOAT_TYPES + PGIdentifierPreparer, PGExecutionContext, \ + ENUM, ARRAY, _DECIMAL_TYPES, _FLOAT_TYPES,\ + _INT_TYPES logger = logging.getLogger('sqlalchemy.dialects.postgresql') @@ -111,19 +112,21 @@ class _PGNumeric(sqltypes.Numeric): if self.asdecimal: if coltype in _FLOAT_TYPES: return processors.to_decimal_processor_factory(decimal.Decimal) - elif coltype in _DECIMAL_TYPES: + elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES: # pg8000 returns Decimal natively for 1700 return None else: - raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype) + raise exc.InvalidRequestError( + "Unknown PG numeric type: %d" % coltype) else: if coltype in _FLOAT_TYPES: # pg8000 returns float natively for 701 return None - elif coltype in _DECIMAL_TYPES: + elif coltype in _DECIMAL_TYPES or coltype in _INT_TYPES: return processors.to_float else: - raise exc.InvalidRequestError("Unknown PG numeric type: %d" % coltype) + raise exc.InvalidRequestError( + "Unknown PG numeric type: %d" % coltype) class _PGEnum(ENUM): def __init__(self, *arg, **kw): diff --git a/test/dialect/test_postgresql.py b/test/dialect/test_postgresql.py index e20274aefa..54127cd986 100644 --- a/test/dialect/test_postgresql.py +++ b/test/dialect/test_postgresql.py @@ -456,7 +456,25 @@ class EnumTest(TestBase, AssertsExecutionResults, AssertsCompiledSQL): assert t2.c.value2.type.schema == 'test_schema' finally: metadata.drop_all() + +class NumericInterpretationTest(TestBase): + + + def test_numeric_codes(self): + from sqlalchemy.dialects.postgresql import pg8000, psycopg2, base + from decimal import Decimal + for dialect in (pg8000.dialect(), psycopg2.dialect()): + + typ = Numeric().dialect_impl(dialect) + for code in base._INT_TYPES + base._FLOAT_TYPES + \ + base._DECIMAL_TYPES: + proc = typ.result_processor(dialect, code) + val = 23.7 + if proc is not None: + val = proc(val) + assert val in (23.7, Decimal("23.7")) + class InsertTest(TestBase, AssertsExecutionResults): __only_on__ = 'postgresql'