]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
catch exception for system_views also
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 15 Sep 2022 12:42:34 +0000 (08:42 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 15 Sep 2022 12:42:34 +0000 (08:42 -0400)
Fixed yet another regression in SQL Server isolation level fetch (see
:ticket:`8231`, :ticket:`8475`), this time with "Microsoft Dynamics CRM
Database via Azure Active Directory", which apparently lacks the
``system_views`` view entirely. Error catching has been extended that under
no circumstances will this method ever fail, provided database connectivity
is present.

Fixes: #8525
Change-Id: I76a429e3329926069a0367d2e77ca1124b9a059d

doc/build/changelog/unreleased_14/8525.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mssql/base.py
test/dialect/mssql/test_engine.py

diff --git a/doc/build/changelog/unreleased_14/8525.rst b/doc/build/changelog/unreleased_14/8525.rst
new file mode 100644 (file)
index 0000000..3031ec3
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, mssql, regression
+    :tickets: 8525
+
+    Fixed yet another regression in SQL Server isolation level fetch (see
+    :ticket:`8231`, :ticket:`8475`), this time with "Microsoft Dynamics CRM
+    Database via Azure Active Directory", which apparently lacks the
+    ``system_views`` view entirely. Error catching has been extended that under
+    no circumstances will this method ever fail, provided database connectivity
+    is present.
\ No newline at end of file
index 82a5bb6f7849cca1c785ff288502b6c95f1c23db..c7e88a643241a82c500ead7b116c3c7989403431 100644 (file)
@@ -2995,10 +2995,13 @@ class MSDialect(default.DefaultDialect):
 
     def get_isolation_level(self, dbapi_connection):
         cursor = dbapi_connection.cursor()
+        view_name = "sys.system_views"
         try:
             cursor.execute(
-                "SELECT name FROM sys.system_views WHERE name IN "
-                "('dm_exec_sessions', 'dm_pdw_nodes_exec_sessions')"
+                (
+                    "SELECT name FROM {} WHERE name IN "
+                    "('dm_exec_sessions', 'dm_pdw_nodes_exec_sessions')"
+                ).format(view_name)
             )
             row = cursor.fetchone()
             if not row:
@@ -3009,31 +3012,30 @@ class MSDialect(default.DefaultDialect):
 
             view_name = "sys.{}".format(row[0])
 
-            try:
-                cursor.execute(
-                    """
-                        SELECT CASE transaction_isolation_level
-                        WHEN 0 THEN NULL
-                        WHEN 1 THEN 'READ UNCOMMITTED'
-                        WHEN 2 THEN 'READ COMMITTED'
-                        WHEN 3 THEN 'REPEATABLE READ'
-                        WHEN 4 THEN 'SERIALIZABLE'
-                        WHEN 5 THEN 'SNAPSHOT' END
-                        AS TRANSACTION_ISOLATION_LEVEL
-                        FROM {}
-                        where session_id = @@SPID
-                    """.format(
-                        view_name
-                    )
+            cursor.execute(
+                """
+                    SELECT CASE transaction_isolation_level
+                    WHEN 0 THEN NULL
+                    WHEN 1 THEN 'READ UNCOMMITTED'
+                    WHEN 2 THEN 'READ COMMITTED'
+                    WHEN 3 THEN 'REPEATABLE READ'
+                    WHEN 4 THEN 'SERIALIZABLE'
+                    WHEN 5 THEN 'SNAPSHOT' END
+                    AS TRANSACTION_ISOLATION_LEVEL
+                    FROM {}
+                    where session_id = @@SPID
+                """.format(
+                    view_name
                 )
-            except self.dbapi.Error as err:
-                raise NotImplementedError(
-                    "Can't fetch isolation level;  encountered error {} when "
-                    'attempting to query the "{}" view.'.format(err, view_name)
-                ) from err
-            else:
-                row = cursor.fetchone()
-                return row[0].upper()
+            )
+        except self.dbapi.Error as err:
+            raise NotImplementedError(
+                "Can't fetch isolation level;  encountered error {} when "
+                'attempting to query the "{}" view.'.format(err, view_name)
+            ) from err
+        else:
+            row = cursor.fetchone()
+            return row[0].upper()
         finally:
             cursor.close()
 
index 28c0fb5328ce60a2b8034d12080129068fa11905..3fb078ef4ca5e96896ec85132d96fbf9880e32fd 100644 (file)
@@ -647,7 +647,12 @@ class RealIsolationLevelTest(fixtures.TestBase):
 
 
 class IsolationLevelDetectTest(fixtures.TestBase):
-    def _fixture(self, view_result, simulate_perm_failure=False):
+    def _fixture(
+        self,
+        view_result,
+        simulate_perm_failure=False,
+        simulate_no_system_views=False,
+    ):
         class Error(Exception):
             pass
 
@@ -662,8 +667,13 @@ class IsolationLevelDetectTest(fixtures.TestBase):
         ):
             result.clear()
             if "SELECT name FROM sys.system_views" in stmt:
-                if view_result:
-                    result.append((view_result,))
+                if simulate_no_system_views:
+                    raise dialect.dbapi.Error(
+                        "SQL Server simulated no system_views error"
+                    )
+                else:
+                    if view_result:
+                        result.append((view_result,))
             elif re.match(
                 ".*SELECT CASE transaction_isolation_level.*FROM sys.%s"
                 % (view_result,),
@@ -709,6 +719,23 @@ class IsolationLevelDetectTest(fixtures.TestBase):
             connection,
         )
 
+    @testing.combinations(True, False)
+    def test_no_system_views(self, simulate_perm_failure_also):
+        dialect, connection = self._fixture(
+            "dm_pdw_nodes_exec_sessions",
+            simulate_perm_failure=simulate_perm_failure_also,
+            simulate_no_system_views=True,
+        )
+
+        assert_raises_message(
+            NotImplementedError,
+            r"Can\'t fetch isolation level;  encountered error SQL Server "
+            r"simulated no system_views error when attempting to query the "
+            r'"sys.system_views" view.',
+            dialect.get_isolation_level,
+            connection,
+        )
+
     def test_dont_have_table_perms(self):
         dialect, connection = self._fixture(
             "dm_pdw_nodes_exec_sessions", simulate_perm_failure=True