Skip to content

Commit 7141e8c

Browse files
committed
Fix collisions with projected columns and order by columns.
1 parent bdd2a40 commit 7141e8c

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

.github/workflows/test-python.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ jobs:
6868
run: >
6969
python3 django_repo/tests/runtests.py --settings mongodb_settings -v 2
7070
aggregation
71+
aggregation_regress
7172
annotations
7273
auth_tests.test_models.UserManagerTestCase
7374
backends.base.test_base.DatabaseWrapperTests

django_mongodb/compiler.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,9 +357,7 @@ def build_query(self, columns=None):
357357
if columns is None:
358358
extra_fields += ordering_fields
359359
if extra_fields:
360-
query.extra_fields = {
361-
field_name: expr.as_mql(self, self.connection) for field_name, expr in extra_fields
362-
}
360+
query.extra_fields = self.get_project_fields(extra_fields, force_expression=True)
363361
where = self.get_where()
364362
try:
365363
expr = where.as_mql(self, self.connection) if where else {}
@@ -429,16 +427,18 @@ def _get_aggregate_expressions(self, expr):
429427
elif hasattr(expr, "get_source_expressions"):
430428
stack.extend(expr.get_source_expressions())
431429

432-
def get_project_fields(self, columns=None, ordering=None):
430+
def get_project_fields(self, columns=None, ordering=None, force_expression=False):
431+
if not columns:
432+
return {}
433433
fields = defaultdict(dict)
434-
for name, expr in columns or []:
434+
for name, expr in columns + (ordering or ()):
435435
collection = expr.alias if isinstance(expr, Col) else None
436436
try:
437437
fields[collection][name] = (
438438
1
439439
# For brevity/simplicity, project {"field_name": 1}
440440
# instead of {"field_name": "$field_name"}.
441-
if isinstance(expr, Col) and name == expr.target.column
441+
if isinstance(expr, Col) and name == expr.target.column and not force_expression
442442
else expr.as_mql(self, self.connection)
443443
)
444444
except EmptyResultSet:
@@ -449,9 +449,6 @@ def get_project_fields(self, columns=None, ordering=None):
449449
# should appear in the top-level of the fields dict.
450450
fields.update(fields.pop(None, {}))
451451
fields.update(fields.pop(self.collection_name, {}))
452-
# Add order_by() fields.
453-
if fields and ordering:
454-
fields.update({alias: expr.as_mql(self, self.connection) for alias, expr in ordering})
455452
# Convert defaultdict to dict so it doesn't appear as
456453
# "defaultdict(<CLASS 'dict'>, ..." in query logging.
457454
return dict(fields)
@@ -471,7 +468,7 @@ def _get_ordering(self):
471468
for order in self.order_by_objs or []:
472469
if isinstance(order.expression, Col):
473470
field_name = order.expression.as_mql(self, self.connection).removeprefix("$")
474-
fields[field_name] = order.expression
471+
fields[order.expression.target.column] = order.expression
475472
elif isinstance(order.expression, Ref):
476473
field_name = order.expression.as_mql(self, self.connection).removeprefix("$")
477474
else:

