From 7530cf3900ab98104edcde69e8a2a415e82b345a Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Fri, 17 Nov 2023 19:42:44 -0500 Subject: [PATCH] Fixed #34975 -- Fixed crash of conditional aggregate() over aggregations. Adjustments made to solve_lookup_type to defer the resolving of references for summarized aggregates failed to account for similar requirements for lookup values which can also reference annotations through Aggregate.filter. Regression in b181cae2e3697b2e53b5b67ac67e59f3b05a6f0d. Refs #25307. Thanks Sergey Nesterenko for the report. --- django/db/models/sql/query.py | 5 +++-- docs/releases/4.2.8.txt | 4 ++++ tests/aggregation/tests.py | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 4690fd304d6..f04b1c4cc3a 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1256,12 +1256,13 @@ class Query(BaseExpression): sql = "(%s)" % sql return sql, params - def resolve_lookup_value(self, value, can_reuse, allow_joins): + def resolve_lookup_value(self, value, can_reuse, allow_joins, summarize=False): if hasattr(value, "resolve_expression"): value = value.resolve_expression( self, reuse=can_reuse, allow_joins=allow_joins, + summarize=summarize, ) elif isinstance(value, (list, tuple)): # The items of the iterable may be expressions and therefore need @@ -1487,7 +1488,7 @@ class Query(BaseExpression): raise FieldError("Joined field references are not permitted in this query") pre_joins = self.alias_refcount.copy() - value = self.resolve_lookup_value(value, can_reuse, allow_joins) + value = self.resolve_lookup_value(value, can_reuse, allow_joins, summarize) used_joins = { k for k, v in self.alias_refcount.items() if v > pre_joins.get(k, 0) } diff --git a/docs/releases/4.2.8.txt b/docs/releases/4.2.8.txt index 5804589408c..22293243627 100644 --- a/docs/releases/4.2.8.txt +++ b/docs/releases/4.2.8.txt @@ -11,3 +11,7 @@ Bugfixes * Fixed a regression in Django 4.2 that caused :option:`makemigrations --check` to stop displaying pending migrations (:ticket:`34457`). + +* Fixed a regression in Django 4.2 that caused a crash of + ``QuerySet.aggregate()`` with aggregates referencing other aggregates or + window functions through conditional expressions (:ticket:`34975`). diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py index a073d01590f..af6c660cf13 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -2309,3 +2309,9 @@ class AggregateAnnotationPruningTests(TestCase): aggregate, {"sum_avg_publisher_pages": 1100.0, "books_count": 2}, ) + + def test_aggregate_reference_lookup_rhs(self): + aggregates = Author.objects.annotate( + max_book_author=Max("book__authors"), + ).aggregate(count=Count("id", filter=Q(id=F("max_book_author")))) + self.assertEqual(aggregates, {"count": 1})