]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- basic sybase+pyodbc support. in particular this will impact freetds detection...
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 17 Mar 2010 17:14:47 +0000 (13:14 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 17 Mar 2010 17:14:47 +0000 (13:14 -0400)
lib/sqlalchemy/connectors/pyodbc.py
lib/sqlalchemy/dialects/mssql/pyodbc.py
lib/sqlalchemy/dialects/sybase/__init__.py
lib/sqlalchemy/dialects/sybase/base.py
lib/sqlalchemy/dialects/sybase/pyodbc.py
lib/sqlalchemy/dialects/sybase/pysybase.py

index ce8e84c33cb5c9f39e6856789854d50c01713091..e503135f70ed29cb8806e978f33883ce06185817 100644 (file)
@@ -19,6 +19,10 @@ class PyODBCConnector(Connector):
     # hold the desired driver name
     pyodbc_driver_name = None
     
+    # will be set to True after initialize()
+    # if the freetds.so is detected
+    freetds = False
+    
     @classmethod
     def dbapi(cls):
         return __import__('pyodbc')
@@ -76,6 +80,26 @@ class PyODBCConnector(Connector):
         else:
             return False
 
+    def initialize(self, connection):
+        # determine FreeTDS first.   can't issue SQL easily
+        # without getting unicode_statements/binds set up.
+        
+        pyodbc = self.dbapi
+
+        dbapi_con = connection.connection
+
+        self.freetds = bool(re.match(r".*libtdsodbc.*\.so",  dbapi_con.getinfo(pyodbc.SQL_DRIVER_NAME)))
+
+        # the "Py2K only" part here is theoretical.
+        # have not tried pyodbc + python3.1 yet.
+        # Py2K
+        self.supports_unicode_statements = not self.freetds
+        self.supports_unicode_binds = not self.freetds
+        # end Py2K
+        
+        # run other initialization which asks for user name, etc.
+        super(PyODBCConnector, self).initialize(connection)
+
     def _get_server_version_info(self, connection):
         dbapi_con = connection.connection
         version = []
index 9ef065b1a969626a43193d6ea04749b0d1944dcc..54b43320a35b9baeeef2584ed937f08cf4400738 100644 (file)
@@ -60,19 +60,4 @@ class MSDialect_pyodbc(PyODBCConnector, MSDialect):
         self.description_encoding = description_encoding
         self.use_scope_identity = self.dbapi and hasattr(self.dbapi.Cursor, 'nextset')
         
-    def initialize(self, connection):
-        super(MSDialect_pyodbc, self).initialize(connection)
-        pyodbc = self.dbapi
-        
-        dbapi_con = connection.connection
-        
-        self.freetds = re.match(r".*libtdsodbc.*\.so",  dbapi_con.getinfo(pyodbc.SQL_DRIVER_NAME))
-    
-        # the "Py2K only" part here is theoretical.
-        # have not tried pyodbc + python3.1 yet.
-        # Py2K
-        self.supports_unicode_statements = not self.freetds
-        self.supports_unicode_binds = not self.freetds
-        # end Py2K
-        
 dialect = MSDialect_pyodbc
index 573aedde32f90c6227dc337717dcc2b4124df479..4d9b07007a65faf082f6fcc2e1549db87e6d2a9e 100644 (file)
@@ -1,4 +1,4 @@
-from sqlalchemy.dialects.sybase import base, pysybase
+from sqlalchemy.dialects.sybase import base, pysybase, pyodbc
 
 
 from base import CHAR, VARCHAR, TIME, NCHAR, NVARCHAR,\
index b3ac455588b5bf1f762f3d0a59bcad9562009a8c..5d20faaf9d60e093ae6cd4a98be00d35bd0f5d92 100644 (file)
@@ -176,7 +176,19 @@ ischema_names = {
 
 class SybaseExecutionContext(default.DefaultExecutionContext):
     _enable_identity_insert = False
-
+    
+    def set_ddl_autocommit(self, connection, value):
+        """Must be implemented by subclasses to accommodate DDL executions.
+        
+        "connection" is the raw unwrapped DBAPI connection.   "value"
+        is True or False.  when True, the connection should be configured
+        such that a DDL can take place subsequently.  when False,
+        a DDL has taken place and the connection should be resumed
+        into non-autocommit mode.
+        
+        """
+        raise NotImplementedError()
+        
     def pre_exec(self):
         if self.isinsert:
             tbl = self.compiled.statement.table
@@ -192,7 +204,22 @@ class SybaseExecutionContext(default.DefaultExecutionContext):
                 self.cursor.execute("SET IDENTITY_INSERT %s ON" % 
                     self.dialect.identifier_preparer.format_table(tbl))
 
+        if self.isddl:
+            # TODO: to enhance this, we can detect "ddl in tran" on the
+            # database settings.  this error message should be improved to 
+            # include a note about that.
+            if not self.should_autocommit:
+                raise exc.InvalidRequestError("The Sybase dialect only supports "
+                                            "DDL in 'autocommit' mode at this time.")
+
+            self.root_connection.engine.logger.info("AUTOCOMMIT (Assuming no Sybase 'ddl in tran')")
+
+            self.set_ddl_autocommit(self.root_connection.connection.connection, True)
+            
+
     def post_exec(self):
+       if self.isddl:
+            self.set_ddl_autocommit(self.root_connection, False)
         
        if self._enable_identity_insert:
             self.cursor.execute(
index 642ae3219c415a0fced681f665a2ebc3b571f0ce..4f89fe33449a5b46f8430e50adfc27e38a4225f3 100644 (file)
@@ -10,7 +10,11 @@ from sqlalchemy.dialects.sybase.base import SybaseDialect, SybaseExecutionContex
 from sqlalchemy.connectors.pyodbc import PyODBCConnector
 
 class SybaseExecutionContext_pyodbc(SybaseExecutionContext):
-    pass
+    def set_ddl_autocommit(self, connection, value):
+        if value:
+            connection.autocommit = True
+        else:
+            connection.autocommit = False
 
 
 class SybaseDialect_pyodbc(PyODBCConnector, SybaseDialect):
index 195407384dbcb6fe42f645d3b67dc7677bc26319..200ce11a2419df1b252bcfb47fea71d2ec026c86 100644 (file)
@@ -20,6 +20,14 @@ from sqlalchemy.dialects.sybase.base import SybaseDialect, \
 
 
 class SybaseExecutionContext_pysybase(SybaseExecutionContext):
+
+    def set_ddl_autocommit(self, dbapi_connection, value):
+        if value:
+            # call commit() on the Sybase connection directly,
+            # to avoid any side effects of calling a Connection 
+            # transactional method inside of pre_exec()
+            dbapi_connection.commit()
+
     def pre_exec(self):
         SybaseExecutionContext.pre_exec(self)
 
@@ -28,18 +36,6 @@ class SybaseExecutionContext_pysybase(SybaseExecutionContext):
                 param["@" + key] = param[key]
                 del param[key]
 
-        if self.isddl:
-            # TODO: to enhance this, we can detect "ddl in tran" on the
-            # database settings.  this error message should be improved to 
-            # include a note about that.
-            if not self.should_autocommit:
-                raise exc.InvalidRequestError("The Sybase dialect only supports "
-                                            "DDL in 'autocommit' mode at this time.")
-            # call commit() on the Sybase connection directly,
-            # to avoid any side effects of calling a Connection 
-            # transactional method inside of pre_exec()
-            self.root_connection.engine.logger.info("COMMIT (Assuming no Sybase 'ddl in tran')")
-            self.root_connection.connection.commit()
 
 class SybaseSQLCompiler_pysybase(SybaseSQLCompiler):
     def bindparam_string(self, name):