]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
run-time selectable DB-API modules for mssql [ticket:419]
authorRick Morrison <rickmorrison@gmail.com>
Wed, 14 Feb 2007 23:58:51 +0000 (23:58 +0000)
committerRick Morrison <rickmorrison@gmail.com>
Wed, 14 Feb 2007 23:58:51 +0000 (23:58 +0000)
preliminary support for pyodbc

CHANGES
lib/sqlalchemy/databases/mssql.py

diff --git a/CHANGES b/CHANGES
index bd0a8298ee370f9c7845518e6b57d4091deff8a2..525610a7525861e5a445942a2139f61ac0319050 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -61,6 +61,9 @@
   - better support for NVARCHAR types added [ticket:298]
   - fix for commit logic on pymssql
   - fix for query.get() with schema [ticket:456]
+  - fix for non-integer relationships [ticket:473]
+  - DB-API module now selectable at run-time [ticket:419]
+  - preliminary support for pyodbc (Yay!) [ticket:419]
   
 0.3.4
 - general:
index 63e04cef7a4aa3ed74ab117e8f684ab0975d42fc..a0ae9b967e18d08fa661782454784957165a1694 100644 (file)
@@ -44,7 +44,11 @@ import sqlalchemy.ansisql as ansisql
 import sqlalchemy.types as sqltypes
 import sqlalchemy.exceptions as exceptions
 
-try:
+dbmodule = None
+dialect = None
+
+def use_adodbapi():
+    global dbmodule, connect, make_connect_string, do_commit, sane_rowcount, dialect
     import adodbapi as dbmodule
     # ADODBAPI has a non-standard Connection method
     connect = dbmodule.Connection
@@ -52,23 +56,61 @@ try:
         [["Provider=SQLOLEDB;Data Source=%s;User Id=%s;Password=%s;Initial Catalog=%s" % (
             keys.get("host"), keys.get("user"), keys.get("password"), keys.get("database"))], {}]
     sane_rowcount = True
-except:
-    try:
-        import pymssql as dbmodule
-        connect = dbmodule.connect
-        # pymmsql doesn't have a Binary method.  we use string
-        dbmodule.Binary = lambda st: str(st)
-        def make_connect_string(keys):
-            if keys.get('port'):
-                # pymssql expects port as host:port, not a separate arg
-                keys['host'] = ''.join([keys.get('host', ''), ':', str(keys['port'])])
-                del keys['port'] 
-            return [[], keys]
-    except:
-        dbmodule = None
-        make_connect_string = lambda keys: [[],{}]
+    dialect = MSSQLDialect
+    
+def use_pymssql():
+    global dbmodule, connect, make_connect_string, do_commit, sane_rowcount, dialect
+    import pymssql as dbmodule
+    connect = dbmodule.connect
+    # pymmsql doesn't have a Binary method.  we use string
+    dbmodule.Binary = lambda st: str(st)
+    def make_connect_string(keys):
+        if keys.get('port'):
+            # pymssql expects port as host:port, not a separate arg
+            keys['host'] = ''.join([keys.get('host', ''), ':', str(keys['port'])])
+            del keys['port'] 
+        return [[], keys]
+    do_commit = True
     sane_rowcount = False
+    dialect = PyMSSQLDialect
     
+def use_pyodbc():
+    global dbmodule, connect, make_connect_string, do_commit, sane_rowcount, dialect
+    import pyodbc as dbmodule
+    connect = dbmodule.connect
+    make_connect_string = lambda keys: \
+        [["Driver={SQL Server};Server=%s;UID=%s;PWD=%s;Database=%s" % (
+            keys.get("host"), keys.get("user"), keys.get("password"), keys.get("database"))], {}]
+    do_commit = True
+    sane_rowcount = True
+    dialect = MSSQLDialect # XXX - find out whether this needs to be tweaked for pyodbc
+    import warnings
+    warnings.warn('pyodbc support in sqlalchemy.databases.mssql is extremely experimental - use at your own risk.')
+
+def use_default():
+    import_errors = []
+    def try_use(f):
+        try:
+            f()
+        except ImportError, e:
+            import_errors.append(e)
+            return False
+        else:
+            return True
+    for f in [
+            # XXX - is this the best default ordering? For now, it retains the current (2007-Jan-11) 
+            # default - that is, adodbapi first, pymssql second - and adds pyodbc as a third option.
+            # However, my tests suggest that the exact opposite order may be the best!
+            use_adodbapi,
+            use_pymssql,
+            use_pyodbc,
+        ]:
+        if try_use(f):
+            return dbmodule # informational return, so the user knows what he's using.
+    else:
+        raise ImportError(import_errors)
+        
+
 class MSNumeric(sqltypes.Numeric):
     def convert_result_value(self, value, dialect):
         return value
@@ -244,7 +286,7 @@ def descriptor():
 class MSSQLExecutionContext(default.DefaultExecutionContext):
     def __init__(self, dialect):
         self.IINSERT = self.HASIDENT = False
-       super(MSSQLExecutionContext, self).__init__(dialect)
+        super(MSSQLExecutionContext, self).__init__(dialect)
     
     def pre_exec(self, engine, proxy, compiled, parameters, **kwargs):
         """ MS-SQL has a special mode for inserting non-NULL values into IDENTITY columns. Activate it if the feature is turned on and needed. """
@@ -280,7 +322,7 @@ class MSSQLExecutionContext(default.DefaultExecutionContext):
 
 class MSSQLDialect(ansisql.ANSIDialect):
     def __init__(self, module=None, auto_identity_insert=False, encoding=None, **params):
-        self.module = module or dbmodule
+        self.module = module or dbmodule or use_default()
         self.auto_identity_insert = auto_identity_insert
         ansisql.ANSIDialect.__init__(self, encoding=encoding, **params)
         self.set_default_schema_name("dbo")
@@ -605,7 +647,5 @@ class MSSQLIdentifierPreparer(ansisql.ANSIIdentifierPreparer):
         #TODO: determin MSSQL's case folding rules
         return value
 
-if dbmodule and dbmodule.__name__ == 'adodbapi':
-       dialect = MSSQLDialect
-else:
-       dialect = PyMSSQLDialect
+
+use_default()