summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-06-28 10:41:38 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-06-28 10:41:38 -0400
commit345f2eb05b07713cec19c620b95ca2dfa1ca5aa0 (patch)
tree9611a3a72fd81708e73c78c8d8d808e793652b91
parent502cd9240e639bd9334ac83111d22500506ca773 (diff)
downloadsqlalchemy-345f2eb05b07713cec19c620b95ca2dfa1ca5aa0.tar.gz
CAST bind values against SQL Server sys into NVARCHAR
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
-rw-r--r--doc/build/changelog/unreleased_13/4745.rst13
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py12
-rw-r--r--test/dialect/mssql/test_reflection.py17
3 files changed, 36 insertions, 6 deletions
diff --git a/doc/build/changelog/unreleased_13/4745.rst b/doc/build/changelog/unreleased_13/4745.rst
new file mode 100644
index 000000000..0728588a1
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4745.rst
@@ -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.
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index 99abba2c6..b2bcc280c 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -2426,8 +2426,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())
)
@@ -2451,8 +2451,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())
)
@@ -2477,8 +2477,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()),
)
)
diff --git a/test/dialect/mssql/test_reflection.py b/test/dialect/mssql/test_reflection.py
index d9b65d4e0..8393a7b48 100644
--- a/test/dialect/mssql/test_reflection.py
+++ b/test/dialect/mssql/test_reflection.py
@@ -209,6 +209,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
Table("foo", metadata, Column("id", Integer, primary_key=True))