Michael Manfre avatar Michael Manfre committed 1ecf3b4 Merge

Merge

Comments (0)

Files changed (5)

docs/changelog.txt

 
 - Ensure master connection connects to the correct database name when TEST_NAME is not defined.
 - Connection.close() will now reset adoConn to make sure it's gone before the CoUninitialize.
+- Changed provider default from 'SQLOLEDB' to 'SQLNCLI10' with MARS enabled.
 - Added :ref:`rawstoredproceduremanager`, which provides ``raw_callproc`` that works the same as ``raw``, except
   expects the name of a stored procedure that returns a result set that matches the model.
 

docs/quickstart.txt

                 'HOST': 'dbserver\\ss2008',
                 'USER': '',
                 'PASSWORD': '',
-                'OPTIONS' : {
-                    'provider': 'SQLOLEDB',
-                    'use_mars': True,
-                },
             }
         }
 
     .. note:: Although the project is named ``django-mssql`` the python module is named ``sqlserver_ado``.
 
+
 Dependencies
 ------------
 

docs/settings.txt

             'HOST': 'dbserver\\ss2008',
             'USER': '',
             'PASSWORD': '',
-            'OPTIONS' : {
-                'provider': 'SQLOLEDB',
-                'use_mars': True,
-            },
         }
     }
 
 use_mars
 ~~~~~~~~
 
-Default: ``False``
+Default: ``True``
 
-Set to ``True`` to enable `Multiple Active Recordsets`. It is recommended 
-to enable MARS to avoid seeing the "Cannot create new connection because 
-in manual or distributed transaction mode" error.
+Set to ``False`` to disable `Multiple Active Recordsets`. It is not recommended 
+to disable MARS. Without MARS enabled, you will probably end up seeing the error
+"Cannot create new connection because in manual or distributed transaction mode".
 
 .. note::
-    This will only set the appropriate connection string value for 
-    the "SQLOLEDB" provider. If you are using a different provider, you 
-    will need to add the appropriate connection string value to 
-    `extra_params`_.
+    This doesn't really work properly with the "SQLOLEDB" provider.
 
 
 .. _`extra_params`: OPTIONS-EXTRA_PARAMS
 provider
 ~~~~~~~~
 
-Default: ``'SQLOLEDB'``
+Default: ``'SQLCLI10'``
 
-The SQL provider to use when connecting to the database.
+The SQL provider to use when connecting to the database. If this doesn't work, 
+try 'SQLCLI11' or 'SQLOLEDB'.
+
+.. note::
+    ``use_mars = True`` doesn't always work properly with 'SQLOLEDB' and can result in the error 
+    "Cannot create new connection because in manual or distributed transaction mode."
+    if you try to filter a queryset with another queryset.
 
 
 disable_avg_cast

sqlserver_ado/base.py

             port = int(settings.PORT)
         except ValueError:
             raise ImproperlyConfigured("DATABASE PORT must be a number.")
-        db_host = '%s,%i;Network Library=DBMSSOCN' % (db_host, port)
+        db_host = '{0},{1};Network Library=DBMSSOCN'.format(db_host, port)
 
     # If no user is specified, use integrated security.
     if settings.USER != '':
-        auth_string = "UID=%s;PWD=%s" % (settings.USER, settings.PASSWORD)
+        auth_string = 'UID={0};PWD={1}'.format(settings.USER, settings.PASSWORD)
     else:
-        auth_string = "Integrated Security=SSPI"
+        auth_string = 'Integrated Security=SSPI'
 
     parts = [
-        "PROVIDER=SQLOLEDB", 
-        "DATA SOURCE=%s" % (db_host,),
-        "Initial Catalog=%s" % (db_name,),
+        'DATA SOURCE={0};Initial Catalog={1}'.format(db_host, db_name),
         auth_string
     ]
+
+    options = settings.OPTIONS
+
+    if not options.get('provider', None):
+        options['provider'] = 'sqlncli10'
     
-    options = settings.OPTIONS
-    if options:
-        if 'use_mars' in options and options['use_mars']:
-            parts.append("MARS Connection=True")
-            
-        if 'extra_params' in options:
-            parts.append(options['extra_params'])
+    parts.append('PROVIDER={0}'.format(options['provider']))
         
