diff options
author | Ben Shen <bshen@telesign.com> | 2017-10-20 11:31:59 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-10-25 10:50:54 -0400 |
commit | cd3db26cc90fcb896120b05e17528cc4c7c8e82e (patch) | |
tree | 5a75f8601bf4c078a0c86a07b58e110ddeeef68c /lib/sqlalchemy | |
parent | f34b180ca9059a74c3bf1db1b79e187c3f4b81c9 (diff) | |
download | sqlalchemy-cd3db26cc90fcb896120b05e17528cc4c7c8e82e.tar.gz |
Fix / consolidate for SQL Server BINARY, VARBINARY
Fixed bug where sqltypes.BINARY and sqltypes.VARBINARY datatypes
would not include correct bound-value handlers for pyodbc,
which allows the pyodbc.NullParam value to be passed that
helps with FreeTDS.
Co-authored by: Mike Bayer <mike_mp@zzzcomputing.com>
Change-Id: I6e3c16a69465b4fbc7b17a1927fb5e66acee93cb
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/386
Fixes: #4121
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/dialects/mssql/base.py | 9 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mssql/pyodbc.py | 24 |
2 files changed, 26 insertions, 7 deletions
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index a7c5286e0..0c3688c9b 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -618,7 +618,7 @@ from ... import engine from ...engine import reflection, default from ... import types as sqltypes from ...types import INTEGER, BIGINT, SMALLINT, DECIMAL, NUMERIC, \ - FLOAT, DATETIME, DATE, BINARY,\ + FLOAT, DATETIME, DATE, BINARY, \ TEXT, VARCHAR, NVARCHAR, CHAR, NCHAR @@ -874,10 +874,9 @@ class NTEXT(sqltypes.UnicodeText): class VARBINARY(sqltypes.VARBINARY, sqltypes.LargeBinary): """The MSSQL VARBINARY type. - This type extends both :class:`.types.VARBINARY` and - :class:`.types.LargeBinary`. In "deprecate_large_types" mode, - the :class:`.types.LargeBinary` type will produce ``VARBINARY(max)`` - on SQL Server. + This type is present to support "deprecate_large_types" mode where + either ``VARBINARY(max)`` or IMAGE is rendered. Otherwise, this type + object is redundant vs. :class:`.types.VARBINARY`. .. versionadded:: 1.0.0 diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index 6fd4fc554..60f08a8b3 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -87,7 +87,7 @@ versioning. """ -from .base import MSExecutionContext, MSDialect, VARBINARY +from .base import MSExecutionContext, MSDialect, BINARY, VARBINARY from ...connectors.pyodbc import PyODBCConnector from ... import types as sqltypes, util, exc import decimal @@ -167,7 +167,13 @@ class _MSFloat_pyodbc(_ms_numeric_pyodbc, sqltypes.Float): pass -class _VARBINARY_pyodbc(VARBINARY): +class _ms_binary_pyodbc(object): + """Wraps binary values in dialect-specific Binary wrapper. + If the value is null, return a pyodbc-specific BinaryNull + object to prevent pyODBC [and FreeTDS] from defaulting binary + NULL types to SQLWCHAR and causing implicit conversion errors. + """ + def bind_processor(self, dialect): if dialect.dbapi is None: return None @@ -183,6 +189,14 @@ class _VARBINARY_pyodbc(VARBINARY): return process +class _VARBINARY_pyodbc(_ms_binary_pyodbc, VARBINARY): + pass + + +class _BINARY_pyodbc(_ms_binary_pyodbc, BINARY): + pass + + class MSExecutionContext_pyodbc(MSExecutionContext): _embedded_scope_identity = False @@ -240,7 +254,13 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect): { sqltypes.Numeric: _MSNumeric_pyodbc, sqltypes.Float: _MSFloat_pyodbc, + BINARY: _BINARY_pyodbc, + + # SQL Server dialect has a VARBINARY that is just to support + # "deprecate_large_types" w/ VARBINARY(max), but also we must + # handle the usual SQL standard VARBINARY VARBINARY: _VARBINARY_pyodbc, + sqltypes.VARBINARY: _VARBINARY_pyodbc, sqltypes.LargeBinary: _VARBINARY_pyodbc, } ) |