# 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')
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 = []
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
-from sqlalchemy.dialects.sybase import base, pysybase
+from sqlalchemy.dialects.sybase import base, pysybase, pyodbc
from base import CHAR, VARCHAR, TIME, NCHAR, NVARCHAR,\
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
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(
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):
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)
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):