diff --git a/doc/build/changelog/unreleased_13/4624.rst b/doc/build/changelog/unreleased_13/4624.rst new file mode 100644 index 0000000000..4e8fc4921f --- /dev/null +++ b/doc/build/changelog/unreleased_13/4624.rst @@ -0,0 +1,10 @@ +.. change:: + :tags: bug, mysql + :tickets: 4624 + + Enhanced MySQL/MariaDB version string parsing to accommodate for exotic + MariaDB version strings where the "MariaDB" word is embedded among other + alphanumeric characters such as "MariaDBV1". This detection is critical in + order to correctly accomodate for API features that have split between MySQL + and MariaDB such as the "transaction_isolation" system variable. + diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 5725b1f05b..9d83541ae4 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -2193,13 +2193,20 @@ class MySQLDialect(default.DefaultDialect): if util.py3k and isinstance(val, bytes): val = val.decode() + return self._parse_server_version(val) + + def _parse_server_version(self, val): version = [] r = re.compile(r"[.\-]") for n in r.split(val): try: version.append(int(n)) except ValueError: - version.append(n) + mariadb = re.match(r"(.*)(MariaDB)(.*)", n) + if mariadb: + version.extend(g for g in mariadb.groups() if g) + else: + version.append(n) return tuple(version) def do_commit(self, dbapi_connection): diff --git a/test/dialect/mysql/test_dialect.py b/test/dialect/mysql/test_dialect.py index 8d0d60f1b5..3005e459b9 100644 --- a/test/dialect/mysql/test_dialect.py +++ b/test/dialect/mysql/test_dialect.py @@ -192,20 +192,35 @@ class DialectTest(fixtures.TestBase): class ParseVersionTest(fixtures.TestBase): def test_mariadb_normalized_version(self): - for expected, version in [ - ((10, 2, 7), (10, 2, 7, "MariaDB")), - ((10, 2, 7), (5, 6, 15, 10, 2, 7, "MariaDB")), - ((10, 2, 10), (10, 2, 10, "MariaDB")), - ((5, 7, 20), (5, 7, 20)), - ((5, 6, 15), (5, 6, 15)), + for expected, raw_version, version, is_mariadb in [ + ((10, 2, 7), "10.2.7-MariaDB", (10, 2, 7, "MariaDB"), True), + ( + (10, 2, 7), + "5.6.15.10.2.7-MariaDB", + (5, 6, 15, 10, 2, 7, "MariaDB"), + True, + ), + ((10, 2, 10), "10.2.10-MariaDB", (10, 2, 10, "MariaDB"), True), + ((5, 7, 20), "5.7.20", (5, 7, 20), False), + ((5, 6, 15), "5.6.15", (5, 6, 15), False), ( (10, 2, 6), + "10.2.6.MariaDB.10.2.6+maria~stretch-log", (10, 2, 6, "MariaDB", 10, 2, "6+maria~stretch", "log"), + True, + ), + ( + (10, 1, 9), + "10.1.9-MariaDBV1.0R050D002-20170809-1522", + (10, 1, 9, "MariaDB", "V1", "0R050D002", 20170809, 1522), + True, ), ]: dialect = mysql.dialect() + eq_(dialect._parse_server_version(raw_version), version) dialect.server_version_info = version eq_(dialect._mariadb_normalized_version_info, expected) + assert dialect._is_mariadb is is_mariadb def test_mariadb_check_warning(self):