Skip to content

Commit 8af48ce

Browse files
authored
FEAT: Support Django 5.2 - Improved Identifier Quoting & Auto-Schema Creation (#468)
1 parent 306d97e commit 8af48ce

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

mssql/creation.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ def _create_test_db(self, verbosity, autoclobber, keepdb=False):
2727
# so we can proceed if we're keeping the DB anyway.
2828
# https://github.com/microsoft/mssql-django/issues/61
2929
try:
30-
return super()._create_test_db(verbosity, autoclobber, keepdb)
30+
test_database_name = super()._create_test_db(verbosity, autoclobber, keepdb)
31+
32+
# Create required schemas for Django tests (only for 5.2+)
33+
if django_version >= (5, 2):
34+
self._create_test_schemas(test_database_name, verbosity)
35+
36+
return test_database_name
3137
except InterfaceError as err:
3238
if err.args[0] == '28000' and keepdb:
3339
self.log('Received error %s, proceeding because keepdb=True' % (
@@ -36,6 +42,32 @@ def _create_test_db(self, verbosity, autoclobber, keepdb=False):
3642
else:
3743
raise err
3844

45+
def _create_test_schemas(self, test_database_name, verbosity):
46+
"""
47+
Create required schemas in test database for Django tests.
48+
"""
49+
schemas_to_create = ['inspectdb_special', 'inspectdb_pascal']
50+
51+
# Use a cursor connected to the test database
52+
test_settings = self.connection.settings_dict.copy()
53+
test_settings['NAME'] = test_database_name
54+
test_connection = self.connection.__class__(test_settings)
55+
56+
try:
57+
with test_connection.cursor() as cursor:
58+
for schema in schemas_to_create:
59+
try:
60+
quoted_schema = self.connection.ops.quote_name(schema)
61+
cursor.execute(f"CREATE SCHEMA {quoted_schema}")
62+
if verbosity >= 2:
63+
self.log(f'Created schema {schema} in test database {test_database_name}')
64+
except Exception as e:
65+
# Schema might already exist, which is fine
66+
if verbosity >= 2:
67+
self.log(f'Schema {schema} creation failed (might already exist): {e}')
68+
finally:
69+
test_connection.close()
70+
3971
def _destroy_test_db(self, test_database_name, verbosity):
4072
"""
4173
Internal implementation - remove the test db tables.

mssql/operations.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,9 +377,28 @@ def quote_name(self, name):
377377
"""
378378
Returns a quoted version of the given table, index or column name. Does
379379
not quote the given name if it's already been quoted.
380-
"""
380+
381+
Supports:
382+
- Schema.table format: quotes both schema and table separately
383+
- Names with spaces: handles proper quoting
384+
"""
385+
if not name:
386+
return name
387+
388+
# Already quoted
381389
if name.startswith('[') and name.endswith(']'):
382390
return name # Quoting once is enough.
391+
392+
# Enhanced schema.table support for Django 5.2+
393+
if django_version >= (5, 2) and '.' in name and not name.startswith('['):
394+
parts = name.split('.', 1) # Split only on first dot
395+
schema = parts[0].strip()
396+
table = parts[1].strip()
397+
398+
# Always quote both parts for SQL Server safety
399+
return '[%s].[%s]' % (schema, table)
400+
401+
# Always quote single names for SQL Server safety
383402
return '[%s]' % name
384403

385404
def random_function_sql(self):

0 commit comments

Comments
 (0)