Skip to content

Commit 3913acd

Browse files
charettesfelixxm
authored andcommitted
[3.1.x] Fixed #31568 -- Fixed alias reference when aggregating over multiple subqueries.
691def1 made all Subquery() instances equal to each other which broke aggregation subquery pushdown which relied on object equality to determine which alias it should select. Subquery.__eq__() will be fixed in an another commit but Query.rewrite_cols() should haved used object identity from the start. Refs #30727, #30188. Thanks Makina Corpus for the report. Backport of adfbf65 from master
1 parent 8cb87a3 commit 3913acd

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

django/db/models/sql/query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ def rewrite_cols(self, annotation, col_cnt):
390390
else:
391391
# Reuse aliases of expressions already selected in subquery.
392392
for col_alias, selected_annotation in self.annotation_select.items():
393-
if selected_annotation == expr:
393+
if selected_annotation is expr:
394394
new_expr = Ref(col_alias, expr)
395395
break
396396
else:

docs/releases/3.0.7.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ Bugfixes
1515
* Fixed a regression in Django 3.0 where ``QuerySet.values()`` and
1616
``values_list()`` crashed if a queryset contained an aggregation and a
1717
subquery annotation (:ticket:`31566`).
18+
19+
* Fixed a regression in Django 3.0 where aggregates used wrong annotations when
20+
a queryset has multiple subqueries annotations (:ticket:`31568`).

tests/aggregation/test_filter_argument.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
from decimal import Decimal
33

44
from django.db.models import (
5-
Avg, Case, Count, F, OuterRef, Q, StdDev, Subquery, Sum, Variance, When,
5+
Avg, Case, Count, Exists, F, Max, OuterRef, Q, StdDev, Subquery, Sum,
6+
Variance, When,
67
)
78
from django.test import TestCase
89
from django.test.utils import Approximate
@@ -120,3 +121,23 @@ def test_filtered_aggregate_ref_subquery_annotation(self):
120121
cnt=Count('pk', filter=Q(earliest_book_year=2008)),
121122
)
122123
self.assertEqual(aggs['cnt'], 2)
124+
125+
def test_filtered_aggregate_ref_multiple_subquery_annotation(self):
126+
aggregate = Book.objects.values('publisher').annotate(
127+
has_authors=Exists(
128+
Book.authors.through.objects.filter(book=OuterRef('pk')),
129+
),
130+
authors_have_other_books=Exists(
131+
Book.objects.filter(
132+
authors__in=Author.objects.filter(
133+
book_contact_set=OuterRef(OuterRef('pk')),
134+
)
135+
).exclude(pk=OuterRef('pk')),
136+
),
137+
).aggregate(
138+
max_rating=Max(
139+
'rating',
140+
filter=Q(has_authors=True, authors_have_other_books=False),
141+
)
142+
)
143+
self.assertEqual(aggregate, {'max_rating': 4.5})

0 commit comments

Comments
 (0)