django_mongodb/features.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
6161
"aggregation.tests.AggregateTestCase.test_aggregation_default_passed_another_aggregate",
6262
"aggregation.tests.AggregateTestCase.test_annotation_expressions",
6363
"aggregation.tests.AggregateTestCase.test_reverse_fkey_annotate",
64+
"aggregation_regress.tests.AggregationTests.test_annotation_disjunction",
65+
"aggregation_regress.tests.AggregationTests.test_decimal_aggregate_annotation_filter",
6466
}
6567
# $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3.
6668
_django_test_expected_failures_bitwise = {
@@ -198,6 +200,7 @@ def django_test_expected_failures(self):
198200
"queries.test_bulk_update.BulkUpdateTests.test_database_routing_batch_atomicity",
199201
},
200202
"Test assumes integer primary key.": {
203+
"aggregation_regress.tests.AggregationTests.test_aggregation_with_generic_reverse_relation",
201204
"db_functions.comparison.test_cast.CastTests.test_cast_to_integer_foreign_key",
202205
"model_fields.test_foreignkey.ForeignKeyTests.test_to_python",
203206
},
@@ -210,6 +213,7 @@ def django_test_expected_failures(self):
210213
"aggregation.tests.AggregateTestCase.test_exists_extra_where_with_aggregate",
211214
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_exists_aggregate_values_chaining",
212215
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_exists_none_query",
216+
"aggregation_regress.tests.AggregationTests.test_annotate_and_join",
213217
"delete_regress.tests.DeleteTests.test_self_reference_with_through_m2m_at_second_level",
214218
"expressions.tests.BasicExpressionsTests.test_annotation_with_deeply_nested_outerref",
215219
"expressions.tests.BasicExpressionsTests.test_boolean_expression_combined",
@@ -299,6 +303,11 @@ def django_test_expected_failures(self):
299303
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_and_alias_filter_in_subquery",
300304
"annotations.tests.NonAggregateAnnotationTestCase.test_annotation_and_alias_filter_related_in_subquery",
301305
"annotations.tests.NonAggregateAnnotationTestCase.test_empty_expression_annotation",
306+
"aggregation_regress.tests.AggregationTests.test_aggregates_in_where_clause",
307+
"aggregation_regress.tests.AggregationTests.test_aggregates_in_where_clause_pre_eval",
308+
"aggregation_regress.tests.AggregationTests.test_f_expression_annotation",
309+
"aggregation_regress.tests.AggregationTests.test_having_subquery_select",
310+
"aggregation_regress.tests.AggregationTests.test_negated_aggregation",
302311
"db_functions.comparison.test_coalesce.CoalesceTests.test_empty_queryset",
303312
"expressions_case.tests.CaseExpressionTests.test_annotate_with_in_clause",
304313
"expressions.tests.FTimeDeltaTests.test_date_subquery_subtraction",
@@ -353,6 +362,7 @@ def django_test_expected_failures(self):
353362
"QuerySet.dates() is not supported on MongoDB.": {
354363
"aggregation.tests.AggregateTestCase.test_dates_with_aggregation",
355364
"annotations.tests.AliasTests.test_dates_alias",
365+
"aggregation_regress.tests.AggregationTests.test_more_more_more",
356366
"dates.tests.DatesTests.test_dates_trunc_datetime_fields",
357367
"dates.tests.DatesTests.test_related_model_traverse",
358368
},
@@ -370,6 +380,9 @@ def django_test_expected_failures(self):
370380
},
371381
"QuerySet.distinct() is not supported.": {
372382
"aggregation.tests.AggregateTestCase.test_sum_distinct_aggregate",
383+
"aggregation_regress.tests.AggregationTests.test_annotate_distinct_aggregate",
384+
"aggregation_regress.tests.AggregationTests.test_conditional_aggregate_on_complex_condition",
385+
"aggregation_regress.tests.AggregationTests.test_distinct_conditional_aggregate",
373386
"lookup.tests.LookupTests.test_lookup_collision_distinct",
374387
"ordering.tests.OrderingTests.test_orders_nulls_first_on_filtered_subquery",
375388
"queries.tests.ExcludeTest17600.test_exclude_plain_distinct",
@@ -424,6 +437,7 @@ def django_test_expected_failures(self):
424437
"aggregation.tests.AggregateAnnotationPruningTests.test_unused_aliased_aggregate_pruned",
425438
"aggregation.tests.AggregateAnnotationPruningTests.test_referenced_aggregate_annotation_kept",
426439
"aggregation.tests.AggregateTestCase.test_count_star",
440+
"aggregation_regress.tests.AggregationTests.test_annotation_with_value",
427441
"delete.tests.DeletionTests.test_only_referenced_fields_selected",
428442
"lookup.tests.LookupTests.test_in_ignore_none",
429443
"lookup.tests.LookupTests.test_textfield_exact_null",
@@ -433,6 +447,9 @@ def django_test_expected_failures(self):
433447
"Test executes raw SQL.": {
434448
"aggregation.tests.AggregateTestCase.test_coalesced_empty_result_set",
435449
"annotations.tests.NonAggregateAnnotationTestCase.test_raw_sql_with_inherited_field",
450+
"aggregation_regress.tests.AggregationTests.test_annotate_with_extra",
451+
"aggregation_regress.tests.AggregationTests.test_annotation",
452+
"aggregation_regress.tests.AggregationTests.test_more_more",
436453
"delete_regress.tests.DeleteLockingTest.test_concurrent_delete",
437454
"expressions.tests.BasicExpressionsTests.test_annotate_values_filter",
438455
"expressions.tests.BasicExpressionsTests.test_filtering_on_rawsql_that_is_boolean",

0 commit comments

Comments
 (0)