summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-10-17 21:29:51 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-10-17 22:13:45 -0400
commitadd9cdd6628f7663229c5e549afac7041a06cfd9 (patch)
tree59b1f08fc7b18d525af39d45e7d2de6c2ecf1033
parentd25c03310fd3523392d37b88c23c48cf26836248 (diff)
downloadsqlalchemy-add9cdd6628f7663229c5e549afac7041a06cfd9.tar.gz
Ensure SQL Server default schema name not interpreted as dot-separated tokens
Fixed an issue in the :meth:`.Engine.table_names` method where it would feed the dialect's default schema name back into the dialect level table function, which in the case of SQL Server would interpret it as a dot-tokenized schema name as viewed by the mssql dialect, which would cause the method to fail in the case where the database username actually had a dot inside of it. In 1.3, this method is still used by the :meth:`.MetaData.reflect` function so is a prominent codepath. In 1.4, which is the current master development branch, this issue doesn't exist, both because :meth:`.MetaData.reflect` isn't using this method nor does the method pass the default schema name explicitly. The fix nonetheless guards against the default server name value returned by the dialect from being interpreted as dot-tokenized name under any circumstances by wrapping it in quoted_name(). Fixes: #4923 Change-Id: I821bd38ed89b767eaca0bdffee7f8ba3baf82560
-rw-r--r--doc/build/changelog/unreleased_13/4923.rst17
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py4
-rw-r--r--test/dialect/mssql/test_reflection.py12
3 files changed, 32 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_13/4923.rst b/doc/build/changelog/unreleased_13/4923.rst
new file mode 100644
index 000000000..e5318f51f
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4923.rst
@@ -0,0 +1,17 @@
+.. change::
+ :tags: bug, mssql
+ :tickets: 4923
+
+ Fixed an issue in the :meth:`.Engine.table_names` method where it would
+ feed the dialect's default schema name back into the dialect level table
+ function, which in the case of SQL Server would interpret it as a
+ dot-tokenized schema name as viewed by the mssql dialect, which would
+ cause the method to fail in the case where the database username actually
+ had a dot inside of it. In 1.3, this method is still used by the
+ :meth:`.MetaData.reflect` function so is a prominent codepath. In 1.4,
+ which is the current master development branch, this issue doesn't exist,
+ both because :meth:`.MetaData.reflect` isn't using this method nor does the
+ method pass the default schema name explicitly. The fix nonetheless
+ guards against the default server name value returned by the dialect from
+ being interpreted as dot-tokenized name under any circumstances by
+ wrapping it in quoted_name().
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index 2f24bb3f4..6c7b732ce 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -2428,7 +2428,9 @@ class MSDialect(default.DefaultDialect):
query = sql.text("SELECT schema_name()")
default_schema_name = connection.scalar(query)
if default_schema_name is not None:
- return util.text_type(default_schema_name)
+ # guard against the case where the default_schema_name is being
+ # fed back into a table reflection function.
+ return quoted_name(default_schema_name, quote=True)
else:
return self.schema_name
diff --git a/test/dialect/mssql/test_reflection.py b/test/dialect/mssql/test_reflection.py
index 24c4a6455..794588dce 100644
--- a/test/dialect/mssql/test_reflection.py
+++ b/test/dialect/mssql/test_reflection.py
@@ -421,6 +421,18 @@ class ReflectHugeViewTest(fixtures.TestBase):
class OwnerPlusDBTest(fixtures.TestBase):
+ def test_default_schema_name_not_interpreted_as_tokenized(self):
+ dialect = mssql.dialect()
+ dialect.server_version_info = base.MS_2014_VERSION
+
+ mock_connection = mock.Mock(scalar=lambda sql: "Jonah.The.Whale")
+ schema_name = dialect._get_default_schema_name(mock_connection)
+ eq_(schema_name, "Jonah.The.Whale")
+ eq_(
+ base._owner_plus_db(dialect, schema_name),
+ (None, "Jonah.The.Whale"),
+ )
+
def test_owner_database_pairs_dont_use_for_same_db(self):
dialect = mssql.dialect()