Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #225 -- Added first stab at MS SQL Server support (via ADO). Th…

…anks to gmilas@gmail.com for the patch

git-svn-id: http://code.djangoproject.com/svn/django/trunk@879 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 24154b216682dfef7ff647a5c2f698b89ba429a6 1 parent 8254a7a
Adrian Holovaty authored October 15, 2005
12  django/conf/global_settings.py
@@ -45,12 +45,12 @@
45 45
 SEND_BROKEN_LINK_EMAILS = False
46 46
 
47 47
 # Database connection info.
48  
-DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', or 'sqlite3'.
49  
-DATABASE_NAME = ''
50  
-DATABASE_USER = ''
51  
-DATABASE_PASSWORD = ''
52  
-DATABASE_HOST = ''             # Set to empty string for localhost.
53  
-DATABASE_PORT = ''             # Set to empty string for default.
  48
+DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
  49
+DATABASE_NAME = ''             # Or path to database file if using sqlite3.
  50
+DATABASE_USER = ''             # Not used with sqlite3.
  51
+DATABASE_PASSWORD = ''         # Not used with sqlite3.
  52
+DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
  53
+DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
54 54
 
55 55
 # Host for sending e-mail.
56 56
 EMAIL_HOST = 'localhost'
2  django/conf/project_template/settings/main.py
@@ -10,7 +10,7 @@
10 10
 
11 11
 LANGUAGE_CODE = 'en-us'
12 12
 
13  
-DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', or 'sqlite3'.
  13
+DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
14 14
 DATABASE_NAME = ''             # Or path to database file if using sqlite3.
15 15
 DATABASE_USER = ''             # Not used with sqlite3.
16 16
 DATABASE_PASSWORD = ''         # Not used with sqlite3.
153  django/core/db/backends/ado_mssql.py
... ...
@@ -0,0 +1,153 @@
  1
+"""
  2
+ADO MSSQL database backend for Django.
  3
+
  4
+Requires adodbapi 2.0.1: http://adodbapi.sourceforge.net/
  5
+"""
  6
+
  7
+from django.core.db import base
  8
+from django.core.db.dicthelpers import *
  9
+import adodbapi as Database
  10
+import datetime
  11
+try:
  12
+    import mx
  13
+except ImportError:
  14
+    mx = None
  15
+
  16
+DatabaseError = Database.DatabaseError
  17
+
  18
+# We need to use a special Cursor class because adodbapi expects question-mark
  19
+# param style, but Django expects "%s". This cursor converts question marks to
  20
+# format-string style.
  21
+class Cursor(Database.Cursor):
  22
+    def executeHelper(self, operation, isStoredProcedureCall, parameters=None):
  23
+        if parameters is not None and "%s" in operation:
  24
+            operation = operation.replace("%s", "?")
  25
+        Database.Cursor.executeHelper(self, operation, isStoredProcedureCall, parameters)
  26
+
  27
+class Connection(Database.Connection):
  28
+    def cursor(self):
  29
+        return Cursor(self)
  30
+Database.Connection = Connection
  31
+
  32
+origCVtoP = Database.convertVariantToPython
  33
+def variantToPython(variant, adType):
  34
+    if type(variant) == bool and adType == 11:
  35
+        return variant  # bool not 1/0
  36
+    res = origCVtoP(variant, adType)
  37
+    if mx is not None and type(res) == mx.DateTime.mxDateTime.DateTimeType:
  38
+        # Convert ms.DateTime objects to Python datetime.datetime objects.
  39
+        tv = list(res.tuple()[:7])
  40
+        tv[-2] = int(tv[-2])
  41
+        return datetime.datetime(*tuple(tv))
  42
+    if type(res) == float and str(res)[-2:] == ".0":
  43
+        return int(res) # If float but int, then int.
  44
+    return res
  45
+Database.convertVariantToPython = variantToPython
  46
+
  47
+class DatabaseWrapper:
  48
+    def __init__(self):
  49
+        self.connection = None
  50
+        self.queries = []
  51
+
  52
+    def cursor(self):
  53
+        from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG
  54
+        if self.connection is None:
  55
+            if DATABASE_NAME == '' or DATABASE_USER == '':
  56
+                from django.core.exceptions import ImproperlyConfigured
  57
+                raise ImproperlyConfigured, "You need to specify both DATABASE_NAME and DATABASE_USER in your Django settings file."
  58
+            if not DATABASE_HOST:
  59
+                DATABASE_HOST = "127.0.0.1"
  60
+            # TODO: Handle DATABASE_PORT.
  61
