Fixed #32152 -- Fixed grouping by subquery aliases.

Regression in 42c08ee465.

Thanks Simon Charette for the review.
This commit is contained in:
Christian Klus 2020-10-27 13:13:10 -05:00 committed by Mariusz Felisiak
parent 9ca22c7733
commit 4ac2d4fa42
4 changed files with 34 additions and 3 deletions

View File

@ -2210,8 +2210,10 @@ class Query(BaseExpression):
field_names.append(f) field_names.append(f)
self.set_extra_mask(extra_names) self.set_extra_mask(extra_names)
self.set_annotation_mask(annotation_names) self.set_annotation_mask(annotation_names)
selected = frozenset(field_names + extra_names + annotation_names)
else: else:
field_names = [f.attname for f in self.model._meta.concrete_fields] field_names = [f.attname for f in self.model._meta.concrete_fields]
selected = frozenset(field_names)
# Selected annotations must be known before setting the GROUP BY # Selected annotations must be known before setting the GROUP BY
# clause. # clause.
if self.group_by is True: if self.group_by is True:
@ -2225,7 +2227,7 @@ class Query(BaseExpression):
# the selected fields anymore. # the selected fields anymore.
group_by = [] group_by = []
for expr in self.group_by: for expr in self.group_by:
if isinstance(expr, Ref) and expr.refs not in field_names: if isinstance(expr, Ref) and expr.refs not in selected:
expr = self.annotations[expr.refs] expr = self.annotations[expr.refs]
group_by.append(expr) group_by.append(expr)
self.group_by = tuple(group_by) self.group_by = tuple(group_by)

View File

@ -4,4 +4,11 @@ Django 3.0.11 release notes
*Expected November 2, 2020* *Expected November 2, 2020*
Django 3.0.11 adds compatibility with Python 3.9. Django 3.0.11 fixes a regression in 3.0.7 and adds compatibility with Python
3.9.
Bugfixes
========
* Fixed a regression in Django 3.0.7 that didn't use ``Subquery()`` aliases in
the ``GROUP BY`` clause (:ticket:`32152`).

View File

@ -57,3 +57,6 @@ Bugfixes
* Fixed a regression in Django 3.1 that caused incorrect textarea layout on * Fixed a regression in Django 3.1 that caused incorrect textarea layout on
medium-sized screens in the admin change form view with the sidebar open medium-sized screens in the admin change form view with the sidebar open
(:ticket:`32127`). (:ticket:`32127`).
* Fixed a regression in Django 3.0.7 that didn't use ``Subquery()`` aliases in
the ``GROUP BY`` clause (:ticket:`32152`).

View File

@ -9,7 +9,7 @@ from django.db.models import (
Subquery, Sum, Value, When, Subquery, Sum, Value, When,
) )
from django.db.models.expressions import RawSQL from django.db.models.expressions import RawSQL
from django.db.models.functions import Coalesce, Length, Lower from django.db.models.functions import Coalesce, ExtractYear, Length, Lower
from django.test import TestCase, skipUnlessDBFeature from django.test import TestCase, skipUnlessDBFeature
from .models import ( from .models import (
@ -658,6 +658,25 @@ class NonAggregateAnnotationTestCase(TestCase):
datetime.date(2008, 11, 3), datetime.date(2008, 11, 3),
]) ])
@skipUnlessDBFeature('supports_subqueries_in_group_by')
def test_annotation_subquery_and_aggregate_values_chaining(self):
qs = Book.objects.annotate(
pub_year=ExtractYear('pubdate')
).values('pub_year').annotate(
top_rating=Subquery(
Book.objects.filter(
pubdate__year=OuterRef('pub_year')
).order_by('-rating').values('rating')[:1]
),
total_pages=Sum('pages'),
).values('pub_year', 'total_pages', 'top_rating')
self.assertCountEqual(qs, [
{'pub_year': 1991, 'top_rating': 5.0, 'total_pages': 946},
{'pub_year': 1995, 'top_rating': 4.0, 'total_pages': 1132},
{'pub_year': 2007, 'top_rating': 4.5, 'total_pages': 447},
{'pub_year': 2008, 'top_rating': 4.0, 'total_pages': 1178},
])
def test_annotation_aggregate_with_m2o(self): def test_annotation_aggregate_with_m2o(self):
if connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode: if connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode:
self.skipTest( self.skipTest(