From c5cfaad2f1f08b31ba04b9534f1a46a6ef1003bf Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Mon, 2 Mar 2020 13:20:36 +0100 Subject: [3.0.x] Fixed #31150 -- Included subqueries that reference related fields in GROUP BY clauses. Thanks Johannes Hoppe for the report. Regression in fb3f034f1c63160c0ff13c609acd01c18be12f80. Co-authored-by: Simon Charette Backport of 7b8fa1653fde578ab3a496d9974ab1d4261b8b26 from master --- django/db/models/expressions.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'django') diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 3adec334f7..2733fbada9 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -6,6 +6,7 @@ from decimal import Decimal from django.core.exceptions import EmptyResultSet, FieldError from django.db import connection from django.db.models import fields +from django.db.models.constants import LOOKUP_SEP from django.db.models.query_utils import Q from django.db.utils import NotSupportedError from django.utils.deconstruct import deconstructible @@ -558,6 +559,14 @@ class ResolvedOuterRef(F): 'only be used in a subquery.' ) + def resolve_expression(self, *args, **kwargs): + col = super().resolve_expression(*args, **kwargs) + # FIXME: Rename possibly_multivalued to multivalued and fix detection + # for non-multivalued JOINs (e.g. foreign key fields). This should take + # into account only many-to-many and one-to-many relationships. + col.possibly_multivalued = LOOKUP_SEP in self.name + return col + def relabeled_clone(self, relabels): return self @@ -744,6 +753,7 @@ class Random(Expression): class Col(Expression): contains_column_references = True + possibly_multivalued = False def __init__(self, alias, target, output_field=None): if output_field is None: @@ -1068,7 +1078,10 @@ class Subquery(Expression): def get_group_by_cols(self, alias=None): if alias: return [Ref(alias, self)] - return self.query.get_external_cols() + external_cols = self.query.get_external_cols() + if any(col.possibly_multivalued for col in external_cols): + return [self] + return external_cols class Exists(Subquery): -- cgit v1.3