]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Get MySQL version info from @@version
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 2 Mar 2018 20:08:08 +0000 (15:08 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 3 Mar 2018 21:16:43 +0000 (16:16 -0500)
MySQL dialects now query the server version using ``SELECT @@version``
explicitly to the server to ensure we are getting the correct version
information back.   Proxy servers like MaxScale interfere with the value
that is passed to the DBAPI's connection.server_version value so this
is no longer reliable.

Change-Id: Iafd39be8c9bf1982d58b34cc997ae1016ad6c48c
Fixes: #4205
(cherry picked from commit 9ba77e8d3b682bff89fdab5e80271a96a52fe8c8)
(cherry picked from commit 5c1ebbc3706c810f936d9e252ee5d16800e561ea)

doc/build/changelog/unreleased_11/4205.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/dialects/mysql/cymysql.py
lib/sqlalchemy/dialects/mysql/mysqlconnector.py
lib/sqlalchemy/dialects/mysql/mysqldb.py
lib/sqlalchemy/dialects/mysql/oursql.py

diff --git a/doc/build/changelog/unreleased_11/4205.rst b/doc/build/changelog/unreleased_11/4205.rst
new file mode 100644 (file)
index 0000000..91b276b
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, mysql
+    :tickets: 4205
+    :versions: 1.2.5, 1.3.0b1
+
+    MySQL dialects now query the server version using ``SELECT @@version``
+    explicitly to the server to ensure we are getting the correct version
+    information back.   Proxy servers like MaxScale interfere with the value
+    that is passed to the DBAPI's connection.server_version value so this
+    is no longer reliable.
index a304d04f6848c6f45738a1d2dca3e77bf32225f0..b5d4cb4b7f943620f0ce75798cf6bde1e9fa5866 100644 (file)
@@ -1750,6 +1750,27 @@ class MySQLDialect(default.DefaultDialect):
             val = val.decode()
         return val.upper().replace("-", " ")
 
+    def _get_server_version_info(self, connection):
+        # get database server version info explicitly over the wire
+        # to avoid proxy servers like MaxScale getting in the
+        # way with their own values, see #4205
+        dbapi_con = connection.connection
+        cursor = dbapi_con.cursor()
+        cursor.execute("SELECT VERSION()")
+        val = cursor.fetchone()[0]
+        cursor.close()
+        if util.py3k and isinstance(val, bytes):
+            val = val.decode()
+
+        version = []
+        r = re.compile(r'[.\-]')
+        for n in r.split(val):
+            try:
+                version.append(int(n))
+            except ValueError:
+                version.append(n)
+        return tuple(version)
+
     def do_commit(self, dbapi_connection):
         """Execute a COMMIT."""
 
@@ -1921,6 +1942,9 @@ class MySQLDialect(default.DefaultDialect):
 
     @property
     def _mariadb_normalized_version_info(self):
+        # MariaDB's wire-protocol prepends the server_version with
+        # the string "5.5"; now that we use @@version we no longer see this.
+
         if self._is_mariadb:
             idx = self.server_version_info.index('MariaDB')
             return self.server_version_info[idx - 3: idx]
index 0738e8fdd874322def0107fd0274a94f6d06f821..d142905948fbd8db27d542f2822be2103d923623 100644 (file)
@@ -56,17 +56,6 @@ class MySQLDialect_cymysql(MySQLDialect_mysqldb):
     def dbapi(cls):
         return __import__('cymysql')
 
-    def _get_server_version_info(self, connection):
-        dbapi_con = connection.connection
-        version = []
-        r = re.compile(r'[.\-]')
-        for n in r.split(dbapi_con.server_version):
-            try:
-                version.append(int(n))
-            except ValueError:
-                version.append(n)
-        return tuple(version)
-
     def _detect_charset(self, connection):
         return connection.connection.charset
 
index bd732303f8c49f8671b6313c225056066feb441f..117115888bf726a6673b91ff64f3530f7cc26673 100644 (file)
@@ -161,11 +161,6 @@ class MySQLDialect_mysqlconnector(MySQLDialect):
     def _mysqlconnector_double_percents(self):
         return not util.py3k and self._mysqlconnector_version_info < (2, 0)
 
-    def _get_server_version_info(self, connection):
-        dbapi_con = connection.connection
-        version = dbapi_con.get_server_version()
-        return tuple(version)
-
     def _detect_charset(self, connection):
         return connection.connection.charset
 
index 33cbd8f3af93627c52915d35a3ab75cd64883104..3da64a4913da02eaedd4c7ebb8cb50d9f69b6098 100644 (file)
@@ -173,17 +173,6 @@ class MySQLDialect_mysqldb(MySQLDialect):
             opts['client_flag'] = client_flag
         return [[], opts]
 
-    def _get_server_version_info(self, connection):
-        dbapi_con = connection.connection
-        version = []
-        r = re.compile(r'[.\-]')
-        for n in r.split(dbapi_con.get_server_info()):
-            try:
-                version.append(int(n))
-            except ValueError:
-                version.append(n)
-        return tuple(version)
-
     def _extract_error_code(self, exception):
         return exception.args[0]
 
index 089f872f3a1bb18f59b1f9c347d564a44a708510..67dbb7cf233a17534e9bfbc6034b5ea00f15b1db 100644 (file)
@@ -220,17 +220,6 @@ class MySQLDialect_oursql(MySQLDialect):
 
         return [[], opts]
 
-    def _get_server_version_info(self, connection):
-        dbapi_con = connection.connection
-        version = []
-        r = re.compile(r'[.\-]')
-        for n in r.split(dbapi_con.server_info):
-            try:
-                version.append(int(n))
-            except ValueError:
-                version.append(n)
-        return tuple(version)
-
     def _extract_error_code(self, exception):
         return exception.errno