Ticket #2358: mssql_update8a.diff

File mssql_update8a.diff, 14.5 KB (added by wycharon@…, 8 years ago)

full pacth for typo. i am sorry. it's my mistake for the typo. i will re upload the mssql_update7.diff

  • db/models/base.py

     
    170170        record_exists = True
    171171        if pk_val is not None:
    172172            # Determine whether a record with the primary key already exists.
    173             cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \
     173            cursor.execute("SELECT 1 FROM %s WHERE %s=%%s" %
    174174                (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val])
    175175            # If it does already exist, do an UPDATE.
    176176            if cursor.fetchone():
  • db/models/fields/__init__.py

     
    519519        if value is not None:
    520520            # MySQL will throw a warning if microseconds are given, because it
    521521            # doesn't support microseconds.
    522             if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
     522            if (settings.DATABASE_ENGINE == 'mysql' or settings.DATABASE_ENGINE == 'ado_mssql') and hasattr(value, 'microsecond'):
    523523                value = value.replace(microsecond=0)
    524524            value = str(value)
    525525        return Field.get_db_prep_save(self, value)
    526526
    527527    def get_db_prep_lookup(self, lookup_type, value):
     528        # MSSQL doesn't like microseconds.
     529        if settings.DATABASE_ENGINE == 'ado_mssql' and hasattr(value, 'microsecond'):
     530            value = value.replace(microsecond=0)
    528531        if lookup_type == 'range':
    529532            value = [str(v) for v in value]
    530533        else:
     
    803806        if value is not None:
    804807            # MySQL will throw a warning if microseconds are given, because it
    805808            # doesn't support microseconds.
    806             if settings.DATABASE_ENGINE == 'mysql':
     809            if settings.DATABASE_ENGINE == 'mysql' or settings.DATABASE_ENGINE == 'ado_mssql':
    807810                value = value.replace(microsecond=0)
    808811            value = str(value)
    809812        return Field.get_db_prep_save(self, value)
  • db/backends/ado_mssql/base.py

     
    33
    44Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/
    55"""
     6import pythoncom
    67
     8from django.conf import settings
    79from django.db.backends import util
     10
    811try:
    9     import adodbapi as Database
     12    import adodbapi.adodbapi as Database
    1013except ImportError, e:
    1114    from django.core.exceptions import ImproperlyConfigured
    1215    raise ImproperlyConfigured, "Error loading adodbapi module: %s" % e
     
    2528    def executeHelper(self, operation, isStoredProcedureCall, parameters=None):
    2629        if parameters is not None and "%s" in operation:
    2730            operation = operation.replace("%s", "?")
     31        pythoncom.CoInitialize()
    2832        Database.Cursor.executeHelper(self, operation, isStoredProcedureCall, parameters)
     33        pythoncom.CoUninitialize()
    2934
    3035class Connection(Database.Connection):
    3136    def cursor(self):
     
    4449        return datetime.datetime(*tuple(tv))
    4550    if type(res) == float and str(res)[-2:] == ".0":
    4651        return int(res) # If float but int, then int.
     52    if type(res) == unicode:
     53        return res.encode(settings.DEFAULT_CHARSET)
    4754    return res
    4855Database.convertVariantToPython = variantToPython
    4956
     
    6976                settings.DATABASE_HOST = "127.0.0.1"
    7077            # TODO: Handle DATABASE_PORT.
    7178            conn_string = "PROVIDER=SQLOLEDB;DATA SOURCE=%s;UID=%s;PWD=%s;DATABASE=%s" % (settings.DATABASE_HOST, settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
     79            pythoncom.CoInitialize()
    7280            self.connection = Database.connect(conn_string)
    73         cursor = self.connection.cursor()
     81            pythoncom.CoUninitialize()
     82       
     83        cursor = Cursor(self.connection)
    7484        if settings.DEBUG:
    7585            return util.CursorDebugWrapper(cursor, self)
    7686        return cursor
     
    99109dictfetchall  = util.dictfetchall
    100110
    101111def get_last_insert_id(cursor, table_name, pk_name):
    102     cursor.execute("SELECT %s FROM %s WHERE %s = @@IDENTITY" % (pk_name, table_name, pk_name))
     112    cursor.execute("SELECT %s FROM %s WHERE %s = IDENT_CURRENT('%s')" % (pk_name, table_name, pk_name,table_name))
    103113    return cursor.fetchone()[0]
    104114
    105115def get_date_extract_sql(lookup_type, table_name):
     
    117127
    118128def get_limit_offset_sql(limit, offset=None):
    119129    # TODO: This is a guess. Make sure this is correct.
    120     sql = "LIMIT %s" % limit
    121     if offset and offset != 0:
    122         sql += " OFFSET %s" % offset
    123     return sql
     130    # should be "SELECT TOP %s" % limit
     131    # not LIMIT at the end
     132    return ""
     133    #sql = "LIMIT %s" % limit
     134    #if offset and offset != 0:
     135    #    sql += " OFFSET %s" % offset
     136    #return sql
    124137
    125138def get_random_function_sql():
    126139    return "RAND()"
  • db/backends/ado_mssql/introspection.py

     
     1# Tested against MSDE and SQL Server 2000 using adodbapi 2.0.1
     2# Python 2.4.2 and 2.4.3 were used during testing.
     3from django.db.backends.ado_mssql.base import Cursor
     4
    15def get_table_list(cursor):
    2     raise NotImplementedError
     6    "Returns a list of table names in the current database."
     7    print "# Note: Any fields that are named 'id', are of type 'AutoField', and"
     8    print "# and are Primary Keys will NOT appear in the model output below."
     9    print "# By default Django assumes that the each model's Primary Key is an "
     10    print "# AutoField with a name of 'id', so there is no need to add it to the"
     11    print "# model description."
     12    print
     13    cursor.execute("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
     14    return [row[2] for row in cursor.fetchall()]
    315
    4 def get_table_description(cursor, table_name):
    5     raise NotImplementedError
     16def _is_auto_field(cursor, table_name, column_name):
     17    cursor.execute("SELECT COLUMNPROPERTY( OBJECT_ID('%s'),'%s','IsIdentity')" % (table_name, column_name))
     18    return cursor.fetchall()[0][0]
    619
     20def get_table_description(cursor, table_name, identity_check=True):
     21    """Returns a description of the table, with the DB-API cursor.description interface.
     22
     23    The 'auto_check' parameter has been added to the function argspec.
     24    If set to True, the function will check each of the table's fields for the
     25    IDENTITY property (the IDENTITY property is the MSSQL equivalent to an AutoField).
     26
     27    When a field is found with an IDENTITY property, it is given a custom field number
     28    of -777, which maps to the 'AutoField' value in the DATA_TYPES_REVERSE dict.
     29    """   
     30    cursor.execute("SELECT TOP 1 * FROM %s" % table_name)
     31    cursor.nextset()
     32    items = []
     33    if identity_check:
     34        for data in cursor.description:
     35            if _is_auto_field(cursor, table_name, data[0]):
     36                data = list(data)
     37                data[1] = -777
     38            items.append(list(data))
     39    else:
     40        items = cursor.description
     41    return items
     42
     43def _name_to_index(cursor, table_name):
     44    """
     45    Returns a dictionary of {field_name: field_index} for the given table.
     46    Indexes are 0-based.
     47    """
     48    return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name, identity_check=False))])
     49
    750def get_relations(cursor, table_name):
    8     raise NotImplementedError
    9 
     51    """
     52    Returns a dictionary of {field_index: (field_index_other_table, other_table)}
     53    representing all relationships to the given table. Indexes are 0-based.   
     54    """
     55    table_index = _name_to_index(cursor, table_name)
     56    sql = """SELECT e.COLUMN_NAME AS column_name,
     57                    c.TABLE_NAME AS referenced_table_name,
     58                    d.COLUMN_NAME AS referenced_column_name
     59                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a
     60                        INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS b
     61                              ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME
     62                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE AS c
     63                              ON b.UNIQUE_CONSTRAINT_NAME = c.CONSTRAINT_NAME
     64                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS d
     65                              ON c.CONSTRAINT_NAME = d.CONSTRAINT_NAME
     66                        INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS e
     67                              ON a.CONSTRAINT_NAME = e.CONSTRAINT_NAME
     68                    WHERE a.TABLE_NAME = ? AND
     69                          a.CONSTRAINT_TYPE = 'FOREIGN KEY'"""
     70    cursor = Cursor(cursor.db.connection)
     71    cursor.execute(sql, (table_name,))
     72    return dict([(table_index[item[0]], (_name_to_index(cursor, item[1])[item[2]], item[1]))
     73                  for item in cursor.fetchall()])
     74   
    1075def get_indexes(cursor, table_name):
    11     raise NotImplementedError
     76    """
     77    Returns a dictionary of fieldname -> infodict for the given table,
     78    where each infodict is in the format:
     79        {'primary_key': boolean representing whether it's the primary key,
     80         'unique': boolean representing whether it's a unique index}
     81    """
     82    sql = """SELECT b.COLUMN_NAME, a.CONSTRAINT_TYPE
     83               FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS a INNER JOIN
     84                    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS b
     85                    ON a.CONSTRAINT_NAME = b.CONSTRAINT_NAME AND
     86                       a.TABLE_NAME = b.TABLE_NAME
     87               WHERE a.TABLE_NAME = ? AND
     88                     (CONSTRAINT_TYPE = 'PRIMARY KEY' OR
     89                      CONSTRAINT_TYPE = 'UNIQUE')"""
     90    field_names = [item[0] for item in get_table_description(cursor, table_name, identity_check=False)]
     91    cursor = Cursor(cursor.db.connection)
     92    cursor.execute(sql, (table_name,))
     93    indexes = {}
     94    results = {}
     95    data = cursor.fetchall()
     96    if data:
     97        results.update(data)
     98    for field in field_names:
     99        val = results.get(field, None)
     100        indexes[field] = dict(primary_key=(val=='PRIMARY KEY'), unique=(val=='UNIQUE'))
     101    return indexes
    12102
    13 DATA_TYPES_REVERSE = {}
     103# A reference for the values below:
     104# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/mdcstdatatypeenum.asp
     105DATA_TYPES_REVERSE = {
     106# 8192 : Array ,
     107# 128 : Binary ,
     108# 9 : IDispatch ,
     109# 12 : Variant ,
     110# 13 : IUnknown ,
     111# 21  : UnsignedBigInt,
     112# 132 : UserDefined ,
     113# 0   : Empty ,
     114# 136 : Chapter ,
     115# 138 : PropVariant ,
     116# 204 : VarBinary ,
     117# 205 : LongVarBinary ,
     118-777: 'AutoField',                  # Custom number used to identify AutoFields
     1192   : 'SmallIntegerField',          # SmallInt
     1203   : 'IntegerField',               # Integer
     1214   : 'FloatField',                 # Single
     1225   : 'FloatField',                 # Decimal
     1236   : 'FloatField',                 # Currency
     1247   : 'DateField',                  # Date
     1258   : 'CharField',                  # BSTR
     12610  : 'IntegerField',               # Error
     12711  : 'BooleanField',               # Boolean
     12814  : 'FloatField',                 # Decimal
     12916  : 'SmallIntegerField',          # TinyInt
     13017  : 'PositiveSmallIntegerField',  # UnsignedTinyInt
     13118  : 'PositiveSmallIntegerField',  # UnsignedSmallInt
     13219  : 'PositiveIntegerField',       # UnsignedInt
     13320  : 'IntegerField',               # BigInt
     13464  : 'DateTimeField',              # FileTime
     13572  : 'CharField',                  # GUID
     136129 : 'CharField',                  # Char
     137130 : 'CharField',                  # WChar
     138131 : 'FloatField',                 # Numeric
     139133 : 'DateField',                  # DBDate
     140134 : 'TimeField',                  # DBTime
     141135 : 'DateTimeField',              # DBTimeStamp
     142139 : 'FloatField',                 # VarNumeric
     143200 : 'CharField',                  # VarChar
     144201 : 'TextField',                  # LongVarChar
     145202 : 'CharField',                  # VarWChar
     146203 : 'TextField',                  # LongVarWChar
     147}
  • db/backends/util.py

     
     1from django.conf import settings
    12import datetime
    23from time import time
    34
     
    1617            # formatting with '%' only works with tuples or dicts.
    1718            if not isinstance(params, (tuple, dict)):
    1819                params = tuple(params)
     20            # ado_mssql uses '?' for parameter escaping, so all '?'
     21            # must be replaced with the standard '%s' if the parameter
     22            # substitution is going to work.
     23            if settings.DATABASE_ENGINE == 'ado_mssql':
     24                sql = sql.replace('?', '%s')
     25            # There are many situations that will cause the string
     26            # substituion below to fail (e.g. wildcard characters '%'
     27            # in LIKE queries).  Instead of attempting to figure out
     28            # the many variations that can cause an error, the string substition
     29            # will be attempted first; if it fails, then the sql
     30            # and its parameters will be combined into a string similar to
     31            # the one created in the executemany function below.
     32            try:
     33                sql = sql % tuple(params)
     34            except:
     35                sql = '%s SQL: %s' % (sql, str(tuple(params)))
    1936            self.db.queries.append({
    20                 'sql': sql % params,
     37                'sql': sql,
    2138                'time': "%.3f" % (stop - start),
    2239            })
    2340
  • contrib/sessions/middleware.py

     
    5353                self._session_cache = {}
    5454            else:
    5555                try:
     56                    datenow = datetime.datetime.now()
     57                    if hasattr(datenow, 'microsecond'):
     58                        datenow = datenow.replace(microsecond=0)
    5659                    s = Session.objects.get(session_key=self.session_key,
    57                         expire_date__gt=datetime.datetime.now())
     60                        expire_date__gt=datenow)
    5861                    self._session_cache = s.get_decoded()
    5962                except (Session.DoesNotExist, SuspiciousOperation):
    6063                    self._session_cache = {}
Back to Top