]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
CAST bind values against SQL Server sys into NVARCHAR
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 28 Jun 2019 14:41:38 +0000 (10:41 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 28 Jun 2019 15:17:47 +0000 (11:17 -0400)
Ensured that the queries used to reflect indexes and view definitions will
explicitly CAST string parameters into NVARCHAR, as many SQL Server drivers
frequently treat string values, particularly those with non-ascii
characters or larger string values, as TEXT which often don't compare
correctly against VARCHAR characters in SQL Server's information schema
tables for some reason.    These CAST operations already take place for
reflection queries against SQL Server ``information_schema.`` tables but
were missing from three additional queries that are against ``sys.``
tables.

Fixes: #4745
Change-Id: I3056533bf1a1e8ef17742879d369ab13f8b704ea
(cherry picked from commit 345f2eb05b07713cec19c620b95ca2dfa1ca5aa0)

doc/build/changelog/unreleased_13/4745.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mssql/base.py
test/dialect/mssql/test_reflection.py

diff --git a/doc/build/changelog/unreleased_13/4745.rst b/doc/build/changelog/unreleased_13/4745.rst
new file mode 100644 (file)
index 0000000..0728588
--- /dev/null
@@ -0,0 +1,13 @@
+.. change::
+    :tags: bug, mssql
+    :tickets: 4745
+
+    Ensured that the queries used to reflect indexes and view definitions will
+    explicitly CAST string parameters into NVARCHAR, as many SQL Server drivers
+    frequently treat string values, particularly those with non-ascii
+    characters or larger string values, as TEXT which often don't compare
+    correctly against VARCHAR characters in SQL Server's information schema
+    tables for some reason.    These CAST operations already take place for
+    reflection queries against SQL Server ``information_schema.`` tables but
+    were missing from three additional queries that are against ``sys.``
+    tables.
index 675c743f343a150b93c305911ba686bd12800003..c43aa1b05f802b4628a480fbcbee56ea76320b50 100644 (file)
@@ -2427,8 +2427,8 @@ class MSDialect(default.DefaultDialect):
                 "and ind.is_primary_key=0 and ind.type != 0"
             )
             .bindparams(
-                sql.bindparam("tabname", tablename, sqltypes.String()),
-                sql.bindparam("schname", owner, sqltypes.String()),
+                sql.bindparam("tabname", tablename, ischema.CoerceUnicode()),
+                sql.bindparam("schname", owner, ischema.CoerceUnicode()),
             )
             .columns(name=sqltypes.Unicode())
         )
@@ -2452,8 +2452,8 @@ class MSDialect(default.DefaultDialect):
                 "and sch.name=:schname"
             )
             .bindparams(
-                sql.bindparam("tabname", tablename, sqltypes.String()),
-                sql.bindparam("schname", owner, sqltypes.String()),
+                sql.bindparam("tabname", tablename, ischema.CoerceUnicode()),
+                sql.bindparam("schname", owner, ischema.CoerceUnicode()),
             )
             .columns(name=sqltypes.Unicode())
         )
@@ -2478,8 +2478,8 @@ class MSDialect(default.DefaultDialect):
                 "views.schema_id=sch.schema_id and "
                 "views.name=:viewname and sch.name=:schname"
             ).bindparams(
-                sql.bindparam("viewname", viewname, sqltypes.String()),
-                sql.bindparam("schname", owner, sqltypes.String()),
+                sql.bindparam("viewname", viewname, ischema.CoerceUnicode()),
+                sql.bindparam("schname", owner, ischema.CoerceUnicode()),
             )
         )
 
index d9b65d4e0ab7bd7f82bd1c74d2588ca8005ab314..8393a7b482f9a5a50fccb9d10a3f0582f5b73594 100644 (file)
@@ -208,6 +208,23 @@ class ReflectionTest(fixtures.TestBase, ComparesTables, AssertsCompiledSQL):
             ],
         )
 
+    @testing.provide_metadata
+    def test_table_name_that_is_greater_than_16_chars(self):
+        metadata = self.metadata
+        Table(
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+            metadata,
+            Column("id", Integer, primary_key=True),
+            Column("foo", Integer),
+            Index("foo_idx", "foo"),
+        )
+        metadata.create_all()
+
+        t = Table(
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ", MetaData(), autoload_with=testing.db
+        )
+        eq_(t.name, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
     @testing.provide_metadata
     def test_db_qualified_items(self):
         metadata = self.metadata