App Engine Python SDK version 1.9.12
[gae.git] / python / lib / django-0.96 / django / db / backends / ado_mssql / base.py
blob8dcb98ce6122d044d337a1a452db07d3577cbb14
1 """
2 ADO MSSQL database backend for Django.
4 Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/
5 """
7 from django.db.backends import util
8 try:
9 import adodbapi as Database
10 except ImportError, e:
11 from django.core.exceptions import ImproperlyConfigured
12 raise ImproperlyConfigured, "Error loading adodbapi module: %s" % e
13 import datetime
14 try:
15 import mx
16 except ImportError:
17 mx = None
19 DatabaseError = Database.DatabaseError
21 # We need to use a special Cursor class because adodbapi expects question-mark
22 # param style, but Django expects "%s". This cursor converts question marks to
23 # format-string style.
24 class Cursor(Database.Cursor):
25 def executeHelper(self, operation, isStoredProcedureCall, parameters=None):
26 if parameters is not None and "%s" in operation:
27 operation = operation.replace("%s", "?")
28 Database.Cursor.executeHelper(self, operation, isStoredProcedureCall, parameters)
30 class Connection(Database.Connection):
31 def cursor(self):
32 return Cursor(self)
33 Database.Connection = Connection
35 origCVtoP = Database.convertVariantToPython
36 def variantToPython(variant, adType):
37 if type(variant) == bool and adType == 11:
38 return variant # bool not 1/0
39 res = origCVtoP(variant, adType)
40 if mx is not None and type(res) == mx.DateTime.mxDateTime.DateTimeType:
41 # Convert ms.DateTime objects to Python datetime.datetime objects.
42 tv = list(res.tuple()[:7])
43 tv[-2] = int(tv[-2])
44 return datetime.datetime(*tuple(tv))
45 if type(res) == float and str(res)[-2:] == ".0":
46 return int(res) # If float but int, then int.
47 return res
48 Database.convertVariantToPython = variantToPython
50 try:
51 # Only exists in Python 2.4+
52 from threading import local
53 except ImportError:
54 # Import copy of _thread_local.py from Python 2.4
55 from django.utils._threading_local import local
57 class DatabaseWrapper(local):
58 def __init__(self, **kwargs):
59 self.connection = None
60 self.queries = []
62 def cursor(self):
63 from django.conf import settings
64 if self.connection is None:
65 if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '':
66 from django.core.exceptions import ImproperlyConfigured
67 raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file."
68 if not settings.DATABASE_HOST:
69 settings.DATABASE_HOST = "127.0.0.1"
70 # TODO: Handle DATABASE_PORT.
71 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)
72 self.connection = Database.connect(conn_string)
73 cursor = self.connection.cursor()
74 if settings.DEBUG:
75 return util.CursorDebugWrapper(cursor, self)
76 return cursor
78 def _commit(self):
79 if self.connection is not None:
80 return self.connection.commit()
82 def _rollback(self):
83 if self.connection is not None:
84 return self.connection.rollback()
86 def close(self):
87 if self.connection is not None:
88 self.connection.close()
89 self.connection = None
91 supports_constraints = True
93 def quote_name(name):
94 if name.startswith('[') and name.endswith(']'):
95 return name # Quoting once is enough.
96 return '[%s]' % name
98 dictfetchone = util.dictfetchone
99 dictfetchmany = util.dictfetchmany
100 dictfetchall = util.dictfetchall
102 def get_last_insert_id(cursor, table_name, pk_name):
103 cursor.execute("SELECT %s FROM %s WHERE %s = @@IDENTITY" % (pk_name, table_name, pk_name))
104 return cursor.fetchone()[0]
106 def get_date_extract_sql(lookup_type, table_name):
107 # lookup_type is 'year', 'month', 'day'
108 return "DATEPART(%s, %s)" % (lookup_type, table_name)
110 def get_date_trunc_sql(lookup_type, field_name):
111 # lookup_type is 'year', 'month', 'day'
112 if lookup_type=='year':
113 return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name
114 if lookup_type=='month':
115 return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name)
116 if lookup_type=='day':
117 return "Convert(datetime, Convert(varchar(12), %s))" % field_name
119 def get_limit_offset_sql(limit, offset=None):
120 # TODO: This is a guess. Make sure this is correct.
121 sql = "LIMIT %s" % limit
122 if offset and offset != 0:
123 sql += " OFFSET %s" % offset
124 return sql
126 def get_random_function_sql():
127 return "RAND()"
129 def get_deferrable_sql():
130 return " DEFERRABLE INITIALLY DEFERRED"
132 def get_fulltext_search_sql(field_name):
133 raise NotImplementedError
135 def get_drop_foreignkey_sql():
136 return "DROP CONSTRAINT"
138 def get_pk_default_value():
139 return "DEFAULT"
141 def get_sql_flush(sql_styler, full_table_list):
142 """Return a list of SQL statements required to remove all data from
143 all tables in the database (without actually removing the tables
144 themselves) and put the database in an empty 'initial' state
146 # Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
147 # TODO - SQL not actually tested against ADO MSSQL yet!
148 # TODO - autoincrement indices reset required? See other get_sql_flush() implementations
149 sql_list = ['%s %s;' % \
150 (sql_styler.SQL_KEYWORD('TRUNCATE'),
151 sql_styler.SQL_FIELD(quote_name(table))
152 ) for table in full_table_list]
154 OPERATOR_MAPPING = {
155 'exact': '= %s',
156 'iexact': 'LIKE %s',
157 'contains': 'LIKE %s',
158 'icontains': 'LIKE %s',
159 'gt': '> %s',
160 'gte': '>= %s',
161 'lt': '< %s',
162 'lte': '<= %s',
163 'startswith': 'LIKE %s',
164 'endswith': 'LIKE %s',
165 'istartswith': 'LIKE %s',
166 'iendswith': 'LIKE %s',