From: Mike Bayer Date: Sun, 21 May 2017 19:28:00 +0000 (-0400) Subject: Prevent SQL server isolation level from failing X-Git-Tag: rel_1_2_0b1~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2574ca4b215cb06720d3ff4352d87ce87ebdd160;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Prevent SQL server isolation level from failing Fixed bug where SQL Server transaction isolation must be fetched from a different view when using Azure data warehouse, the query is now attempted against both views and then a NotImplemented is raised unconditionally if failure continues to provide the best resiliency against future arbitrary API changes in new SQL Server versions. Change-Id: I621b5089febe8ace136428fa133fde1a7e21cda4 Fixes: #3994 --- diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 1996f90ddc..9fba02c320 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,17 @@ .. changelog:: :version: 1.1.11 + .. change:: 3994 + :tags: bug, mssql + :tickets: 3994 + + Fixed bug where SQL Server transaction isolation must be fetched + from a different view when using Azure data warehouse, the query + is now attempted against both views and then a NotImplemented + is raised unconditionally if failure continues to provide the + best resiliency against future arbitrary API changes in new + SQL Server versions. + .. changelog:: :version: 1.1.10 :released: Friday, May 19, 2017 diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index 814fc77993..0399cbd90d 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -1786,21 +1786,36 @@ class MSDialect(default.DefaultDialect): raise NotImplementedError( "Can't fetch isolation level prior to SQL Server 2005") - cursor = connection.cursor() - 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 sys.dm_exec_sessions - where session_id = @@SPID - """) - val = cursor.fetchone()[0] - cursor.close() - return val.upper() + views = ("sys.dm_exec_sessions", "sys.dm_pdw_nodes_exec_sessions") + for view in views: + cursor = connection.cursor() + 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 %s + where session_id = @@SPID + """ % view) + val = cursor.fetchone()[0] + except self.dbapi.Error as err: + continue + else: + return val.upper() + finally: + cursor.close() + + util.warn( + "Could not fetch transaction isolation level, " + "tried views: %s; final error was: %s" % (views, err)) + raise NotImplementedError( + "Can't fetch isolation level on this particular " + "SQL Server version" + ) def initialize(self, connection): super(MSDialect, self).initialize(connection)