Skip to content

Commit cba5117

Browse files
authored
Merge branch 'dev' into Nandana/5.2/composite-primary-key
2 parents 97ba852 + e75a901 commit cba5117

File tree

8 files changed

+302
-89
lines changed

8 files changed

+302
-89
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
#
1212
name: "CodeQL"
1313

14+
# This workflow is triggered on pushes to the dev branch, pull requests targeting
15+
permissions:
16+
actions: read
17+
contents: read
18+
security-events: write
19+
1420
on:
1521
push:
1622
branches: [ dev ]

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ We hope you enjoy using the MSSQL-Django 3rd party backend.
1010

1111
## Features
1212

13-
- Supports Django 3.2, 4.0, 4.1, 4.2 and 5.0
13+
- Supports Django 3.2, 4.0, 4.1, 4.2, 5.0, 5.1, and 5.2
14+
- **Django 5.0 and below**: Full production support
15+
- **Django 5.1**: Supported with minor limitations (composite primary key inspectdb)
16+
- **Django 5.2**: Supported with enhanced SQL Server compatibility features and documented limitations (see Django 5.2 Specific Limitations section below)
1417
- Tested on Microsoft SQL Server 2016, 2017, 2019, 2022
1518
- Passes most of the tests of the Django test suite
19+
- Enhanced SQL Server compatibility with automatic schema creation and improved identifier quoting
1620
- Compatible with
1721
[Micosoft ODBC Driver for SQL Server](https://docs.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server),
1822
[SQL Server Native Client](https://msdn.microsoft.com/en-us/library/ms131321(v=sql.120).aspx),
@@ -273,6 +277,42 @@ The following features are currently not fully supported:
273277
- Date extract function
274278
- Bulk insert into a table with a trigger and returning the rows inserted
275279

280+
### Django 5.1 Specific Limitations
281+
282+
Django 5.1 introduces composite primary key support which has limited compatibility with SQL Server:
283+
- **inspectdb command**: Cannot properly inspect tables with composite primary keys
284+
- **Backend debugging**: SQL execution wrapper debug functionality may not work correctly
285+
- **Schema operations**: Some field unique constraint removal operations may have issues
286+
- Most other Django 5.1 features work correctly with SQL Server
287+
288+
### Django 5.2 Specific Limitations
289+
290+
Django 5.2 introduces new features that may cause regressions for existing Django 5.0+ applications. This release includes enhanced SQL Server compatibility for Django 5.2, with automatic schema creation and improved identifier quoting. The following limitations remain:
291+
292+
**Critical Limitations (May Affect Common Use Cases):**
293+
- **Tuple lookups**: Queries like `Model.objects.filter((col1, col2)__in=[(val1, val2)])` will fail with SQL syntax errors as SQL Server doesn't support `(col1, col2) IN (...)` syntax
294+
- **Multi-column foreign key relationships**: Complex queries involving foreign keys with multiple columns may fail in Django 5.2 due to tuple lookup generation
295+
- **JSONField with special characters**: JSONField lookups involving special characters (quotes, emojis, escape sequences) may generate invalid SQL
296+
- **JSONField bulk updates**: Bulk update operations on JSONField with null handling may fail
297+
298+
**Moderate Impact:**
299+
- **Complex aggregations**: Some aggregation queries with filtered references and subqueries may not work correctly
300+
- **Prefetch operations**: `prefetch_related()` operations on multi-column foreign keys may fail
301+
302+
**Low Impact (Edge Cases):**
303+
- **Migration operations**: Advanced migration operations involving composite primary keys and generated fields
304+
- **Backend debugging**: Certain backend debugging and introspection features
305+
- **JSONField CASE WHEN updates**: JSONField updates using CASE WHEN expressions with null handling
306+
307+
**Specific Test Failures in Django 5.2:**
308+
- All `foreign_object.test_tuple_lookups.TupleLookupsTests.*` tests
309+
- All `foreign_object.tests.MultiColumnFKTests.*` tests involving complex queries
310+
- `model_fields.test_jsonfield.TestQuerying.test_lookups_special_chars*` tests
311+
- `queries.test_bulk_update.BulkUpdateTests.test_json_field_sql_null` test
312+
- Various migration and backend debugging tests
313+
314+
**Workaround**: These limitations are documented in the test exclusions (`testapp/settings.py`) and are excellent candidates for community contributions. Applications using Django 5.0 and below are unaffected by these limitations.
315+
276316
JSONField lookups have limitations, more details [here](https://github.com/microsoft/mssql-django/wiki/JSONField).
277317

278318
## Contributing

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ jobs:
176176
Python3.10 - Django 5.2:
177177
python.version: '3.10'
178178
tox.env: 'py310-django52'
179-
179+
180180
Python3.13 - Django 5.1:
181181
python.version: '3.13'
182182
tox.env: 'py313-django51'

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.

0 commit comments

Comments
 (0)