Skip to content

Commit d50e574

Browse files
committed
Add initial support for SQL Server 2005 (Fixes #21)
1 parent 3e55098 commit d50e574

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

sql_server/pyodbc/base.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
152152
'08S02',
153153
)
154154
_sql_server_versions = {
155+
9: 2005,
155156
10: 2008,
156157
11: 2012,
157158
12: 2014,
@@ -210,6 +211,21 @@ def __init__(self, *args, **kwargs):
210211
def create_cursor(self, name=None):
211212
return CursorWrapper(self.connection.cursor(), self)
212213

214+
def _cursor(self):
215+
new_conn = False
216+
217+
if self.connection is None:
218+
new_conn = True
219+
220+
conn = super()._cursor()
221+
if new_conn:
222+
if self.sql_server_version <= 2005:
223+
self.data_types['DateField'] = 'datetime'
224+
self.data_types['DateTimeField'] = 'datetime'
225+
self.data_types['TimeField'] = 'datetime'
226+
227+
return conn
228+
213229
def get_connection_params(self):
214230
settings_dict = self.settings_dict
215231
if settings_dict['NAME'] == '':
@@ -351,8 +367,7 @@ def init_connection_state(self):
351367
datefirst = options.get('datefirst', 7)
352368
cursor.execute('SET DATEFORMAT ymd; SET DATEFIRST %s' % datefirst)
353369

354-
# http://blogs.msdn.com/b/sqlnativeclient/archive/2008/02/27/microsoft-sql-server-native-client-and-microsoft-sql-server-2008-native-client.aspx
355-
val = cursor.execute('SELECT SYSDATETIME()').fetchone()[0]
370+
val = self.get_system_datetime()
356371
if isinstance(val, str):
357372
raise ImproperlyConfigured(
358373
"The database driver doesn't support modern datatime types.")
@@ -365,6 +380,14 @@ def is_usable(self):
365380
else:
366381
return True
367382

383+
def get_system_datetime(self):
384+
# http://blogs.msdn.com/b/sqlnativeclient/archive/2008/02/27/microsoft-sql-server-native-client-and-microsoft-sql-server-2008-native-client.aspx
385+
with self.temporary_connection() as cursor:
386+
if self.sql_server_version <= 2005:
387+
return cursor.execute('SELECT GETDATE()').fetchone()[0]
388+
else:
389+
return cursor.execute('SELECT SYSDATETIME()').fetchone()[0]
390+
368391
@cached_property
369392
def sql_server_version(self, _known_versions={}):
370393
"""

sql_server/pyodbc/features.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.db.backends.base.features import BaseDatabaseFeatures
2+
from django.utils.functional import cached_property
23

34

45
class DatabaseFeatures(BaseDatabaseFeatures):
@@ -21,7 +22,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
2122
requires_sqlparse_for_splitting = False
2223
supports_ignore_conflicts = False
2324
supports_index_on_text_field = False
24-
supports_nullable_unique_constraints = True
2525
supports_paramstyle_pyformat = False
2626
supports_partially_nullable_unique_constraints = False
2727
supports_regex_backreferencing = False
@@ -32,3 +32,19 @@ class DatabaseFeatures(BaseDatabaseFeatures):
3232
supports_timezones = False
3333
supports_transactions = True
3434
uses_savepoints = True
35+
36+
@cached_property
37+
def has_bulk_insert(self):
38+
return self.connection.sql_server_version > 2005
39+
40+
@cached_property
41+
def supports_nullable_unique_constraints(self):
42+
return self.connection.sql_server_version > 2005
43+
44+
@cached_property
45+
def supports_partial_indexes(self):
46+
return self.connection.sql_server_version > 2005
47+
48+
@cached_property
49+
def supports_functions_in_partial_indexes(self):
50+
return self.connection.sql_server_version > 2005

sql_server/pyodbc/schema.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,9 @@ def _alter_field(self, model, old_field, new_field, old_type, new_type,
321321
self._delete_primary_key(model, strict)
322322
# Added a unique?
323323
if self._unique_should_be_added(old_field, new_field):
324-
if not new_field.many_to_many and new_field.null:
324+
if (self.connection.features.supports_nullable_unique_constraints and
325+
not new_field.many_to_many and new_field.null):
326+
325327
self.execute(
326328
self._create_index_sql(
327329
model, [new_field], sql=self.sql_create_unique_null, suffix="_uniq"
@@ -505,7 +507,9 @@ def add_field(self, model, field):
505507
if definition is None:
506508
return
507509

508-
if not field.many_to_many and field.null and field.unique:
510+
if (self.connection.features.supports_nullable_unique_constraints and
511+
not field.many_to_many and field.null and field.unique):
512+
509513
definition = definition.replace(' UNIQUE', '')
510514
self.deferred_sql.append(self._create_index_sql(
511515
model, [field], sql=self.sql_create_unique_null, suffix="_uniq"
@@ -554,7 +558,9 @@ def create_model(self, model):
554558
if definition is None:
555559
continue
556560

557-
if not field.many_to_many and field.null and field.unique:
561+
if (self.connection.features.supports_nullable_unique_constraints and
562+
not field.many_to_many and field.null and field.unique):
563+
558564
definition = definition.replace(' UNIQUE', '')
559565
self.deferred_sql.append(self._create_index_sql(
560566
model, [field], sql=self.sql_create_unique_null, suffix="_uniq"

0 commit comments

Comments
 (0)