Ticket #2358: mssql_update6b.diff
File mssql_update6b.diff, 14.2 KB (added by , 18 years ago) |
---|
-
db/models/base.py
170 170 record_exists = True 171 171 if pk_val is not None: 172 172 # 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" % 174 174 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val]) 175 175 # If it does already exist, do an UPDATE. 176 176 if cursor.fetchone(): -
db/models/fields/__init__.py
519 519 if value is not None: 520 520 # MySQL will throw a warning if microseconds are given, because it 521 521 # 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'): 523 523 value = value.replace(microsecond=0) 524 524 value = str(value) 525 525 return Field.get_db_prep_save(self, value) 526 526 527 527 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) 528 531 if lookup_type == 'range': 529 532 value = [str(v) for v in value] 530 533 else: … … 803 806 if value is not None: 804 807 # MySQL will throw a warning if microseconds are given, because it 805 808 # doesn't support microseconds. 806 if settings.DATABASE_ENGINE == 'mysql' :809 if settings.DATABASE_ENGINE == 'mysql' or settings.DATABASE_ENGINE == 'ado_mssql': 807 810 value = value.replace(microsecond=0) 808 811 value = str(value) 809 812 return Field.get_db_prep_save(self, value) -
db/backends/ado_mssql/base.py
3 3 4 4 Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/ 5 5 """ 6 import pythoncom 6 7 8 from django.conf import settings 7 9 from django.db.backends import util 10 8 11 try: 9 import adodbapi as Database12 import adodbapi.adodbapi as Database 10 13 except ImportError, e: 11 14 from django.core.exceptions import ImproperlyConfigured 12 15 raise ImproperlyConfigured, "Error loading adodbapi module: %s" % e … … 25 28 def executeHelper(self, operation, isStoredProcedureCall, parameters=None): 26 29 if parameters is not None and "%s" in operation: 27 30 operation = operation.replace("%s", "?") 31 pythoncom.CoInitialize() 28 32 Database.Cursor.executeHelper(self, operation, isStoredProcedureCall, parameters) 33 pythoncom.CoUninitialize() 29 34 30 35 class Connection(Database.Connection): 31 36 def cursor(self): … … 44 49 return datetime.datetime(*tuple(tv)) 45 50 if type(res) == float and str(res)[-2:] == ".0": 46 51 return int(res) # If float but int, then int. 52 if type(res) == unicode: 53 return res.encode(settings.DEFAULT_CHARSET) 47 54 return res 48 Database.convertVariantToPython = variantToPyth on55 Database.convertVariantToPython = variantToPythn 49 56 50 57 try: 51 58 # Only exists in Python 2.4+ … … 69 76 settings.DATABASE_HOST = "127.0.0.1" 70 77 # TODO: Handle DATABASE_PORT. 71 78 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() 72 80 self.connection = Database.connect(conn_string) 73 cursor = self.connection.cursor() 81 pythoncom.CoUninitialize() 82 83 cursor = Cursor(self.connection) 74 84 if settings.DEBUG: 75 85 return util.CursorDebugWrapper(cursor, self) 76 86 return cursor … … 117 127 118 128 def get_limit_offset_sql(limit, offset=None): 119 129 # 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 124 137 125 138 def get_random_function_sql(): 126 139 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. 3 from django.db.backends.ado_mssql.base import Cursor 4 1 5 def 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()] 3 15 4 def get_table_description(cursor, table_name): 5 raise NotImplementedError 16 def _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] 6 19 20 def 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 43 def _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 7 50 def 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 10 75 def 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 12 102 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 105 DATA_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 119 2 : 'SmallIntegerField', # SmallInt 120 3 : 'IntegerField', # Integer 121 4 : 'FloatField', # Single 122 5 : 'FloatField', # Decimal 123 6 : 'FloatField', # Currency 124 7 : 'DateField', # Date 125 8 : 'CharField', # BSTR 126 10 : 'IntegerField', # Error 127 11 : 'BooleanField', # Boolean 128 14 : 'FloatField', # Decimal 129 16 : 'SmallIntegerField', # TinyInt 130 17 : 'PositiveSmallIntegerField', # UnsignedTinyInt 131 18 : 'PositiveSmallIntegerField', # UnsignedSmallInt 132 19 : 'PositiveIntegerField', # UnsignedInt 133 20 : 'IntegerField', # BigInt 134 64 : 'DateTimeField', # FileTime 135 72 : 'CharField', # GUID 136 129 : 'CharField', # Char 137 130 : 'CharField', # WChar 138 131 : 'FloatField', # Numeric 139 133 : 'DateField', # DBDate 140 134 : 'TimeField', # DBTime 141 135 : 'DateTimeField', # DBTimeStamp 142 139 : 'FloatField', # VarNumeric 143 200 : 'CharField', # VarChar 144 201 : 'TextField', # LongVarChar 145 202 : 'CharField', # VarWChar 146 203 : 'TextField', # LongVarWChar 147 } -
db/backends/util.py
1 from django.conf import settings 1 2 import datetime 2 3 from time import time 3 4 … … 16 17 # formatting with '%' only works with tuples or dicts. 17 18 if not isinstance(params, (tuple, dict)): 18 19 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))) 19 36 self.db.queries.append({ 20 'sql': sql % params,37 'sql': sql, 21 38 'time': "%.3f" % (stop - start), 22 39 }) 23 40 -
contrib/sessions/middleware.py
53 53 self._session_cache = {} 54 54 else: 55 55 try: 56 datenow = datetime.datetime.now() 57 if hasattr(datenow, 'microsecond'): 58 datenow = datenow.replace(microsecond=0) 56 59 s = Session.objects.get(session_key=self.session_key, 57 expire_date__gt=date time.datetime.now())60 expire_date__gt=datenow) 58 61 self._session_cache = s.get_decoded() 59 62 except (Session.DoesNotExist, SuspiciousOperation): 60 63 self._session_cache = {}