From 57f499e412c7c28b4a1f1b740468bf6eabbdb695 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Sun, 21 May 2023 23:49:05 -0400 Subject: [4.2.x] Refs #34551 -- Fixed QuerySet.aggregate() crash on precending aggregation reference. Regression in 1297c0d0d76a708017fe196b61a0ab324df76954. Refs #31679. Backport of 2ee01747c32a7275a7a1a5f7862acba7db764921 from main --- django/db/models/sql/query.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'django/db/models/sql/query.py') diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index b615d06f28..8739a7b09c 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -387,7 +387,10 @@ class Query(BaseExpression): """ if not aggregate_exprs: return {} - aggregates = {} + # Store annotation mask prior to temporarily adding aggregations for + # resolving purpose to facilitate their subsequent removal. + replacements = {} + annotation_select_mask = self.annotation_select_mask for alias, aggregate_expr in aggregate_exprs.items(): self.check_alias(alias) aggregate = aggregate_expr.resolve_expression( @@ -395,7 +398,16 @@ class Query(BaseExpression): ) if not aggregate.contains_aggregate: raise TypeError("%s is not an aggregate expression" % alias) - aggregates[alias] = aggregate + # Temporarily add aggregate to annotations to allow remaining + # members of `aggregates` to resolve against each others. + self.append_annotation_mask([alias]) + aggregate = aggregate.replace_expressions(replacements) + self.annotations[alias] = aggregate + replacements[Ref(alias, aggregate)] = aggregate + # Stash resolved aggregates now that they have been allowed to resolve + # against each other. + aggregates = {alias: self.annotations.pop(alias) for alias in aggregate_exprs} + self.set_annotation_mask(annotation_select_mask) # Existing usage of aggregation can be determined by the presence of # selected aggregates but also by filters against aliased aggregates. _, having, qualify = self.where.split_having_qualify() -- cgit v1.3