-        if 'provider' in options:
-            parts[0] = 'PROVIDER=%s' % (options['provider'],)
+    if options['provider'].lower().find('=sqlcli') != -1:
+        # native client needs a compatibility mode that behaves like OLEDB
+        parts.append('DataTypeCompatibility=80')
+
+    if options.get('use_mars', True):
+        parts.append('MARS Connection=True')
+    
+    if options.get('extra_params', None):
+        parts.append(options['extra_params'])    
     
     return ";".join(parts)
 
         "startswith": "LIKE %s ESCAPE '\\'",
         "endswith": "LIKE %s ESCAPE '\\'",
         "istartswith": "LIKE %s ESCAPE '\\'",
-        "iendswith": "LIKE %s ESCAPE '\\'",
+        "iendswith": "LIKE %S ESCAPE '\\'",
     }
 
     def __init__(self, *args, **kwargs):

sqlserver_ado/compiler.py

             if self.query.distinct:
                 _select += ' DISTINCT'
             
-            sql = re.sub(r'(?i)^%s' % _select, '%s TOP %s' % (_select, self.query.high_mark), raw_sql, 1)
+            sql = re.sub(r'(?i)^{0}'.format(_select), '{0} TOP {1}'.format(_select, self.query.high_mark), raw_sql, 1)
             return sql, fields
             
         # Else we have limits; rewrite the query using ROW_NUMBER()
         if order is None:
             meta = self.query.get_meta()                
             column = meta.pk.db_column or meta.pk.get_attname()
-            order = '%s.%s ASC' % (inner_table_name, qn(column))
+            order = '{0}.{1} ASC'.format(inner_table_name, qn(column))
         else:
             # remap order for injected subselect
             new_order = []
                     tbl, col = x.rsplit('.', 1)
                 else:
                     col = x
-                new_order.append('%s.%s' % (inner_table_name, col))
+                new_order.append('{0}.{1}'.format(inner_table_name, col))
             order = ', '.join(new_order)
         
-        where_row_num = "%s < _row_num" % (self.query.low_mark)
+        where_row_num = '{0} < _row_num'.format(self.query.low_mark)
         if self.query.high_mark:
-            where_row_num += " and _row_num <= %s" % (self.query.high_mark)
+            where_row_num += ' and _row_num <= {0}'.format(self.query.high_mark)
             
         # Lop off ORDER... and the initial "SELECT"
         inner_select = _remove_order_limit_offset(raw_sql)
                 tbl, col = x.rsplit('.', 1)
             else:
                 col = x
-            f.append('%s.%s' % (inner_table_name, col.strip()))
+            f.append('{0}.{1}'.format(inner_table_name, col.strip()))
         
         
         # inject a subselect to get around OVER requiring ORDER BY to come from FROM
-        inner_select = '%s FROM ( SELECT %s ) AS %s'\
-             % (', '.join(f), inner_select, inner_table_name)
+        inner_select = '{fields} FROM ( SELECT {inner} ) AS {inner_as}'.format(
+            fields=', '.join(f),
+            inner=inner_select,
+            inner_as=inner_table_name,
+        )
         
-        sql = "SELECT _row_num, %s FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY %s) as _row_num, %s) as QQQ where %s"\
-             % (outer_fields, order, inner_select, where_row_num)
+        sql = "SELECT _row_num, {outer} FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY {order}) as _row_num, {inner}) as QQQ where {where}".format(
+            outer=outer_fields,
+            order=order,
+            inner=inner_select,
+            where=where_row_num,
+        )
         
         return sql, fields
 
                 col_key = col_name.lower()
 
                 if col_key in names_seen:
-                    alias = qn('%s___%s' % (col_name, names_seen.count(col_key)))
+                    alias = qn('{0}___{1}'.format(col_name, names_seen.count(col_key)))
                     outer.append(alias)
             
                     col = _replace_sub(col)
             
-                    inner.append("%s as %s" % (col, alias))
+                    inner.append('{0} as {1}'.format(col, alias))
                 else:
                     replaced = _replace_sub(col)
                             
                 params = []
             elif auto_in_fields:
                 # wrap with identity insert
-                sql = "SET IDENTITY_INSERT %s ON;%s;SET IDENTITY_INSERT %s OFF" %\
-                    (quoted_table, sql, quoted_table)
+                sql = 'SET IDENTITY_INSERT {table} ON;{sql};SET IDENTITY_INSERT {table} OFF'.format(
+                    table=quoted_table,
+                    sql=sql,
+                )
 
         return sql, params
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.