Skip to content

Commit 39128a7

Browse files
committed
add basic support for Windows Azure SQL Database
1 parent 9f9f3fc commit 39128a7

File tree

3 files changed

+48
-14
lines changed

3 files changed

+48
-14
lines changed

django_pyodbc/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
class DatabaseFeatures(BaseDatabaseFeatures):
4545
can_use_chunked_reads = False
4646
can_return_id_from_insert = True
47+
supports_microsecond_precision = False
48+
supports_transactions = True
4749
#uses_savepoints = True
4850

4951

django_pyodbc/creation.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,25 @@ def _create_test_db(self, verbosity, autoclobber):
8686
self.connection.connection.commit()
8787
return test_name
8888

89+
if self.connection.ops.on_azure_sql_db:
90+
self.connection.close()
91+
settings_dict["NAME"] = 'master'
92+
8993
return super(DatabaseCreation, self)._create_test_db(verbosity, autoclobber)
9094

9195
def _destroy_test_db(self, test_database_name, verbosity):
9296
"Internal implementation - remove the test db tables."
9397
if self.connection.test_create:
98+
if self.connection.ops.on_azure_sql_db:
99+
self.connection.close()
100+
self.connection.settings_dict["NAME"] = 'master'
101+
94102
cursor = self.connection.cursor()
95103
self.connection.connection.autocommit = True
96104
#time.sleep(1) # To avoid "database is being accessed by other users" errors.
97-
cursor.execute("ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE " % \
98-
self.connection.ops.quote_name(test_database_name))
105+
if not self.connection.ops.on_azure_sql_db:
106+
cursor.execute("ALTER DATABASE %s SET SINGLE_USER WITH ROLLBACK IMMEDIATE " % \
107+
self.connection.ops.quote_name(test_database_name))
99108
cursor.execute("DROP DATABASE %s" % \
100109
self.connection.ops.quote_name(test_database_name))
101110
else:

django_pyodbc/operations.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import time
44
import decimal
55

6+
EDITION_AZURE_SQL_DB = 5
7+
68
class DatabaseOperations(BaseDatabaseOperations):
79
compiler_module = "django_pyodbc.compiler"
810
def __init__(self, connection):
@@ -13,6 +15,7 @@ def __init__(self, connection):
1315

1416
self.connection = connection
1517
self._ss_ver = None
18+
self._ss_edition = None
1619

1720
def _get_sql_server_ver(self):
1821
"""
@@ -22,8 +25,11 @@ def _get_sql_server_ver(self):
2225
return self._ss_ver
2326
cur = self.connection.cursor()
2427
cur.execute("SELECT CAST(SERVERPROPERTY('ProductVersion') as varchar)")
25-
ver_code = int(cur.fetchone()[0].split('.')[0])
26-
if ver_code >= 10:
28+
ver_code = cur.fetchone()[0]
29+
ver_code = int(ver_code.split('.')[0])
30+
if ver_code >= 11:
31+
self._ss_ver = 2012
32+
elif ver_code == 10:
2733
self._ss_ver = 2008
2834
elif ver_code == 9:
2935
self._ss_ver = 2005
@@ -32,6 +38,15 @@ def _get_sql_server_ver(self):
3238
return self._ss_ver
3339
sql_server_ver = property(_get_sql_server_ver)
3440

41+
def _on_azure_sql_db(self):
42+
if self._ss_edition is not None:
43+
return self._ss_edition == EDITION_AZURE_SQL_DB
44+
cur = self.connection.cursor()
45+
cur.execute("SELECT CAST(SERVERPROPERTY('EngineEdition') as integer)")
46+
self._ss_edition = cur.fetchone()[0]
47+
return self._ss_edition == EDITION_AZURE_SQL_DB
48+
on_azure_sql_db = property(_on_azure_sql_db)
49+
3550
def date_extract_sql(self, lookup_type, field_name):
3651
"""
3752
Given a lookup_type of 'year', 'month', 'day' or 'week_day', returns
@@ -194,16 +209,24 @@ def sql_flush(self, style, tables, sequences):
194209
(self.quote_name(fk[0]), self.quote_name(fk[1])) for fk in fks]
195210
sql_list.extend(['%s %s %s;' % (style.SQL_KEYWORD('DELETE'), style.SQL_KEYWORD('FROM'),
196211
style.SQL_FIELD(self.quote_name(table)) ) for table in tables])
197-
# Then reset the counters on each table.
198-
sql_list.extend(['%s %s (%s, %s, %s) %s %s;' % (
199-
style.SQL_KEYWORD('DBCC'),
200-
style.SQL_KEYWORD('CHECKIDENT'),
201-
style.SQL_FIELD(self.quote_name(seq["table"])),
202-
style.SQL_KEYWORD('RESEED'),
203-
style.SQL_FIELD('%d' % seq['start_id']),
204-
style.SQL_KEYWORD('WITH'),
205-
style.SQL_KEYWORD('NO_INFOMSGS'),
206-
) for seq in seqs])
212+
213+
if self.on_azure_sql_db:
214+
import warnings
215+
warnings.warn("The identity columns will never be reset " \
216+
"on Windows Azure SQL Database.",
217+
RuntimeWarning)
218+
else:
219+
# Then reset the counters on each table.
220+
sql_list.extend(['%s %s (%s, %s, %s) %s %s;' % (
221+
style.SQL_KEYWORD('DBCC'),
222+
style.SQL_KEYWORD('CHECKIDENT'),
223+
style.SQL_FIELD(self.quote_name(seq["table"])),
224+
style.SQL_KEYWORD('RESEED'),
225+
style.SQL_FIELD('%d' % seq['start_id']),
226+
style.SQL_KEYWORD('WITH'),
227+
style.SQL_KEYWORD('NO_INFOMSGS'),
228+
) for seq in seqs])
229+
207230
sql_list.extend(['ALTER TABLE %s CHECK CONSTRAINT %s;' % \
208231
(self.quote_name(fk[0]), self.quote_name(fk[1])) for fk in fks])
209232
return sql_list

0 commit comments

Comments
 (0)