+            conn_string = "PROVIDER=SQLOLEDB;DATA SOURCE=%s;UID=%s;PWD=%s;DATABASE=%s" % (DATABASE_HOST, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME)
  62
+            self.connection = Database.connect(conn_string)
  63
+        cursor = self.connection.cursor()
  64
+        if DEBUG:
  65
+            return base.CursorDebugWrapper(cursor, self)
  66
+        return cursor
  67
+
  68
+    def commit(self):
  69
+        return self.connection.commit()
  70
+
  71
+    def rollback(self):
  72
+        if self.connection:
  73
+            return self.connection.rollback()
  74
+
  75
+    def close(self):
  76
+        if self.connection is not None:
  77
+            self.connection.close()
  78
+            self.connection = None
  79
+
  80
+def get_last_insert_id(cursor, table_name, pk_name):
  81
+    cursor.execute("SELECT %s FROM %s WHERE %s = @@IDENTITY" % (pk_name, table_name, pk_name))
  82
+    return cursor.fetchone()[0]
  83
+
  84
+def get_date_extract_sql(lookup_type, table_name):
  85
+    # lookup_type is 'year', 'month', 'day'
  86
+    return "DATEPART(%s, %s)" % (lookup_type, table_name)
  87
+
  88
+def get_date_trunc_sql(lookup_type, field_name):
  89
+    # lookup_type is 'year', 'month', 'day'
  90
+    if lookup_type=='year':
  91
+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/01/01')" % field_name
  92
+    if lookup_type=='month':
  93
+        return "Convert(datetime, Convert(varchar, DATEPART(year, %s)) + '/' + Convert(varchar, DATEPART(month, %s)) + '/01')" % (field_name, field_name)
  94
+    if lookup_type=='day':
  95
+        return "Convert(datetime, Convert(varchar(12), %s))" % field_name
  96
+
  97
+def get_limit_offset_sql(limit, offset=None):
  98
+    # TODO: This is a guess. Make sure this is correct.
  99
+    sql = "LIMIT %s" % limit
  100
+    if offset and offset != 0:
  101
+        sql += " OFFSET %s" % offset
  102
+    return sql
  103
+
  104
+def get_random_function_sql():
  105
+    # TODO: This is a guess. Make sure this is correct.
  106
+    return "RANDOM()"
  107
+
  108
+def get_relations(cursor, table_name):
  109
+    raise NotImplementedError
  110
+
  111
+OPERATOR_MAPPING = {
  112
+    'exact': '=',
  113
+    'iexact': 'LIKE',
  114
+    'contains': 'LIKE',
  115
+    'icontains': 'LIKE',
  116
+    'ne': '!=',
  117
+    'gt': '>',
  118
+    'gte': '>=',
  119
+    'lt': '<',
  120
+    'lte': '<=',
  121
+    'startswith': 'LIKE',
  122
+    'endswith': 'LIKE',
  123
+    'istartswith': 'LIKE',
  124
+    'iendswith': 'LIKE',
  125
+}
  126
+
  127
+DATA_TYPES = {
  128
+    'AutoField':         'int IDENTITY (1, 1)',
  129
+    'BooleanField':      'bit',
  130
+    'CharField':         'varchar(%(maxlength)s)',
  131
+    'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
  132
+    'DateField':         'smalldatetime',
  133
+    'DateTimeField':     'smalldatetime',
  134
+    'EmailField':        'varchar(75)',
  135
+    'FileField':         'varchar(100)',
  136
+    'FilePathField':     'varchar(100)',
  137
+    'FloatField':        'numeric(%(max_digits)s, %(decimal_places)s)',
  138
+    'ImageField':        'varchar(100)',
  139
+    'IntegerField':      'int',
  140
+    'IPAddressField':    'char(15)',
  141
+    'ManyToManyField':   None,
  142
+    'NullBooleanField':  'bit',
  143
+    'OneToOneField':     'int',
  144
+    'PhoneNumberField':  'varchar(20)',
  145
+    'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(name)s] CHECK ([%(name)s] > 0)',
  146
+    'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(name)s] CHECK ([%(name)s] > 0)',
  147
+    'SlugField':         'varchar(50)',
  148
+    'SmallIntegerField': 'smallint',
  149
+    'TextField':         'text',
  150
+    'TimeField':         'time',
  151
+    'URLField':          'varchar(200)',
  152
+    'USStateField':      'varchar(2)',
  153
+}

0 notes on commit 24154b2

Please sign in to comment.
Something went wrong with that request. Please try again.