diff --git a/mssql/features.py b/mssql/features.py index d63fcc4..60d3f62 100644 --- a/mssql/features.py +++ b/mssql/features.py @@ -3,8 +3,10 @@ from django.db.backends.base.features import BaseDatabaseFeatures from django.utils.functional import cached_property - - +from django import VERSION as django_version +# Import CompositePrimaryKey only if Django version is 5.2 or higher +if django_version >= (5, 2): + from django.db.models.fields.composite import CompositePrimaryKey class DatabaseFeatures(BaseDatabaseFeatures): allows_group_by_select_index = False allow_sliced_subqueries_with_in = False @@ -63,8 +65,11 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_default_keyword_in_bulk_insert = True supports_stored_generated_columns = True supports_virtual_generated_columns = True - - + # CompositePrimaryKey support is only available in Django 5.2 and later + supports_composite_primary_keys = django_version >= (5, 2) + if django_version >= (5, 2) and isinstance(CompositePrimaryKey, type): + # Set fallback tupple lookup support + supports_tuple_lookups = False @cached_property def has_zoneinfo_database(self): with self.connection.cursor() as cursor: diff --git a/mssql/schema.py b/mssql/schema.py index e54ec51..a31fdf7 100644 --- a/mssql/schema.py +++ b/mssql/schema.py @@ -29,8 +29,9 @@ if django_version >= (4, 0): from django.db.models.sql import Query from django.db.backends.ddl_references import Expressions - - +# Import CompositePrimaryKey only if Django version is 5.2 or higher +if django_version >= (5, 2): + from django.db.models.fields.composite import CompositePrimaryKey class Statement(DjStatement): def __hash__(self): return hash((self.template, str(self.parts['name']))) @@ -1315,7 +1316,19 @@ def create_model(self, model): autoinc_sql = self.connection.ops.autoinc_sql(model._meta.db_table, field.column) if autoinc_sql: self.deferred_sql.extend(autoinc_sql) - + + # Initialize composite_pk_sql to None; will be set if composite primary key is detected + composite_pk_sql = None + # Check if Django version is >= 5.2 and the model has composite primary key fields + if django_version >= (5, 2) and hasattr(model._meta, "pk_fields"): + #specifically refers to the primary key field of that model. + pk = model._meta.pk + # Check if the primary key is a CompositePrimaryKey instance + if isinstance(pk, CompositePrimaryKey): + # Get the column names for all fields in the composite primary key + pk_columns = [field.column for field in model._meta.pk_fields] + # Build the PRIMARY KEY SQL clause for the composite key + composite_pk_sql = "PRIMARY KEY (%s)" % ", ".join(self.quote_name(col) for col in pk_columns) # Add any unique_togethers (always deferred, as some fields might be # created afterwards, like geometry fields with some backends) for field_names in model._meta.unique_together: @@ -1328,6 +1341,9 @@ def create_model(self, model): self.deferred_sql.append(self._create_unique_sql(model, columns, condition=condition)) constraints = [constraint.constraint_sql(model, self) for constraint in model._meta.constraints] + # If a composite primary key SQL clause was generated, insert it at the beginning of the constraints list + if composite_pk_sql: + constraints.insert(0, composite_pk_sql) # Make the table sql = self.sql_create_table % { "table": self.quote_name(model._meta.db_table),