Skip to content

Commit 9636c17

Browse files
committed
Bug fixes.
1 parent 6f3573e commit 9636c17

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

django_mongodb_backend/features.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class DatabaseFeatures(GISFeatures, BaseDatabaseFeatures):
2929
supports_deferrable_unique_constraints = False
3030
supports_explaining_query_execution = True
3131
supports_expression_defaults = False
32-
supports_expression_indexes = True
32+
supports_expression_indexes = False
3333
supports_foreign_keys = False
3434
supports_ignore_conflicts = False
3535
supports_json_field_contains = False
@@ -102,6 +102,9 @@ class DatabaseFeatures(GISFeatures, BaseDatabaseFeatures):
102102
"model_fields.test_jsonfield.TestSaveLoad.test_bulk_update_custom_get_prep_value",
103103
# To debug: https://github.com/mongodb/django-mongodb-backend/issues/362
104104
"constraints.tests.UniqueConstraintTests.test_validate_case_when",
105+
# Partially expression index support
106+
"schema.tests.SchemaTests.test_func_unique_constraint_unsupported",
107+
"schema.tests.SchemaTests.test_func_index_unsupported",
105108
}
106109
# $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3.
107110
_django_test_expected_failures_bitwise = {

django_mongodb_backend/indexes.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.core.checks import Error, Warning
55
from django.db import NotSupportedError
66
from django.db.models import FloatField, Index, IntegerField
7-
from django.db.models.expressions import F, OrderBy
7+
from django.db.models.expressions import OrderBy
88
from django.db.models.lookups import BuiltinLookup
99
from django.db.models.sql.query import Query
1010
from django.db.models.sql.where import AND, XOR, WhereNode
@@ -51,16 +51,14 @@ def get_pymongo_index_model(self, model, schema_editor, field=None, unique=False
5151
expressions_fields = []
5252
if self.contains_expressions:
5353
for expression in self.expressions:
54-
if not isinstance(expression, F | OrderBy):
55-
continue
5654
query = Query(model=model, alias_cols=False)
5755
field_ = expression.resolve_expression(query)
5856
compiler = query.get_compiler(connection=schema_editor.connection)
5957
column = field_.as_mql(compiler, schema_editor.connection, as_path=True)
6058
db_type = (
6159
field_.expression.db_type(schema_editor.connection)
6260
if isinstance(field_, OrderBy)
63-
else field_.db_type(schema_editor.connection)
61+
else field_.output_field.db_type(schema_editor.connection)
6462
)
6563
if unique:
6664
filter_expression[column].update({"$type": db_type})

django_mongodb_backend/schema.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
22
from django.db.models import Index, UniqueConstraint
3+
from django.db.models.expressions import F, OrderBy
34
from pymongo.operations import SearchIndexModel
45

56
from django_mongodb_backend.indexes import SearchIndex
@@ -345,6 +346,36 @@ def _remove_field_index(self, model, field, column_prefix=""):
345346
)
346347
collection.drop_index(index_names[0])
347348

349+
def _check_supported_expressions(self, expressions):
350+
for expression in expressions:
351+
expression = expression.expression if isinstance(expression, OrderBy) else expression
352+
if not isinstance(expression, F):
353+
return False
354+
return True
355+
356+
def _unique_supported(
357+
self,
358+
condition=None,
359+
deferrable=None,
360+
include=None,
361+
expressions=None,
362+
nulls_distinct=None,
363+
):
364+
return (
365+
(not condition or self.connection.features.supports_partial_indexes)
366+
and (not deferrable or self.connection.features.supports_deferrable_unique_constraints)
367+
and (not include or self.connection.features.supports_covering_indexes)
368+
and (
369+
not expressions
370+
or self._check_supported_expressions(expressions)
371+
or self.connection.features.supports_expression_indexes
372+
)
373+
and (
374+
nulls_distinct is None
375+
or self.connection.features.supports_nulls_distinct_unique_constraints
376+
)
377+
)
378+
348379
@ignore_embedded_models
349380
def add_constraint(self, model, constraint, field=None, column_prefix="", parent_model=None):
350381
if isinstance(constraint, UniqueConstraint) and self._unique_supported(
@@ -386,6 +417,7 @@ def remove_constraint(self, model, constraint):
386417
nulls_distinct=constraint.nulls_distinct,
387418
):
388419
idx = Index(
420+
*constraint.expressions,
389421
fields=constraint.fields,
390422
name=constraint.name,
391423
condition=constraint.condition,

0 commit comments

Comments
 (0)