From: Mike Bayer Date: Sat, 28 Dec 2013 22:50:19 +0000 (-0500) Subject: - apply a similar fix for floats to mssql+pyodbc as we did to firebird X-Git-Tag: rel_0_9_0~4^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1eb92e50d9845642940e7ab20906384bebec85fb;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - apply a similar fix for floats to mssql+pyodbc as we did to firebird - wrangle through osx+pyodbc+freetds to get at least test_suite to pass again with mssql+pyodbc. invovled adding some silly requirements --- diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index 2e6bc153cb..974949cffd 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -28,12 +28,12 @@ in order of RDB$FIELD_POSITION. .. change:: - :tags: bug, firebird + :tags: bug, mssql, firebird :versions: 0.9.0b2 The "asdecimal" flag used with the :class:`.Float` type will now - work with Firebird dialects; previously the decimal conversion was - not occurring. + work with Firebird as well as the mssql+pyodbc dialects; previously the + decimal conversion was not occurring. .. change:: :tags: bug, mssql, pymssql diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index 5a359d1795..036265cfb4 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -116,8 +116,8 @@ from ...connectors.pyodbc import PyODBCConnector from ... import types as sqltypes, util import decimal +class _ms_numeric_pyodbc(object): -class _MSNumeric_pyodbc(sqltypes.Numeric): """Turns Decimals with adjusted() < 0 or > 7 into strings. The routines here are needed for older pyodbc versions @@ -127,7 +127,7 @@ class _MSNumeric_pyodbc(sqltypes.Numeric): def bind_processor(self, dialect): - super_process = super(_MSNumeric_pyodbc, self).\ + super_process = super(_ms_numeric_pyodbc, self).\ bind_processor(dialect) if not dialect._need_decimal_fix: @@ -180,6 +180,11 @@ class _MSNumeric_pyodbc(sqltypes.Numeric): [str(s) for s in _int][0:value.adjusted() + 1])) return result +class _MSNumeric_pyodbc(_ms_numeric_pyodbc, sqltypes.Numeric): + pass + +class _MSFloat_pyodbc(_ms_numeric_pyodbc, sqltypes.Float): + pass class MSExecutionContext_pyodbc(MSExecutionContext): _embedded_scope_identity = False @@ -238,7 +243,8 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect): colspecs = util.update_copy( MSDialect.colspecs, { - sqltypes.Numeric: _MSNumeric_pyodbc + sqltypes.Numeric: _MSNumeric_pyodbc, + sqltypes.Float: _MSFloat_pyodbc } ) diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 3e48ba026e..60e966b3b8 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -424,6 +424,16 @@ class SuiteRequirements(Requirements): """ return exclusions.open() + @property + def fetch_null_from_numeric(self): + """target backend doesn't crash when you try to select a NUMERIC + value that has a value of NULL. + + Added to support Pyodbc bug #351. + """ + + return exclusions.open() + @property def text_type(self): """Target database must support an unbounded Text() " diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index b147f891a7..a6e937e8e2 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -369,15 +369,31 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): def test_numeric_as_decimal(self): self._do_test( Numeric(precision=8, scale=4), - [15.7563, decimal.Decimal("15.7563"), None], - [decimal.Decimal("15.7563"), None], + [15.7563, decimal.Decimal("15.7563")], + [decimal.Decimal("15.7563")], ) def test_numeric_as_float(self): self._do_test( Numeric(precision=8, scale=4, asdecimal=False), - [15.7563, decimal.Decimal("15.7563"), None], - [15.7563, None], + [15.7563, decimal.Decimal("15.7563")], + [15.7563], + ) + + @testing.requires.fetch_null_from_numeric + def test_numeric_null_as_decimal(self): + self._do_test( + Numeric(precision=8, scale=4), + [None], + [None], + ) + + @testing.requires.fetch_null_from_numeric + def test_numeric_null_as_float(self): + self._do_test( + Numeric(precision=8, scale=4, asdecimal=False), + [None], + [None], ) @testing.requires.floats_to_four_decimals diff --git a/test/requirements.py b/test/requirements.py index b90591a802..d26eb86cbe 100644 --- a/test/requirements.py +++ b/test/requirements.py @@ -570,9 +570,19 @@ class DefaultRequirements(SuiteRequirements): ("mysql+oursql", None, None, "Floating point error"), ("firebird", None, None, "Firebird still has FP inaccuracy even " - "with only four decimal places") + "with only four decimal places"), + ('mssql+pyodbc', None, None, + 'mssql+pyodbc has FP inaccuracy even with ' + 'only four decimal places ' + ) ]) + @property + def fetch_null_from_numeric(self): + return skip_if( + ("mssql+pyodbc", None, None, "crashes due to bug #351"), + ) + @property def python2(self): return skip_if(