diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-03-17 13:14:47 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-03-17 13:14:47 -0400 |
commit | b81e9741ba26f2740725c9d403d116284af7d7a4 (patch) | |
tree | 5b8792ceca125ac46e8055db997ce9e6e82bba11 | |
parent | 893f6563730f4d2460dd266a8fea40a38c678794 (diff) | |
download | sqlalchemy-b81e9741ba26f2740725c9d403d116284af7d7a4.tar.gz |
- basic sybase+pyodbc support. in particular this will impact freetds detection for MS-SQL as well.
-rw-r--r-- | lib/sqlalchemy/connectors/pyodbc.py | 24 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/mssql/pyodbc.py | 15 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sybase/__init__.py | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sybase/base.py | 29 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sybase/pyodbc.py | 6 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sybase/pysybase.py | 20 |
6 files changed, 66 insertions, 30 deletions
diff --git a/lib/sqlalchemy/connectors/pyodbc.py b/lib/sqlalchemy/connectors/pyodbc.py index ce8e84c33..e503135f7 100644 --- a/lib/sqlalchemy/connectors/pyodbc.py +++ b/lib/sqlalchemy/connectors/pyodbc.py @@ -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 = [] diff --git a/lib/sqlalchemy/dialects/mssql/pyodbc.py b/lib/sqlalchemy/dialects/mssql/pyodbc.py index 9ef065b1a..54b43320a 100644 --- a/lib/sqlalchemy/dialects/mssql/pyodbc.py +++ b/lib/sqlalchemy/dialects/mssql/pyodbc.py @@ -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 diff --git a/lib/sqlalchemy/dialects/sybase/__init__.py b/lib/sqlalchemy/dialects/sybase/__init__.py index 573aedde3..4d9b07007 100644 --- a/lib/sqlalchemy/dialects/sybase/__init__.py +++ b/lib/sqlalchemy/dialects/sybase/__init__.py @@ -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,\ diff --git a/lib/sqlalchemy/dialects/sybase/base.py b/lib/sqlalchemy/dialects/sybase/base.py index b3ac45558..5d20faaf9 100644 --- a/lib/sqlalchemy/dialects/sybase/base.py +++ b/lib/sqlalchemy/dialects/sybase/base.py @@ -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( diff --git a/lib/sqlalchemy/dialects/sybase/pyodbc.py b/lib/sqlalchemy/dialects/sybase/pyodbc.py index 642ae3219..4f89fe334 100644 --- a/lib/sqlalchemy/dialects/sybase/pyodbc.py +++ b/lib/sqlalchemy/dialects/sybase/pyodbc.py @@ -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): diff --git a/lib/sqlalchemy/dialects/sybase/pysybase.py b/lib/sqlalchemy/dialects/sybase/pysybase.py index 195407384..200ce11a2 100644 --- a/lib/sqlalchemy/dialects/sybase/pysybase.py +++ b/lib/sqlalchemy/dialects/sybase/pysybase.py @@ -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): |