summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-03-17 13:14:47 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-03-17 13:14:47 -0400
commitb81e9741ba26f2740725c9d403d116284af7d7a4 (patch)
tree5b8792ceca125ac46e8055db997ce9e6e82bba11
parent893f6563730f4d2460dd266a8fea40a38c678794 (diff)
downloadsqlalchemy-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.py24
-rw-r--r--lib/sqlalchemy/dialects/mssql/pyodbc.py15
-rw-r--r--lib/sqlalchemy/dialects/sybase/__init__.py2
-rw-r--r--lib/sqlalchemy/dialects/sybase/base.py29
-rw-r--r--lib/sqlalchemy/dialects/sybase/pyodbc.py6
-rw-r--r--lib/sqlalchemy/dialects/sybase/pysybase.py20
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):