summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Klus <christianklus@gmail.com>2020-10-27 13:13:10 -0500
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-10-29 11:30:53 +0100
commitab951d242e3de232c7fc9a2f6facfd6aa95f5fe2 (patch)
tree466e3933ec79e4629c5b58ab5594d8eb9112de54
parent62f6ab2c4a2bbf1b5354bca268dcd43be8537785 (diff)
[3.1.x] Fixed #32152 -- Fixed grouping by subquery aliases.
Regression in 42c08ee46539ef44f8658ebb1cbefb408e0d03fe. Thanks Simon Charette for the review. Backport of 4ac2d4fa42e1659f328c35b6b8d4761b3419c11a from master
-rw-r--r--django/db/models/sql/query.py4
-rw-r--r--docs/releases/3.0.11.txt9
-rw-r--r--docs/releases/3.1.3.txt3
-rw-r--r--tests/annotations/tests.py21
4 files changed, 34 insertions, 3 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 7acef7f654..7a16d4889a 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -2148,8 +2148,10 @@ class Query(BaseExpression):
field_names.append(f)
self.set_extra_mask(extra_names)
self.set_annotation_mask(annotation_names)
+ selected = frozenset(field_names + extra_names + annotation_names)
else:
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
# clause.
if self.group_by is True:
@@ -2163,7 +2165,7 @@ class Query(BaseExpression):
# the selected fields anymore.
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]
group_by.append(expr)
self.group_by = tuple(group_by)
diff --git a/docs/releases/3.0.11.txt b/docs/releases/3.0.11.txt
index a5009feb51..1dcf37a517 100644
--- a/docs/releases/3.0.11.txt
+++ b/docs/releases/3.0.11.txt
@@ -4,4 +4,11 @@ Django 3.0.11 release notes
*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`).
diff --git a/docs/releases/3.1.3.txt b/docs/releases/3.1.3.txt
index ce6cf962c7..6e13da1e78 100644
--- a/docs/releases/3.1.3.txt
+++ b/docs/releases/3.1.3.txt
@@ -57,3 +57,6 @@ Bugfixes
* 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
(:ticket:`32127`).
+
+* Fixed a regression in Django 3.0.7 that didn't use ``Subquery()`` aliases in
+ the ``GROUP BY`` clause (:ticket:`32152`).
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index 836c0ebb1d..06038781f2 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -10,7 +10,7 @@ from django.db.models import (
NullBooleanField, OuterRef, Q, Subquery, Sum, Value, When,
)
from django.db.models.expressions import RawSQL
-from django.db.models.functions import Length, Lower
+from django.db.models.functions import ExtractYear, Length, Lower
from django.test import TestCase, skipUnlessDBFeature
from .models import (
@@ -664,6 +664,25 @@ class NonAggregateAnnotationTestCase(TestCase):
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},
+ ])
+
@skipIf(
connection.vendor == 'mysql' and 'ONLY_FULL_GROUP_BY' in connection.sql_mode,
'GROUP BY optimization does not work properly when ONLY_FULL_GROUP_BY '