All pastes #43851 Raw Edit

matt

public text v1 · immutable
#43851 ·published 2006-03-01 00:35 UTC
rendered paste body
=== django/core/db/backends/mssql.py==================================================================--- django/core/db/backends/mssql.py	(revision 8524)+++ django/core/db/backends/mssql.py	(revision 8525)@@ -0,0 +1,214 @@+"""+SQL Server database backend for Django.++Requires ADODBAPI: http://adodbapi.sf.net+"""++import re++from django.core.db import base+from django.core.db.dicthelpers import *+import pymssql as Database+from itertools import repeat++DatabaseError = Database.DatabaseError++class CursorWrapper:+    def __init__(self, conn, cursor):+        self._conn = conn+        self._cursor = cursor+        self._limit_re = re.compile(r'(?:LIMIT\s+(\d+))?\s*(?:OFFSET\s+(\d+))?$')+        self.execute('')++    def execute(self, sql, params=None):+        self._conn.queries.append((sql, params))+        sql, offset = self._parse_sql(sql, params)+        result = self._cursor.execute(sql, params)+        if offset:+            self._cursor.fetchmany(offset) # discard offset amount+        return result++    def executemany(self, sql, paramseq):+        self._conn.queries.append((sql, params))+        sql, offset = self._parse_sql(sql, paramseq[0])+        return self._cursor.executemany(sql, paramseq)++    def _parse_sql(self, sql, params):+        limit, offset = self._limit_re.search(sql).groups()+        sql = self._limit_re.sub('', sql)++        if offset:+            offset = int(offset)+        else:+            offset = 0++        if not limit:+            return sql, offset++        limit = int(limit) + offset++        return (' TOP %s ' % limit).join(sql.split(None, 1)), offset++    def __getattr__(self, attr):+        return getattr(self._cursor, attr)+++class DatabaseWrapper:+    def __init__(self):+        self.connection = None+        self.queries = []++    def cursor(self):+        from django.conf.settings import DEBUG+        if DEBUG:+            return base.CursorDebugWrapper(self._cursor(), self)+        return self._cursor()++    def _cursor(self):+        if self.connection is None:+            from django.conf.settings import DATABASE_USER, DATABASE_NAME, \+                                             DATABASE_HOST, DATABASE_PASSWORD+            self.connection = Database.connect(host=DATABASE_HOST,+                                               database=DATABASE_NAME,+                                               user=DATABASE_USER,+                                               password=DATABASE_PASSWORD)+        return CursorWrapper(self, self.connection.cursor())++    def commit(self):+        self.connection.commit()++    def rollback(self):+        if self.connection is not None:+            self.connection.rollback()++    def close(self):+        if self.connection is not None:+            self.connection.close()+            self.connection = None++    def quote_name(self, name):+        if name.startswith('[') and name.endswith(']'):+            return name # Quoting once is enough.+        return '[%s]' % name++def get_last_insert_id(cursor, table_name, pk_name):+    cursor.execute("SELECT cast(@@IDENTITY AS int)") # or possibly SCOPE_IDENTITY() if necessary+    return cursor.fetchone()[0]++def get_date_extract_sql(lookup_type, table_name):+    # lookup_type is 'year', 'month', 'day'+    return "DATEPART(%s, %s)" % (lookup_type, table_name)++def get_date_trunc_sql(lookup_type, field_name):+    # lookup_type is 'year', 'month', 'day'+    if lookup_type=='year':+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name+    if lookup_type=='month':+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name)+    if lookup_type=='day':+        return "Convert(datetime, Convert(varchar(12), %s))" % field_name++def get_limit_offset_sql(limit, offset=None):+    sql = "LIMIT %s" % limit+    if offset and offset != 0:+        sql += " OFFSET %s" % offset+    return sql++def get_random_function_sql():+    return 'rand()'++def get_table_list(cursor):+    cursor.execute("select name from sysobjects where type='U'")+    return [row[0] for row in cursor.fetchall()]++def get_table_description(cursor, table_name):+    raise NotImplementedError++def get_relations(cursor, table_name):+    raise NotImplementedError++OPERATOR_MAPPING = {+    'exact': '= %s',+    'iexact': 'LIKE %s',+    'contains': 'LIKE %s',+    'icontains': 'LIKE %s',+    'ne': '!= %s',+    'gt': '> %s',+    'gte': '>= %s',+    'lt': '< %s',+    'lte': '<= %s',+    'startswith': 'LIKE %s',+    'endswith': 'LIKE %s',+    'istartswith': 'LIKE %s',+    'iendswith': 'LIKE %s',+}++def get_relations(cursor, table_name):+    raise NotImplementedError+    """FIXME: something like below is a start on SQL:+    source:+    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsqlpro03/html/sp03l12.asp++SELECT +     KCU1.CONSTRAINT_NAME AS 'FK_CONSTRAINT_NAME'+   , KCU1.TABLE_NAME AS 'FK_TABLE_NAME'+   , KCU1.COLUMN_NAME AS 'FK_COLUMN_NAME'+   , KCU1.ORDINAL_POSITION AS 'FK_ORDINAL_POSITION'+   , KCU2.CONSTRAINT_NAME AS 'UQ_CONSTRAINT_NAME'+   , KCU2.TABLE_NAME AS 'UQ_TABLE_NAME'+   , KCU2.COLUMN_NAME AS 'UQ_COLUMN_NAME'+   , KCU2.ORDINAL_POSITION AS 'UQ_ORDINAL_POSITION'+FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC+JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1+ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG +   AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA+   AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME+JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2+ON KCU2.CONSTRAINT_CATALOG = +RC.UNIQUE_CONSTRAINT_CATALOG +   AND KCU2.CONSTRAINT_SCHEMA = +RC.UNIQUE_CONSTRAINT_SCHEMA+   AND KCU2.CONSTRAINT_NAME = +RC.UNIQUE_CONSTRAINT_NAME+   AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION++    """++def quote_name(name):+    # TODO: Figure out how MS-SQL quotes database identifiers.+    return name+    ++# This dictionary maps Field objects to their associated SQL Server column+# types, as strings. Column-type strings can contain format strings; they'll+# be interpolated against the values of Field.__dict__ before being output.+# If a column type is set to None, it won't be included in the output.+DATA_TYPES = {+    'AutoField':         'int identity',+    'BooleanField':      'bit',+    'CharField':         'varchar(%(maxlength)s)',+    'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',+    'DateField':         'smalldatetime',+    'DateTimeField':     'smalldatetime',+    'FileField':         'varchar(100)',+    'FilePathField':     'varchar(100)',+    'FloatField':        'numeric(%(max_digits)s, %(decimal_places)s)',+    'ImageField':        'nvarchar(100)',+    'IntegerField':      'int',+    'IPAddressField':    'nchar(15)',+    'ManyToManyField':   None,+    'NullBooleanField':  'bit',+    'OneToOneField':     'int',+    'PhoneNumberField':  'varchar(20)',+    'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)',+    'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',+    'SlugField':         'varchar(50)',+    'SmallIntegerField': 'smallint',+    'TextField':         'ntext',+    'TimeField':         'datetime',+    'URLField':          'nvarchar(200)',+    'USStateField':      'nvarchar(2)',+    'XMLField':          'ntext',+}++DATA_TYPES_REVERSE = { }Property changes on: django/core/db/backends/mssql.py___________________________________________________________________Name: svn:eol-style +native=== django/core/db/backends/ado_mssql.py==================================================================--- django/core/db/backends/ado_mssql.py	(revision 8524)+++ django/core/db/backends/ado_mssql.py	(revision 8525)@@ -1,80 +1,107 @@ """-ADO MSSQL database backend for Django.+SQL Server database backend for Django. -Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/+Requires ADODBAPI: http://adodbapi.sf.net """ +import re+import threading+ from django.core.db import base from django.core.db.dicthelpers import * import adodbapi as Database-import datetime-try:-    import mx-except ImportError:-    mx = None+from itertools import repeat  DatabaseError = Database.DatabaseError -# We need to use a special Cursor class because adodbapi expects question-mark-# param style, but Django expects "%s". This cursor converts question marks to-# format-string style.-class Cursor(Database.Cursor):-    def executeHelper(self, operation, isStoredProcedureCall, parameters=None):-        if parameters is not None and "%s" in operation:-            operation = operation.replace("%s", "?")-        Database.Cursor.executeHelper(self, operation, isStoredProcedureCall, parameters)+class CursorWrapper:+    def __init__(self, cursor):+        self._cursor = cursor+        self._limit_re = re.compile(r'(?:LIMIT\s+(\d+))?\s*(?:OFFSET\s+(\d+))?$') -class Connection(Database.Connection):-    def cursor(self):-        return Cursor(self)-Database.Connection = Connection+    def execute(self, sql, params=None):+        sql, offset = self._parse_sql(sql, params)+        result = self._cursor.execute(sql, params)+        if offset:+            self._cursor.fetchmany(offset) # discard offset amount+        return result -origCVtoP = Database.convertVariantToPython-def variantToPython(variant, adType):-    if type(variant) == bool and adType == 11:-        return variant  # bool not 1/0-    res = origCVtoP(variant, adType)-    if mx is not None and type(res) == mx.DateTime.mxDateTime.DateTimeType:-        # Convert ms.DateTime objects to Python datetime.datetime objects.-        tv = list(res.tuple()[:7])-        tv[-2] = int(tv[-2])-        return datetime.datetime(*tuple(tv))-    if type(res) == float and str(res)[-2:] == ".0":-        return int(res) # If float but int, then int.-    return res-Database.convertVariantToPython = variantToPython+    def executemany(self, sql, paramseq):+        sql, offset = self._parse_sql(sql, paramseq[0])+        return self._cursor.executemany(sql, paramseq) +    def _parse_sql(self, sql, params):+        sql = sql.replace('%s', '?')+        #if params:+            #sql = sql % tuple(repeat('?', len(params)))++        limit, offset = self._limit_re.search(sql).groups()+        sql = self._limit_re.sub('', sql)++        if offset:+            offset = int(offset)+        else:+            offset = 0++        if not limit:+            return sql, offset++        limit = int(limit) + offset++        return (' TOP %s ' % limit).join(sql.split(None, 1)), offset++    def __getattr__(self, attr):+        return getattr(self._cursor, attr)++def connect(host, database, user, password):+    import pythoncom+    pythoncom.CoInitialize() # Make sure COM is initialized for this thread+    provider = 'sqlncli'+    #provider = 'sqloledb'+    return Database.connect('Provider=%s;Data Source=%s;Initial Catalog=%s;User Id=%s;Password=%s'+                            % (provider, host, database, user, password))+          class DatabaseWrapper:     def __init__(self):-        self.connection = None+        self.local = threading.local()         self.queries = [] +    def connection():+        def fget(self):+            return getattr(self.local, 'connection', None)+        def fset(self, value):+            self.local.connection = value+        def fdel(self):+            del self.local.connection+        return property(fget, fset, fdel)+    connection = connection()+     def cursor(self):-        from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG-        if self.connection is None:-            if DATABASE_NAME == '' or DATABASE_USER == '':-                from django.core.exceptions import ImproperlyConfigured-                raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file."-            if not DATABASE_HOST:-                DATABASE_HOST = "127.0.0.1"-            # TODO: Handle DATABASE_PORT.-            conn_string = "PROVIDER=SQLOLEDB;DATA SOURCE=%s;UID=%s;PWD=%s;DATABASE=%s" % (DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME)-            self.connection = Database.connect(conn_string)-        cursor = self.connection.cursor()+        from django.conf.settings import DEBUG         if DEBUG:-            return base.CursorDebugWrapper(cursor, self)-        return cursor+            return base.CursorDebugWrapper(self._cursor(), self)+        return self._cursor() +    def _cursor(self):+        if self.connection is None:+            from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PASSWORD+            self.connection = connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD)+        return CursorWrapper(self.connection.cursor())+     def commit(self):-        return self.connection.commit()+        self.connection.commit()      def rollback(self):-        if self.connection:-            return self.connection.rollback()+        if self.connection is not None:+            self.connection.rollback()      def close(self):         if self.connection is not None:-            self.connection.close()+            try:+                self.connection.close()+            except Database.InternalError:+                # ignore connection errors for 'No transaction is active.'+                pass             self.connection = None      def quote_name(self, name):@@ -83,7 +110,7 @@         return '[%s]' % name  def get_last_insert_id(cursor, table_name, pk_name):-    cursor.execute("SELECT %s FROM %s WHERE %s = @@IDENTITY" % (pk_name, table_name, pk_name))+    cursor.execute("SELECT cast(@@IDENTITY AS int)") # or possibly SCOPE_IDENTITY() if necessary     return cursor.fetchone()[0]  def get_date_extract_sql(lookup_type, table_name):@@ -100,17 +127,17 @@         return "Convert(datetime, Convert(varchar(12), %s))" % field_name  def get_limit_offset_sql(limit, offset=None):-    # TODO: This is a guess. Make sure this is correct.     sql = "LIMIT %s" % limit     if offset and offset != 0:         sql += " OFFSET %s" % offset     return sql  def get_random_function_sql():-    return "RAND()"+    return 'rand()'  def get_table_list(cursor):-    raise NotImplementedError+    cursor.execute("select name from sysobjects where type='U'")+    return [row[0] for row in cursor.fetchall()]  def get_table_description(cursor, table_name):     raise NotImplementedError@@ -134,8 +161,48 @@     'iendswith': 'LIKE %s', } +def get_relations(cursor, table_name):+    raise NotImplementedError+    """FIXME: something like below is a start on SQL:+    source:+    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsqlpro03/html/sp03l12.asp++SELECT +     KCU1.CONSTRAINT_NAME AS 'FK_CONSTRAINT_NAME'+   , KCU1.TABLE_NAME AS 'FK_TABLE_NAME'+   , KCU1.COLUMN_NAME AS 'FK_COLUMN_NAME'+   , KCU1.ORDINAL_POSITION AS 'FK_ORDINAL_POSITION'+   , KCU2.CONSTRAINT_NAME AS 'UQ_CONSTRAINT_NAME'+   , KCU2.TABLE_NAME AS 'UQ_TABLE_NAME'+   , KCU2.COLUMN_NAME AS 'UQ_COLUMN_NAME'+   , KCU2.ORDINAL_POSITION AS 'UQ_ORDINAL_POSITION'+FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC+JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1+ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG +   AND KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA+   AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME+JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2+ON KCU2.CONSTRAINT_CATALOG = +RC.UNIQUE_CONSTRAINT_CATALOG +   AND KCU2.CONSTRAINT_SCHEMA = +RC.UNIQUE_CONSTRAINT_SCHEMA+   AND KCU2.CONSTRAINT_NAME = +RC.UNIQUE_CONSTRAINT_NAME+   AND KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION++    """++def quote_name(name):+    # TODO: Figure out how MS-SQL quotes database identifiers.+    return name+    ++# This dictionary maps Field objects to their associated SQL Server column+# types, as strings. Column-type strings can contain format strings; they'll+# be interpolated against the values of Field.__dict__ before being output.+# If a column type is set to None, it won't be included in the output. DATA_TYPES = {-    'AutoField':         'int IDENTITY (1, 1)',+    'AutoField':         'int identity',     'BooleanField':      'bit',     'CharField':         'varchar(%(maxlength)s)',     'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',@@ -144,9 +211,9 @@     'FileField':         'varchar(100)',     'FilePathField':     'varchar(100)',     'FloatField':        'numeric(%(max_digits)s, %(decimal_places)s)',-    'ImageField':        'varchar(100)',+    'ImageField':        'nvarchar(100)',     'IntegerField':      'int',-    'IPAddressField':    'char(15)',+    'IPAddressField':    'nchar(15)',     'ManyToManyField':   None,     'NullBooleanField':  'bit',     'OneToOneField':     'int',@@ -155,10 +222,11 @@     'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',     'SlugField':         'varchar(50)',     'SmallIntegerField': 'smallint',-    'TextField':         'text',-    'TimeField':         'time',-    'URLField':          'varchar(200)',-    'USStateField':      'varchar(2)',+    'TextField':         'ntext',+    'TimeField':         'datetime',+    'URLField':          'nvarchar(200)',+    'USStateField':      'nvarchar(2)',+    'XMLField':          'ntext', } -DATA_TYPES_REVERSE = {}+DATA_TYPES_REVERSE = { }=== django/core/meta/__init__.py==================================================================--- django/core/meta/__init__.py	(revision 8524)+++ django/core/meta/__init__.py	(revision 8525)@@ -1021,6 +1021,8 @@             placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \                 (db.db.quote_name(opts.db_table), db.db.quote_name(opts.order_with_respect_to.column)))             db_values.append(getattr(self, opts.order_with_respect_to.attname))+        if settings.DATABASE_ENGINE == 'mssql' and opts.has_auto_field and pk_set:+            cursor.execute("SET IDENTITY_INSERT %s ON" % db.db.quote_name(opts.db_table))         cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \             (db.db.quote_name(opts.db_table), ','.join(field_names),             ','.join(placeholders)), db_values)@@ -1103,13 +1105,16 @@         val = getattr(self, field_with_rel.attname)         mod = field_with_rel.rel.to.get_model_module()         if val is None:-            raise getattr(mod, '%sDoesNotExist' % field_with_rel.rel.to.object_name)-        other_field = field_with_rel.rel.get_related_field()-        if other_field.rel:-            params = {'%s__%s__exact' % (field_with_rel.rel.field_name, other_field.rel.field_name): val}+            if not field_with_rel.null:+                raise getattr(mod, '%sDoesNotExist' % field_with_rel.rel.to.object_name)+            retrieved_obj = None         else:-            params = {'%s__exact'% field_with_rel.rel.field_name: val}-        retrieved_obj = mod.get_object(**params)+            other_field = field_with_rel.rel.get_related_field()+            if other_field.rel:+                params = {'%s__%s__exact' % (field_with_rel.rel.field_name, other_field.rel.field_name): val}+            else:+                params = {'%s__exact'% field_with_rel.rel.field_name: val}+            retrieved_obj = mod.get_object(**params)         setattr(self, cache_var, retrieved_obj)     return getattr(self, cache_var)