dabo Commit
Revision 7209
Date: 2012-07-25 06:43:41 -0700 (Wed, 25 Jul 2012)
Author: Jacekk
Trac: http://trac.dabodev.com/changeset/7209

Changed:
U   trunk/dabo/db/dbMsSQL.py

Log:
Several improvements in dbMsSQL module:
- added "charset" parameter supported in new pymssql driver branch to resolve 
non-ascii charsets issue;
- added filtering numeric columns in dictionary cursors;
- improved SQL Schema query (I noticed very poor performance on SQL 2008 
Server);
- fix lastrowid attribute referred to class instance instead of cursor object.

Diff:
Modified: trunk/dabo/db/dbMsSQL.py
===================================================================
--- trunk/dabo/db/dbMsSQL.py    2012-07-23 16:16:33 UTC (rev 7208)
+++ trunk/dabo/db/dbMsSQL.py    2012-07-25 13:43:41 UTC (rev 7209)
@@ -16,18 +16,15 @@
                self.dbModuleName = "pymssql"
                self.useTransactions = True  # this does not appear to be 
required
                import pymssql
+               self.dbapi = pymssql
 
 
        def getConnection(self, connectInfo, forceCreate=False, **kwargs):
                """
-               The pymssql module requires the connection be created for the 
FreeTDS libraries first.  Therefore, the
-               DSN is really the name of the connection for FreeTDS ::
-                       
+               The pymssql module requires the connection be created for the 
FreeTDS libraries first.
+               Therefore, the DSN is really the name of the connection for 
FreeTDS :
                  __init__(self, dsn, user, passwd, database = None, strip = 0)
-               
                """
-               import pymssql
-
                port = ustr(connectInfo.Port)
                if not port or port == "None":
                        port = 1433
@@ -38,29 +35,39 @@
 
                # hack to make this work.  I am sure there is a better way.
                self.database = database
+               # Hack to make new driver working with non us-ascii encoding.
+               if "charset" not in kwargs and self.dbapi.__version__ >= 
"2.0.0":
+                       kwargs["charset"] = self.Encoding
 
