]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Gracefully skip isolation level if no row returned
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 7 Apr 2020 23:21:01 +0000 (19:21 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 7 Apr 2020 23:21:01 +0000 (19:21 -0400)
Fixed issue in MySQL dialect when connecting to a psuedo-MySQL database
such as that provided by ProxySQL, the up front check for isolation level
when it returns no row will not prevent the dialect from continuing to
connect. A warning is emitted that the isolation level could not be
detected.

Fixes: #5239
Change-Id: I4a240386a0d38bd90733819495ce50e37fe2234c

doc/build/changelog/unreleased_13/5239.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mysql/base.py
test/dialect/mysql/test_dialect.py

diff --git a/doc/build/changelog/unreleased_13/5239.rst b/doc/build/changelog/unreleased_13/5239.rst
new file mode 100644 (file)
index 0000000..6d0c720
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, mysql
+    :tickets: 5239
+
+    Fixed issue in MySQL dialect when connecting to a psuedo-MySQL database
+    such as that provided by ProxySQL, the up front check for isolation level
+    when it returns no row will not prevent the dialect from continuing to
+    connect. A warning is emitted that the isolation level could not be
+    detected.
+
index 26d751faaa8127a6f0f4146b20a4a83321c90fd2..54a13b550383bb8ba9a0419db935525ba3e930f4 100644 (file)
@@ -2297,7 +2297,14 @@ class MySQLDialect(default.DefaultDialect):
             cursor.execute("SELECT @@transaction_isolation")
         else:
             cursor.execute("SELECT @@tx_isolation")
-        val = cursor.fetchone()[0]
+        row = cursor.fetchone()
+        if row is None:
+            util.warn(
+                "Could not retrieve transaction isolation level for MySQL "
+                "connection."
+            )
+            raise NotImplementedError()
+        val = row[0]
         cursor.close()
         if util.py3k and isinstance(val, bytes):
             val = val.decode()
index c641411e181398bdaa6ac1a791fef5cea07e522e..cf0e0b02dd87d40354b725495daeed10c33d5af0 100644 (file)
@@ -194,6 +194,32 @@ class DialectTest(fixtures.TestBase):
             ):
                 engine.connect()
 
+    def test_no_default_isolation_level(self):
+        from sqlalchemy.testing import mock
+
+        engine = engines.testing_engine()
+
+        real_isolation_level = testing.db.dialect.get_isolation_level
+
+        def fake_isolation_level(connection):
+            connection = mock.Mock(
+                cursor=mock.Mock(
+                    return_value=mock.Mock(
+                        fetchone=mock.Mock(return_value=None)
+                    )
+                )
+            )
+            return real_isolation_level(connection)
+
+        with mock.patch.object(
+            engine.dialect, "get_isolation_level", fake_isolation_level
+        ):
+            with expect_warnings(
+                "Could not retrieve transaction isolation level for MySQL "
+                "connection."
+            ):
+                engine.connect()
+
     def test_autocommit_isolation_level(self):
         c = testing.db.connect().execution_options(
             isolation_level="AUTOCOMMIT"