]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Use SQL Server SERVERPROPERTY for version info w/ pyodbc
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 4 Oct 2016 15:17:26 +0000 (11:17 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 4 Oct 2016 15:17:26 +0000 (11:17 -0400)
Updated the server version info scheme for pyodbc to use SQL Server
SERVERPROPERTY(), rather than relying upon pyodbc.SQL_DBMS_VER, which
continues to be unreliable particularly with FreeTDS.

Change-Id: I4ff49ae13c8ff51bd764980131d41c18d73d87ce
Fixes: #3814
doc/build/changelog/changelog_10.rst
lib/sqlalchemy/connectors/pyodbc.py
lib/sqlalchemy/dialects/mssql/base.py
lib/sqlalchemy/dialects/mssql/pyodbc.py

index b3e76b4756611fc982e92ae685e12f6a2b231498..0ea3633b7a1fe2e8a1a1d98e778516bd0fc34671 100644 (file)
 .. changelog::
     :version: 1.0.16
 
+    .. change::
+        :tags: bug, mssql
+        :tickets: 3814
+        :versions: 1.1.0
+
+        Updated the server version info scheme for pyodbc to use SQL Server
+        SERVERPROPERTY(), rather than relying upon pyodbc.SQL_DBMS_VER, which
+        continues to be unreliable particularly with FreeTDS.
+
     .. change::
         :tags: bug, orm
         :tickets: 3800
index 68bbcc43560de306a6caeb841f19c5121759d7e9..1811229d70a304e8a4e6f11fcebabd373d23b425 100644 (file)
@@ -153,7 +153,6 @@ class PyODBCConnector(Connector):
         # run other initialization which asks for user name, etc.
         super(PyODBCConnector, self).initialize(connection)
 
-
     def _dbapi_version(self):
         if not self.dbapi:
             return ()
@@ -172,6 +171,9 @@ class PyODBCConnector(Connector):
         return vers
 
     def _get_server_version_info(self, connection):
+        # NOTE: this function is not reliable, particularly when
+        # freetds is in use.   Implement database-specific server version
+        # queries.
         dbapi_con = connection.connection
         version = []
         r = re.compile('[.\-]')
index 20b812731be28cd945c63e54257044f1f038e96b..9db025df788a507418547ee73a3fc80354bdf631 100644 (file)
@@ -571,6 +571,8 @@ from ...util import update_wrapper
 from . import information_schema as ischema
 
 # http://sqlserverbuilds.blogspot.com/
+MS_2016_VERSION = (13,)
+MS_2014_VERSION = (12,)
 MS_2012_VERSION = (11,)
 MS_2008_VERSION = (10,)
 MS_2005_VERSION = (9,)
@@ -1712,18 +1714,9 @@ class MSDialect(default.DefaultDialect):
 
     def _setup_version_attributes(self):
         if self.server_version_info[0] not in list(range(8, 17)):
-            # FreeTDS with version 4.2 seems to report here
-            # a number like "95.10.255".  Don't know what
-            # that is.  So emit warning.
-            # Use TDS Version 7.0 through 7.3, per the MS information here:
-            # https://msdn.microsoft.com/en-us/library/dd339982.aspx
-            # and FreeTDS information here (7.3 highest supported version):
-            # http://www.freetds.org/userguide/choosingtdsprotocol.htm
             util.warn(
-                "Unrecognized server version info '%s'.   Version specific "
-                "behaviors may not function properly.   If using ODBC "
-                "with FreeTDS, ensure TDS_VERSION 7.0 through 7.3, not "
-                "4.2, is configured in the FreeTDS configuration." %
+                "Unrecognized server version info '%s'.  Some SQL Server "
+                "features may not function properly." %
                 ".".join(str(x) for x in self.server_version_info))
         if self.server_version_info >= MS_2005_VERSION and \
                 'implicit_returning' not in self.__dict__:
index 45c091cfb88a9936b7da4af6993cd92d7bbccd63..30db94e49dcacc32796686497588f2e7f74b276d 100644 (file)
@@ -104,8 +104,9 @@ versioning.
 
 from .base import MSExecutionContext, MSDialect, VARBINARY
 from ...connectors.pyodbc import PyODBCConnector
-from ... import types as sqltypes, util
+from ... import types as sqltypes, util, exc
 import decimal
+import re
 
 
 class _ms_numeric_pyodbc(object):
@@ -269,4 +270,22 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect):
         self._need_decimal_fix = self.dbapi and \
             self._dbapi_version() < (2, 1, 8)
 
+    def _get_server_version_info(self, connection):
+        try:
+            raw = connection.scalar("SELECT  SERVERPROPERTY('ProductVersion')")
+        except exc.ProgrammingError:
+            # SQL Server docs indicate this function isn't present prior to
+            # 2008
+            return super(MSDialect_pyodbc, self).\
+                _get_server_version_info(connection)
+        else:
+            version = []
+            r = re.compile('[.\-]')
+            for n in r.split(raw):
+                try:
+                    version.append(int(n))
+                except ValueError:
+                    version.append(n)
+            return tuple(version)
+
 dialect = MSDialect_pyodbc