-               self._connection = pymssql.connect(host=host, user=user, 
password=password,
+               self._connection = self.dbapi.connect(host=host, user=user, 
password=password,
                                database=database, **kwargs)
                return self._connection
 
 
        def getDictCursorClass(self):
-               """Currently this is not working completely"""
-               import pymssql
-
-               if pymssql.__version__ >= "2.0.0":
-                       class ConCursor(pymssql.Cursor):
+               """Since there are two versions of driver package we support 
both,
+               deprecated and new one.
+               """
+               if self.dbapi.__version__ >= "2.0.0":
+                       class ConCursor(self.dbapi.Cursor):
                                def __init__(self, *args, **kwargs):
-                                       # pymssql requires an additional param 
to its __init__() method
+                                       # pymssql requires an additional param 
to be passed
+                                       # to its __init__() method
                                        kwargs["as_dict"] = True
                                        super(ConCursor, self).__init__(*args, 
**kwargs)
+                               def fetchall(self):
+                                       # In dictionary mode both column 
numbers and names are used
+                                       # as keys. We need to filter them and 
leave name based keys only.
+                                       return tuple([{col: row[col] for col in 
row if type(col) != int}
+                                                       for row in 
super(ConCursor, self).fetchall()])
                else:
-                       class ConCursor(pymssql.pymssqlCursor):
+                       class ConCursor(self.dbapi.pymssqlCursor):
                                def __init__(self, *args, **kwargs):
-                                       # pymssql requires an additional param 
to its __init__() method
+                                       # pymssql requires an additional param 
to be passed
+                                       # to its __init__() method
                                        kwargs["as_dict"] = True
                                        super(ConCursor, self).__init__(*args, 
**kwargs)
-                               if not hasattr(pymssql.pymssqlCursor, 
"connection"):
+                               if not hasattr(self.dbapi.pymssqlCursor, 
"connection"):
                                        def _getconn(self):
                                                return self._source
                                        # pymssql doesn't supply this optional 
dbapi attribute, so create it here.
@@ -74,7 +81,7 @@
                # wrap the result in single quotes
                sl = "\\"
                qt = "\'"
-               return qt + val.replace(sl, sl+sl).replace(qt, sl+qt) + qt
+               return qt + val.replace(sl, sl + sl).replace(qt, sl + qt) + qt
 
 
        def formatDateTime(self, val):
@@ -132,8 +139,9 @@
                        "CHAR": "C",
                        "DATE": "D",
                        "DATETIME": "T",
+                       "DATETIME2": "T",
                        "DECIMAL": "N",
-                       "DOUBLE": "G",  ## G maps to Long (INT), but this could 
be wrong if it is supposed to be a double float.
+                       "DOUBLE": "G", ## G maps to Long (INT), but this could 
be wrong if it is supposed to be a double float.
                        "ENUM": "C",
                        "FLOAT": "F",
                        "GEOMETRY": "?",
@@ -194,35 +202,33 @@
 select COLUMN_NAME,
        DATA_TYPE
   from INFORMATION_SCHEMA.COLUMNS
- where table_catalog = '%(db)s' and
-     table_name = '%(table)s' and
-     table_schema = '%(schema)s'
+ where table_catalog = %s and
+       table_schema = %s and
+     table_name = %s
  order by ORDINAL_POSITION """
 
-               cursor.execute(sql % {'table': tableName, 'db': dbName, 
'schema': tableSchema})
+               cursor.execute(sql, (dbName, tableSchema, tableName))
                fieldDefs = cursor.getDataSet()
 
                sql = """
-select COLUMN_NAME
-  from information_schema.Constraint_Column_Usage CCU
-  join information_schema.TABLE_CONSTRAINTS TC
-    on CCU.CONSTRAINT_NAME = TC.CONSTRAINT_NAME
- where CONSTRAINT_TYPE = 'PRIMARY KEY' and
-   TC.CONSTRAINT_CATALOG = '%(db)s' and
-   TC.TABLE_NAME = '%(table)s' and
-   TC.CONSTRAINT_SCHEMA = '%(schema)s' """
+select kc.COLUMN_NAME from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kc
+       inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
+               on tc.CONSTRAINT_NAME = kc.CONSTRAINT_NAME
+       where kc.TABLE_CATALOG = %s and
+               kc.TABLE_SCHEMA = %s and
+               kc.TABLE_NAME = %s and
+               tc.CONSTRAINT_TYPE = 'PRIMARY KEY' """
 
-               cursor.execute(sql % {'table': tableName, 'db': dbName, 
'schema': tableSchema})
+               cursor.execute(sql, (dbName, tableSchema, tableName))
                pkFields = cursor.getDataSet()
 
                fields = []
                for r in fieldDefs:
                        name = r["COLUMN_NAME"]
                        ft = self._fieldTypeNativeToDabo(r["DATA_TYPE"])
-                       pk = (name,) in [(p["COLUMN_NAME"], ) for p in pkFields]
+                       pk = (name,) in [(p["COLUMN_NAME"],) for p in pkFields]
                        fields.append((name, ft, pk))
 
-
                return tuple(fields)
 
 
@@ -254,9 +260,9 @@
        def formSQL(self, fieldClause, fromClause, joinClause,
                                whereClause, groupByClause, orderByClause, 
limitClause):
                """MS SQL wants the limit clause before the field clause."""
-               clauses =  (limitClause, fieldClause, fromClause, joinClause,
+               clauses = (limitClause, fieldClause, fromClause, joinClause,
                                whereClause, groupByClause, orderByClause)
-               sql = "SELECT " + "\n".join( [clause for clause in clauses if 
clause] )
+               sql = "SELECT " + "\n".join([clause for clause in clauses if 
clause])
                return sql
 
 
@@ -267,7 +273,7 @@
                """
                # Use the AuxCursor so as not to disturb the contents of the 
primary data cursor.
                try:
-                       idVal = self.lastrowid
+                       idVal = cursor.lastrowid
                except AttributeError:
                        crs = cursor.AuxCursor
                        crs.execute("select @@IDENTITY as newid")



_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev
Searchable Archives: http://leafe.com/archives/search/dabo-dev
This message: 
http://leafe.com/archives/byMID/[email protected]

Reply via email to