From: Mike Bayer Date: Tue, 7 Apr 2020 23:21:01 +0000 (-0400) Subject: Gracefully skip isolation level if no row returned X-Git-Tag: rel_1_4_0b1~412 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=978755e851e505e2715e71efcb51b0904ded9f80;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Gracefully skip isolation level if no row returned 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 --- diff --git a/doc/build/changelog/unreleased_13/5239.rst b/doc/build/changelog/unreleased_13/5239.rst new file mode 100644 index 0000000000..6d0c720870 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5239.rst @@ -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. + diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 26d751faaa..54a13b5503 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -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() diff --git a/test/dialect/mysql/test_dialect.py b/test/dialect/mysql/test_dialect.py index c641411e18..cf0e0b02dd 100644 --- a/test/dialect/mysql/test_dialect.py +++ b/test/dialect/mysql/test_dialect.py @@ -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"