Django

Code

Ticket #5062: NewMSSQL.diff

File NewMSSQL.diff, 38.0 kB (added by mamcx, 1 year ago)

Integration older patch + enabling of this new backend

  • contrib/sessions/middleware.py

    old new  
    5959                self._session_cache = {} 
    6060            else: 
    6161                try: 
     62                    datenow = datetime.datetime.now() 
     63                    if hasattr(datenow, 'microsecond'): 
     64                        datenow = datenow.replace(microsecond=0) 
    6265                    s = Session.objects.get(session_key=self.session_key, 
    63                         expire_date__gt=datetime.datetime.now()
     66                        expire_date__gt=datenow
    6467                    self._session_cache = s.get_decoded() 
    6568                except (Session.DoesNotExist, SuspiciousOperation): 
    6669                    self._session_cache = {} 
  • db/backends/mssql/base.py

    old new  
     1""" 
     2Alpha Multi-plataform MSSQL database backend for Django. 
     3 
     4Requires pymssql >= v0.8.0: http://pymssql.sourceforge.net/ 
     5""" 
     6if __name__ == '__main__': 
     7    import sys 
     8    import os 
     9     
     10    SETTINGS_MODULE = 'settings' 
     11 
     12    project_dir = r'E:\Proyectos\Python\mysite' 
     13    sys.path.append(os.path.join(project_dir, '..')) 
     14    sys.path.append("..") 
     15    sys.path.pop() 
     16    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' 
     17     
     18 
     19import datetime 
     20from django.db.backends import util 
     21from django.core.exceptions import ImproperlyConfigured 
     22 
     23try: 
     24    import pymssql as Database 
     25except ImportError, e: 
     26    raise ImproperlyConfigured, "Error loading pymssql module: %s" % e 
     27 
     28try: 
     29    import mx 
     30except ImportError: 
     31    mx = None 
     32 
     33try: 
     34    # Only exists in Python 2.4+ 
     35    from threading import local 
     36except ImportError: 
     37    # Import copy of _thread_local.py from Python 2.4 
     38    from django.utils._threading_local import local 
     39 
     40DatabaseError = Database.DatabaseError 
     41IntegrityError = Database.IntegrityError 
     42 
     43#Configure support options: 
     44allows_group_by_ordinal = True 
     45allows_unique_and_pk = True 
     46autoindexes_primary_keys = True 
     47needs_datetime_string_cast = True 
     48needs_upper_for_iops = False 
     49supports_constraints = True 
     50supports_tablespaces = False 
     51uses_case_insensitive_names = False 
     52 
     53def complain(*args, **kwargs): 
     54    raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet." 
     55 
     56def ignore(*args, **kwargs): 
     57    pass 
     58 
     59class DatabaseError(Exception): 
     60    pass 
     61 
     62class IntegrityError(DatabaseError): 
     63    pass 
     64 
     65class DatabaseWrapper(local): 
     66    def __init__(self, **kwargs): 
     67        self.connection = None 
     68        self.queries = [] 
     69 
     70    def cursor(self): 
     71        from django.conf import settings 
     72        if self.connection is None: 
     73            if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '': 
     74                raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file." 
     75            if not settings.DATABASE_HOST: 
     76                settings.DATABASE_HOST = "127.0.0.1" 
     77            # TODO: Handle DATABASE_PORT. 
     78            self.connection = Database.connect(host=settings.DATABASE_HOST,user=settings.DATABASE_USER,password=settings.DATABASE_PASSWORD,database=settings.DATABASE_NAME) 
     79         
     80        self.connection.cursor().execute("SET DATEFORMAT ymd\nGO") 
     81         
     82        cursor = self.connection.cursor() 
     83        if settings.DEBUG: 
     84            return util.CursorDebugWrapper(cursor, self) 
     85        return cursor 
     86 
     87    def _commit(self): 
     88        if self.connection is not None: 
     89            return self.connection.commit() 
     90 
     91    def _rollback(self): 
     92        if self.connection is not None: 
     93            return self.connection.rollback() 
     94 
     95    def close(self): 
     96        if self.connection is not None: 
     97            self.connection.close() 
     98            self.connection = None 
     99 
     100''' 
     101    Return the major version of the server. 7=Sql 7,8=Sql2000,9=Sql2005 
     102''' 
     103def version(): 
     104    cur = DatabaseWrapper().cursor() 
     105    cur.execute("SELECT SERVERPROPERTY('ProductVersion')") 
     106     
     107    return int(cur.fetchone()[0].split('.')[0]) 
     108 
     109def quote_name(name): 
     110    if name.startswith('[') and name.endswith(']'): 
     111        return name # Quoting once is enough. 
     112    return '[%s]' % name 
     113 
     114dictfetchone = util.dictfetchone 
     115dictfetchmany = util.dictfetchmany 
     116dictfetchall  = util.dictfetchall 
     117 
     118def get_last_insert_id(cursor, table_name, pk_name): 
     119    cursor.execute("SELECT %s FROM %s WHERE %s = IDENT_CURRENT('%s')" % (pk_name, table_name, pk_name,table_name))  
     120    return cursor.fetchone()[0] 
     121 
     122def get_date_extract_sql(lookup_type, table_name): 
     123    # lookup_type is 'year', 'month', 'day' 
     124    return "DATEPART(%s, %s)" % (lookup_type, table_name) 
     125 
     126def get_date_trunc_sql(lookup_type, field_name): 
     127    # lookup_type is 'year', 'month', 'day' 
     128    if lookup_type=='year': 
     129        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name 
     130    if lookup_type=='month': 
     131        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name) 
     132    if lookup_type=='day': 
     133        return "Convert(datetime, Convert(varchar(12), %s))" % field_name 
     134 
     135def get_datetime_cast_sql(): 
     136    return None 
     137 
     138def get_limit_offset_sql(limit, offset=None): 
     139    # Limits and offset are too complicated to be handled here. 
     140    # Look for a implementation similar to oracle backend 
     141    return "" 
     142 
     143def get_random_function_sql(): 
     144    return "RAND()" 
     145 
     146def get_deferrable_sql(): 
     147    # TODO: Workaround cicle paths... 
     148    # DEFERRABLE and INITALLY DEFFERRED are not apparently supported on constraints 
     149    # This cause SQL Server message 1750, severity 16, state 0, for example in the multiple joins path of comments. 
     150    # So, this left Sql Server as if have not relations :( 
     151    #return " ON DELETE CASCADE ON UPDATE CASCADE" 
     152    return ""  
     153 
     154def get_fulltext_search_sql(field_name): 
     155    raise NotImplementedError 
     156 
     157def get_drop_foreignkey_sql(): 
     158    return "DROP CONSTRAINT" 
     159 
     160def get_pk_default_value(): 
     161    return "DEFAULT" 
     162 
     163def get_max_name_length(): 
     164    return None 
     165 
     166def get_start_transaction_sql(): 
     167    return "BEGIN;" 
     168 
     169def get_tablespace_sql(tablespace, inline=False): 
     170    return "ON %s" % quote_name(tablespace) 
     171 
     172def get_autoinc_sql(table): 
     173    return None 
     174 
     175def get_sql_flush(sql_styler, full_table_list, sequences):  
     176    """Return a list of SQL statements required to remove all data from 
     177    all tables in the database (without actually removing the tables 
     178    themselves) and put the database in an empty 'initial' state 
     179    """ 
     180    # Cannot use TRUNCATE on tables that are reference by a FOREIGN KEY 
     181    # So must use the much slower DELETE 
     182    sql_list = ['%s %s %s;' % \ 
     183                (sql_styler.SQL_KEYWORD('DELETE'), 
     184                sql_styler.SQL_KEYWORD('FROM'), 
     185                sql_styler.SQL_FIELD(quote_name(table)) 
     186                )  for table in full_table_list] 
     187    #The reset the counters on each table. 
     188    sql_list.extend(['%s %s %s %s %s %s %s;' % ( 
     189        sql_styler.SQL_KEYWORD('DBCC'), 
     190        sql_styler.SQL_KEYWORD('CHECKIDENT'), 
     191        sql_styler.SQL_FIELD(quote_name(seq["table"])), 
     192        sql_styler.SQL_KEYWORD('RESEED'), 
     193        sql_styler.SQL_FIELD('1'), 
     194        sql_styler.SQL_KEYWORD('WITH'), 
     195        sql_styler.SQL_KEYWORD('NO_INFOMSGS'), 
     196        ) for seq in sequences]) 
     197     
     198    return sql_list  
     199 
     200def get_sql_sequence_reset(style, model_list): 
     201    "Returns a list of the SQL statements to reset sequences for the given models." 
     202    # No sequence reset required 
     203    return [] 
     204 
     205OPERATOR_MAPPING = { 
     206    'exact': '= %s', 
     207    'iexact': 'LIKE %s', 
     208    'contains': 'LIKE %s', 
     209    'icontains': 'LIKE %s', 
     210    'gt': '> %s', 
     211    'gte': '>= %s', 
     212    'lt': '< %s', 
     213    'lte': '<= %s', 
     214    'startswith': 'LIKE %s', 
     215    'endswith': 'LIKE %s', 
     216    'istartswith': 'LIKE %s', 
     217    'iendswith': 'LIKE %s', 
     218} 
     219 
     220if __name__ == '__main__': 
     221    from mysite.polls.models import Poll, Choice 
     222    from django.contrib.auth.models import User 
     223    from datetime import datetime 
     224    Poll.objects.all() 
     225    p = Poll(question="What's up?", pub_date=datetime.now()) 
     226    p.save() 
     227    print p.id 
     228     
     229    db=DatabaseWrapper() 
     230    print version() 
     231 
     232 
  • db/backends/mssql/client.py

    old new  
     1def runshell(): 
     2    raise NotImplementedError 
  • db/backends/mssql/introspection.py

    old new  
     1def get_table_list(cursor): 
     2    "Returns a list of table names in the current database." 
     3    cursor.execute("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'") 
     4    return [row[2] for row in cursor.fetchall()] 
     5 
     6def _is_auto_field(cursor, table_name, column_name): 
     7    cursor.execute("SELECT COLUMNPROPERTY( OBJECT_ID('%s'),'%s','IsIdentity')" % (table_name, column_name)) 
     8    return cursor.fetchall()[0][0] 
     9 
     10def get_table_description(cursor, table_name, identity_check=True): 
     11    """Returns a description of the table, with the DB-API cursor.description interface. 
     12 
     13    The 'auto_check' parameter has been added to the function argspec. 
     14    If set to True, the function will check each of the table's fields for the 
     15    IDENTITY property (the IDENTITY property is the MSSQL equivalent to an AutoField). 
     16 
     17    When a field is found with an IDENTITY property, it is given a custom field number 
     18    of -777, which maps to the 'AutoField' value in the DATA_TYPES_REVERSE dict. 
     19    """     
     20    cursor.execute("SELECT TOP 1 * FROM %s" % table_name) 
     21    cursor.nextset() 
     22    items = [] 
     23    if identity_check: 
     24        for data in cursor.description: 
     25            if _is_auto_field(cursor, table_name, data[0]): 
     26                data = list(data) 
     27                data[1] = -777 
     28            items.append(list(data)) 
     29    else: 
     30        items = cursor.description 
     31    return items 
     32 
     33def _name_to_index(cursor, table_name): 
     34    """ 
     35    Returns a dictionary of {field_name: field_index} for the given table. 
     36    Indexes are 0-based. 
     37    """ 
     38    return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name, identity_check=False))]) 
     39 
     40def get_relations(cursor, table_name): 
     41    """ 
     42    Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
     43    representing all relationships to the given table. Indexes are 0-based.     
     44    """ 
     45    table_index = _name_to_index(cursor, table_name) 
     46    sql = """SELECT e.COLUMN_NAME AS column_name, 
     47                    c.TABLE_NAME AS referenced_table_name, 
     48                    d.COLUMN_NAME AS referenced_column_name 
     49                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a 
     50                        INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS b 
     51                              ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME 
     52                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS c 
     53                              ON b.UNIQUE_CONSTRAINT_NAME = c.CONSTRAINT_NAME 
     54                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS d 
     55                              ON c.CONSTRAINT_NAME = d.CONSTRAINT_NAME 
     56                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS e 
     57                              ON a.CONSTRAINT_NAME = e.CONSTRAINT_NAME 
     58                    WHERE a.TABLE_NAME = ? AND 
     59                          a.CONSTRAINT_TYPE = 'FOREIGN KEY'""" 
     60    cursor = Cursor(cursor.db.connection) 
     61    cursor.execute(sql, (table_name,)) 
     62    return dict([(table_index[item[0]], (_name_to_index(cursor, item[1])[item[2]], item[1])) 
     63                  for item in cursor.fetchall()]) 
     64     
     65def get_indexes(cursor, table_name): 
     66    """ 
     67    Returns a dictionary of fieldname -> infodict for the given table, 
     68    where each infodict is in the format: 
     69        {'primary_key': boolean representing whether it's the primary key, 
     70         'unique': boolean representing whether it's a unique index} 
     71    """ 
     72    sql = """SELECT b.COLUMN_NAME, a.CONSTRAINT_TYPE 
     73               FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a INNER JOIN 
     74                    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS b 
     75                    ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME AND 
     76                       a.TABLE_NAME = b.TABLE_NAME 
     77               WHERE a.TABLE_NAME = ? AND 
     78                     (CONSTRAINT_TYPE = 'PRIMARY KEY' OR 
     79                      CONSTRAINT_TYPE = 'UNIQUE')""" 
     80    field_names = [item[0] for item in get_table_description(cursor, table_name, identity_check=False)] 
     81    cursor = Cursor(cursor.db.connection) 
     82    cursor.execute(sql, (table_name,)) 
     83    indexes = {} 
     84    results = {} 
     85    data = cursor.fetchall() 
     86    if data: 
     87        results.update(data) 
     88    for field in field_names: 
     89        val = results.get(field, None) 
     90        indexes[field] = dict(primary_key=(val=='PRIMARY KEY'), unique=(val=='UNIQUE')) 
     91    return indexes 
     92 
     93# A reference for the values below: 
     94# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdcstdatatypeenum.asp 
     95DATA_TYPES_REVERSE = { 
     96# 8192 : Array , 
     97# 128 : Binary , 
     98# 9 : IDispatch , 
     99# 12 : Variant , 
     100# 13 : IUnknown , 
     101# 21  : UnsignedBigInt, 
     102# 132 : UserDefined , 
     103# 0   : Empty , 
     104# 136 : Chapter , 
     105# 138 : PropVariant , 
     106# 204 : VarBinary , 
     107# 205 : LongVarBinary , 
     108-777: 'AutoField',                  # Custom number used to identify AutoFields 
     1092   : 'SmallIntegerField',          # SmallInt 
     1103   : 'IntegerField',               # Integer 
     1114   : 'FloatField',                 # Single 
     1125   : 'FloatField',                 # Decimal 
     1136   : 'FloatField',                 # Currency 
     1147   : 'DateField',                  # Date 
     1158   : 'CharField',                  # BSTR 
     11610  : 'IntegerField',               # Error 
     11711  : 'BooleanField',               # Boolean 
     11814  : 'FloatField',                 # Decimal 
     11916  : 'SmallIntegerField',          # TinyInt 
     12017  : 'PositiveSmallIntegerField',  # UnsignedTinyInt 
     12118  : 'PositiveSmallIntegerField',  # UnsignedSmallInt 
     12219  : 'PositiveIntegerField',       # UnsignedInt 
     12320  : 'IntegerField',               # BigInt 
     12464  : 'DateTimeField',              # FileTime 
     12572  : 'CharField',                  # GUID 
     126129 : 'CharField',                  # Char 
     127130 : 'CharField',                  # WChar 
     128131 : 'FloatField',                 # Numeric 
     129133 : 'DateField',                  # DBDate 
     130134 : 'TimeField',                  # DBTime 
     131135 : 'DateTimeField',              # DBTimeStamp 
     132139 : 'FloatField',                 # VarNumeric 
     133200 : 'CharField',                  # VarChar 
     134201 : 'TextField',                  # LongVarChar 
     135202 : 'CharField',                  # VarWChar 
     136203 : 'TextField',                  # LongVarWChar 
     137} 
  • db/backends/mssql/creation.py

    old new  
     1DATA_TYPES = { 
     2    'AutoField':         'int IDENTITY (1, 1)', 
     3    'BooleanField':      'bit', 
     4    'CharField':         'varchar(%(maxlength)s)', 
     5    'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 
     6    'DateField':         'datetime', 
     7    'DateTimeField':     'datetime', 
     8    'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
     9    'FileField':         'varchar(254)', 
     10    'FilePathField':     'varchar(254)', 
     11    'FloatField':        'double precision', 
     12    'ImageField':        'varchar(254)', 
     13    'IntegerField':      'int', 
     14    'IPAddressField':    'char(15)', 
     15    'ManyToManyField':   None, 
     16    'NullBooleanField':  'bit', 
     17    'OneToOneField':     'int', 
     18    'PhoneNumberField':  'varchar(20)', 
     19    #The check must be unique in for the database. Put random so the regresion test not complain about duplicate names 
     20    'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)',     
     21    'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)', 
     22    'SlugField':         'varchar(%(maxlength)s)', 
     23    'SmallIntegerField': 'smallint', 
     24    'TextField':         'text', 
     25    'TimeField':         'datetime', 
     26    'USStateField':      'varchar(2)', 
     27} 
  • db/backends/mssql/base.py

    old new  
     1""" 
     2Alpha Multi-plataform MSSQL database backend for Django. 
     3 
     4Requires pymssql >= v0.8.0: http://pymssql.sourceforge.net/ 
     5""" 
     6if __name__ == '__main__': 
     7    import sys 
     8    import os 
     9     
     10    SETTINGS_MODULE = 'settings' 
     11 
     12    project_dir = r'E:\Proyectos\Python\mysite' 
     13    sys.path.append(os.path.join(project_dir, '..')) 
     14    sys.path.append("..") 
     15    sys.path.pop() 
     16    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' 
     17     
     18 
     19import datetime 
     20from django.db.backends import util 
     21from django.core.exceptions import ImproperlyConfigured 
     22 
     23try: 
     24    import pymssql as Database 
     25except ImportError, e: 
     26    raise ImproperlyConfigured, "Error loading pymssql module: %s" % e 
     27 
     28try: 
     29    import mx 
     30except ImportError: 
     31    mx = None 
     32 
     33try: 
     34    # Only exists in Python 2.4+ 
     35    from threading import local 
     36except ImportError: 
     37    # Import copy of _thread_local.py from Python 2.4 
     38    from django.utils._threading_local import local 
     39 
     40DatabaseError = Database.DatabaseError 
     41IntegrityError = Database.IntegrityError 
     42 
     43#Configure support options: 
     44allows_group_by_ordinal = True 
     45allows_unique_and_pk = True 
     46autoindexes_primary_keys = True 
     47needs_datetime_string_cast = True 
     48needs_upper_for_iops = False 
     49supports_constraints = True 
     50supports_tablespaces = False 
     51uses_case_insensitive_names = False 
     52 
     53def complain(*args, **kwargs): 
     54    raise ImproperlyConfigured, "You haven't set the DATABASE_ENGINE setting yet." 
     55 
     56def ignore(*args, **kwargs): 
     57    pass 
     58 
     59class DatabaseError(Exception): 
     60    pass 
     61 
     62class IntegrityError(DatabaseError): 
     63    pass 
     64 
     65class DatabaseWrapper(local): 
     66    def __init__(self, **kwargs): 
     67        self.connection = None 
     68        self.queries = [] 
     69 
     70    def cursor(self): 
     71        from django.conf import settings 
     72        if self.connection is None: 
     73            if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '': 
     74                raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file." 
     75            if not settings.DATABASE_HOST: 
     76                settings.DATABASE_HOST = "127.0.0.1" 
     77            # TODO: Handle DATABASE_PORT. 
     78            self.connection = Database.connect(host=settings.DATABASE_HOST,user=settings.DATABASE_USER,password=settings.DATABASE_PASSWORD,database=settings.DATABASE_NAME) 
     79         
     80        self.connection.cursor().execute("SET DATEFORMAT ymd\nGO") 
     81         
     82        cursor = self.connection.cursor() 
     83        if settings.DEBUG: 
     84            return util.CursorDebugWrapper(cursor, self) 
     85        return cursor 
     86 
     87    def _commit(self): 
     88        if self.connection is not None: 
     89            return self.connection.commit() 
     90 
     91    def _rollback(self): 
     92        if self.connection is not None: 
     93            return self.connection.rollback() 
     94 
     95    def close(self): 
     96        if self.connection is not None: 
     97            self.connection.close() 
     98            self.connection = None 
     99 
     100''' 
     101    Return the major version of the server. 7=Sql 7,8=Sql2000,9=Sql2005 
     102''' 
     103def version(): 
     104    cur = DatabaseWrapper().cursor() 
     105    cur.execute("SELECT SERVERPROPERTY('ProductVersion')") 
     106     
     107    return int(cur.fetchone()[0].split('.')[0]) 
     108 
     109def quote_name(name): 
     110    if name.startswith('[') and name.endswith(']'): 
     111        return name # Quoting once is enough. 
     112    return '[%s]' % name 
     113 
     114dictfetchone = util.dictfetchone 
     115dictfetchmany = util.dictfetchmany 
     116dictfetchall  = util.dictfetchall 
     117 
     118def get_last_insert_id(cursor, table_name, pk_name): 
     119    cursor.execute("SELECT %s FROM %s WHERE %s = IDENT_CURRENT('%s')" % (pk_name, table_name, pk_name,table_name))  
     120    return cursor.fetchone()[0] 
     121 
     122def get_date_extract_sql(lookup_type, table_name): 
     123    # lookup_type is 'year', 'month', 'day' 
     124    return "DATEPART(%s, %s)" % (lookup_type, table_name) 
     125 
     126def get_date_trunc_sql(lookup_type, field_name): 
     127    # lookup_type is 'year', 'month', 'day' 
     128    if lookup_type=='year': 
     129        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name 
     130    if lookup_type=='month': 
     131        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name) 
     132    if lookup_type=='day': 
     133        return "Convert(datetime, Convert(varchar(12), %s))" % field_name 
     134 
     135def get_datetime_cast_sql(): 
     136    return None 
     137 
     138def get_limit_offset_sql(limit, offset=None): 
     139    # Limits and offset are too complicated to be handled here. 
     140    # Look for a implementation similar to oracle backend 
     141    return "" 
     142 
     143def get_random_function_sql(): 
     144    return "RAND()" 
     145 
     146def get_deferrable_sql(): 
     147    # TODO: Workaround cicle paths... 
     148    # DEFERRABLE and INITALLY DEFFERRED are not apparently supported on constraints 
     149    # This cause SQL Server message 1750, severity 16, state 0, for example in the multiple joins path of comments. 
     150    # So, this left Sql Server as if have not relations :( 
     151    #return " ON DELETE CASCADE ON UPDATE CASCADE" 
     152    return ""  
     153 
     154def get_fulltext_search_sql(field_name): 
     155    raise NotImplementedError 
     156 
     157def get_drop_foreignkey_sql(): 
     158    return "DROP CONSTRAINT" 
     159 
     160def get_pk_default_value(): 
     161    return "DEFAULT" 
     162 
     163def get_max_name_length(): 
     164    return None 
     165 
     166def get_start_transaction_sql(): 
     167    return "BEGIN;" 
     168 
     169def get_tablespace_sql(tablespace, inline=False): 
     170    return "ON %s" % quote_name(tablespace) 
     171 
     172def get_autoinc_sql(table): 
     173    return None 
     174 
     175def get_sql_flush(sql_styler, full_table_list, sequences):  
     176    """Return a list of SQL statements required to remove all data from 
     177    all tables in the database (without actually removing the tables 
     178    themselves) and put the database in an empty 'initial' state 
     179    """ 
     180    # Cannot use TRUNCATE on tables that are reference by a FOREIGN KEY 
     181    # So must use the much slower DELETE 
     182    sql_list = ['%s %s %s;' % \ 
     183                (sql_styler.SQL_KEYWORD('DELETE'), 
     184                sql_styler.SQL_KEYWORD('FROM'), 
     185                sql_styler.SQL_FIELD(quote_name(table)) 
     186                )  for table in full_table_list] 
     187    #The reset the counters on each table. 
     188    sql_list.extend(['%s %s %s %s %s %s %s;' % ( 
     189        sql_styler.SQL_KEYWORD('DBCC'), 
     190        sql_styler.SQL_KEYWORD('CHECKIDENT'), 
     191        sql_styler.SQL_FIELD(quote_name(seq["table"])), 
     192        sql_styler.SQL_KEYWORD('RESEED'), 
     193        sql_styler.SQL_FIELD('1'), 
     194        sql_styler.SQL_KEYWORD('WITH'), 
     195        sql_styler.SQL_KEYWORD('NO_INFOMSGS'), 
     196        ) for seq in sequences]) 
     197     
     198    return sql_list  
     199 
     200def get_sql_sequence_reset(style, model_list): 
     201    "Returns a list of the SQL statements to reset sequences for the given models." 
     202    # No sequence reset required 
     203    return [] 
     204 
     205OPERATOR_MAPPING = { 
     206    'exact': '= %s', 
     207    'iexact': 'LIKE %s', 
     208    'contains': 'LIKE %s', 
     209    'icontains': 'LIKE %s', 
     210    'gt': '> %s', 
     211    'gte': '>= %s', 
     212    'lt': '< %s', 
     213    'lte': '<= %s', 
     214    'startswith': 'LIKE %s', 
     215    'endswith': 'LIKE %s', 
     216    'istartswith': 'LIKE %s', 
     217    'iendswith': 'LIKE %s', 
     218} 
     219 
     220if __name__ == '__main__': 
     221    from mysite.polls.models import Poll, Choice 
     222    from django.contrib.auth.models import User 
     223    from datetime import datetime 
     224    Poll.objects.all() 
     225    p = Poll(question="What's up?", pub_date=datetime.now()) 
     226    p.save() 
     227    print p.id 
     228     
     229    db=DatabaseWrapper() 
     230    print version() 
     231 
     232 
  • db/backends/mssql/client.py

    old new  
     1def runshell(): 
     2    raise NotImplementedError 
  • db/backends/mssql/creation.py

    old new  
     1DATA_TYPES = { 
     2    'AutoField':         'int IDENTITY (1, 1)', 
     3    'BooleanField':      'bit', 
     4    'CharField':         'varchar(%(maxlength)s)', 
     5    'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)', 
     6    'DateField':         'datetime', 
     7    'DateTimeField':     'datetime', 
     8    'DecimalField':      'numeric(%(max_digits)s, %(decimal_places)s)', 
     9    'FileField':         'varchar(254)', 
     10    'FilePathField':     'varchar(254)', 
     11    'FloatField':        'double precision', 
     12    'ImageField':        'varchar(254)', 
     13    'IntegerField':      'int', 
     14    'IPAddressField':    'char(15)', 
     15    'ManyToManyField':   None, 
     16    'NullBooleanField':  'bit', 
     17    'OneToOneField':     'int', 
     18    'PhoneNumberField':  'varchar(20)', 
     19    #The check must be unique in for the database. Put random so the regresion test not complain about duplicate names 
     20    'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)',     
     21    'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(creation_counter)s_%(column)s] CHECK ([%(column)s] > 0)', 
     22    'SlugField':         'varchar(%(maxlength)s)', 
     23    'SmallIntegerField': 'smallint', 
     24    'TextField':         'text', 
     25    'TimeField':         'datetime', 
     26    'USStateField':      'varchar(2)', 
     27} 
  • db/backends/mssql/introspection.py

    old new  
     1def get_table_list(cursor): 
     2    "Returns a list of table names in the current database." 
     3    cursor.execute("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'") 
     4    return [row[2] for row in cursor.fetchall()] 
     5 
     6def _is_auto_field(cursor, table_name, column_name): 
     7    cursor.execute("SELECT COLUMNPROPERTY( OBJECT_ID('%s'),'%s','IsIdentity')" % (table_name, column_name)) 
     8    return cursor.fetchall()[0][0] 
     9 
     10def get_table_description(cursor, table_name, identity_check=True): 
     11    """Returns a description of the table, with the DB-API cursor.description interface. 
     12 
     13    The 'auto_check' parameter has been added to the function argspec. 
     14    If set to True, the function will check each of the table's fields for the 
     15    IDENTITY property (the IDENTITY property is the MSSQL equivalent to an AutoField). 
     16 
     17    When a field is found with an IDENTITY property, it is given a custom field number 
     18    of -777, which maps to the 'AutoField' value in the DATA_TYPES_REVERSE dict. 
     19    """     
     20    cursor.execute("SELECT TOP 1 * FROM %s" % table_name) 
     21    cursor.nextset() 
     22    items = [] 
     23    if identity_check: 
     24        for data in cursor.description: 
     25            if _is_auto_field(cursor, table_name, data[0]): 
     26                data = list(data) 
     27                data[1] = -777 
     28            items.append(list(data)) 
     29    else: 
     30        items = cursor.description 
     31    return items 
     32 
     33def _name_to_index(cursor, table_name): 
     34    """ 
     35    Returns a dictionary of {field_name: field_index} for the given table. 
     36    Indexes are 0-based. 
     37    """ 
     38    return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name, identity_check=False))]) 
     39 
     40def get_relations(cursor, table_name): 
     41    """ 
     42    Returns a dictionary of {field_index: (field_index_other_table, other_table)} 
     43    representing all relationships to the given table. Indexes are 0-based.     
     44    """ 
     45    table_index = _name_to_index(cursor, table_name) 
     46    sql = """SELECT e.COLUMN_NAME AS column_name, 
     47                    c.TABLE_NAME AS referenced_table_name, 
     48                    d.COLUMN_NAME AS referenced_column_name 
     49                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a 
     50                        INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS b 
     51                              ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME 
     52                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS c 
     53                              ON b.UNIQUE_CONSTRAINT_NAME = c.CONSTRAINT_NAME 
     54                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS d 
     55                              ON c.CONSTRAINT_NAME = d.CONSTRAINT_NAME 
     56                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS e 
     57                              ON a.CONSTRAINT_NAME = e.CONSTRAINT_NAME 
     58                    WHERE a.TABLE_NAME = ? AND 
     59                          a.CONSTRAINT_TYPE = 'FOREIGN KEY'""" 
     60    cursor = Cursor(cursor.db.connection) 
     61    cursor.execute(sql, (table_name,)) 
     62    return dict([(table_index[item[0]], (_name_to_index(cursor, item[1])[item[2]], item[1])) 
     63                  for item in cursor.fetchall()]) 
     64     
     65def get_indexes(cursor, table_name): 
     66    """ 
     67    Returns a dictionary of fieldname -> infodict for the given table, 
     68    where each infodict is in the format: 
     69        {'primary_key': boolean representing whether it's the primary key, 
     70         'unique': boolean representing whether it's a unique index} 
     71    """ 
     72    sql = """SELECT b.COLUMN_NAME, a.CONSTRAINT_TYPE 
     73               FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a INNER JOIN 
     74                    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS b 
     75                    ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME AND 
     76                       a.TABLE_NAME = b.TABLE_NAME 
     77               WHERE a.TABLE_NAME = ? AND 
     78                     (CONSTRAINT_TYPE = 'PRIMARY KEY' OR 
     79                      CONSTRAINT_TYPE = 'UNIQUE')""" 
     80    field_names = [item[0] for item in get_table_description(cursor, table_name, identity_check=False)] 
     81    cursor = Cursor(cursor.db.connection) 
     82    cursor.execute(sql, (table_name,)) 
     83    indexes = {} 
     84    results = {} 
     85    data = cursor.fetchall() 
     86    if data: 
     87        results.update(data) 
     88    for field in field_names: 
     89        val = results.get(field, None) 
     90        indexes[field] = dict(primary_key=(val=='PRIMARY KEY'), unique=(val=='UNIQUE')) 
     91    return indexes 
     92 
     93# A reference for the values below: 
     94# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdcstdatatypeenum.asp 
     95DATA_TYPES_REVERSE = { 
     96# 8192 : Array , 
     97# 128 : Binary , 
     98# 9 : IDispatch , 
     99# 12 : Variant , 
     100# 13 : IUnknown , 
     101# 21  : UnsignedBigInt, 
     102# 132 : UserDefined , 
     103# 0   : Empty , 
     104# 136 : Chapter , 
     105# 138 : PropVariant , 
     106# 204 : VarBinary , 
     107# 205 : LongVarBinary , 
     108-777: 'AutoField',                  # Custom number used to identify AutoFields 
     1092   : 'SmallIntegerField',          # SmallInt 
     1103   : 'IntegerField',               # Integer 
     1114   : 'FloatField',                 # Single 
     1125   : 'FloatField',                 # Decimal 
     1136   : 'FloatField',                 # Currency 
     1147   : 'DateField',                  # Date 
     1158   : 'CharField',                  # BSTR 
     11610  : 'IntegerField',               # Error 
     11711  : 'BooleanField',               # Boolean 
     11814  : 'FloatField',                 # Decimal 
     11916  : 'SmallIntegerField',          # TinyInt 
     12017  : 'PositiveSmallIntegerField',  # UnsignedTinyInt 
     12118  : 'PositiveSmallIntegerField',  # UnsignedSmallInt 
     12219  : 'PositiveIntegerField',       # UnsignedInt 
     12320  : 'IntegerField',               # BigInt 
     12464  : 'DateTimeField',              # FileTime 
     12572  : 'CharField',                  # GUID 
     126129 : 'CharField',                  # Char 
     127130 : 'CharField',                  # WChar 
     128131 : 'FloatField',                 # Numeric 
     129133 : 'DateField',                  # DBDate 
     130134 : 'TimeField',                  # DBTime 
     131135 : 'DateTimeField',              # DBTimeStamp 
     132139 : 'FloatField',                 # VarNumeric 
     133200 : 'CharField',                  # VarChar 
     134201 : 'TextField',                  # LongVarChar 
     135202 : 'CharField',                  # VarWChar 
     136203 : 'TextField',                  # LongVarWChar 
     137} 
  • db/backends/util.py

    old new  
     1from django.conf import settings 
    12import datetime 
    23import md5 
    34from time import time 
     
    2223            # formatting with '%' only works with tuples or dicts. 
    2324            if not isinstance(params, (tuple, dict)): 
    2425                params = tuple(params) 
     26            # ado_mssql uses '?' for parameter escaping, so all '?' 
     27            # must be replaced with the standard '%s' if the parameter 
     28            # substitution is going to work. 
     29            if settings.DATABASE_ENGINE == 'ado_mssql': 
     30                sql = sql.replace('?', '%s') 
     31            # There are many situations that will cause the string 
     32            # substituion below to fail (e.g. wildcard characters '%' 
     33            # in LIKE queries).  Instead of attempting to figure out 
     34            # the many variations that can cause an error, the string substition 
     35            # will be attempted first; if it fails, then the sql 
     36            # and its parameters will be combined into a string similar to 
     37            # the one created in the executemany function below. 
     38            try: 
     39                sql = sql % tuple(params) 
     40            except: 
     41                sql = '%s SQL: %s' % (sql, str(tuple(params))) 
    2542            self.db.queries.append({ 
    26                 'sql': sql % params
     43                'sql': sql
    2744                'time': "%.3f" % (stop - start), 
    2845            }) 
    2946 
  • db/models/base.py

    old new  
    239239                    (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column))) 
    240240                db_values.append(getattr(self, self._meta.order_with_respect_to.attname)) 
    241241            if db_values: 
     242                if pk_set and (settings.DATABASE_ENGINE=="ado_mssql" or settings.DATABASE_ENGINE=="mssql"): 
     243                    # You can't insert an auto value into a column unless you do 
     244                    # this in MSSQL 
     245                    # TODO: Only works for auto-id's... how chek it properly? 
     246                    if self._meta.pk.column == 'id': 
     247                        cursor.execute("SET IDENTITY_INSERT %s ON" % \ 
     248                            backend.quote_name(self._meta.db_table)) 
     249                     
    242250                cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \ 
    243251                    (backend.quote_name(self._meta.db_table), ','.join(field_names), 
    244252                    ','.join(placeholders)), db_values) 
     253                     
     254                if pk_set and (settings.DATABASE_ENGINE=="ado_mssql" or settings.DATABASE_ENGINE=="mssql"): 
     255                    if self._meta.pk.column == 'id': 
     256                        cursor.execute("SET IDENTITY_INSERT %s OFF" %\ 
     257                            backend.quote_name(self._meta.db_table)) 
    245258            else: 
    246259                # Create a new record with defaults for everything. 
    247260                cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % 
  • db/models/fields/__init__.py

    old new  
    541541        if value is not None: 
    542542            # MySQL will throw a warning if microseconds are given, because it 
    543543            # doesn't support microseconds. 
    544             if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 
     544            if settings.DATABASE_ENGINE in ('mysql', 'ado_mssql','mssql') and hasattr(value, 'microsecond'): 
    545545                value = value.replace(microsecond=0) 
    546546            value = str(value) 
    547547        return Field.get_db_prep_save(self, value) 
    548548 
    549549    def get_db_prep_lookup(self, lookup_type, value): 
     550        # MSSQL doesn't like microseconds. 
     551        if settings.DATABASE_ENGINE in ('mysql', 'ado_mssql','mssql') and hasattr(value, 'microsecond'): 
     552            value = value.replace(microsecond=0) 
    550553        if lookup_type == 'range': 
    551554            value = [str(v) for v in value] 
    552555        else: 
     
    908911        # Casts dates into string format for entry into database. 
    909912        if value is not None: 
    910913            # MySQL will throw a warning if microseconds are given, because it 
    911             # doesn't support microseconds. 
    912             if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 
     914            # doesn't support microseconds. Ditto MSSQL 
     915            if settings.DATABASE_ENGINE in ('mysql', 'ado_mssql','mssql') \ 
     916                            and hasattr(value, 'microsecond'): 
    913917                value = value.replace(microsecond=0) 
    914918            if settings.DATABASE_ENGINE == 'oracle': 
    915919                # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field.