From dd68af62b2b27ece50d434f6a351877212e15c3f Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Fri, 6 Jan 2023 09:10:16 -0500 Subject: Fixed #34176 -- Fixed grouping by ambiguous aliases. Regression in b7b28c7c189615543218e81319473888bc46d831. Refs #31377. Thanks Shai Berger for the report and reviews. test_aggregation_subquery_annotation_values_collision() has been updated as queries that are explicitly grouped by a subquery should always be grouped by it and not its outer columns even if its alias collides with referenced table columns. This was not possible to accomplish at the time 10866a10 landed because we didn't have compiler level handling of colliding aliases. --- django/db/models/sql/query.py | 45 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 30 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 9e70aadca1..3fe00002bd 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -2211,40 +2211,25 @@ class Query(BaseExpression): primary key, and the query would be equivalent, the optimization will be made automatically. """ - if allow_aliases: - # Column names from JOINs to check collisions with aliases. - column_names = set() - seen_models = set() - for join in list(self.alias_map.values())[1:]: # Skip base table. - model = join.join_field.related_model - if model not in seen_models: - column_names.update( - {field.column for field in model._meta.local_concrete_fields} - ) - seen_models.add(model) - if self.values_select: - # If grouping by aliases is allowed assign selected values - # aliases by moving them to annotations. - group_by_annotations = {} - values_select = {} - for alias, expr in zip(self.values_select, self.select): - if isinstance(expr, Col): - values_select[alias] = expr - else: - group_by_annotations[alias] = expr - self.annotations = {**group_by_annotations, **self.annotations} - self.append_annotation_mask(group_by_annotations) - self.select = tuple(values_select.values()) - self.values_select = tuple(values_select) + if allow_aliases and self.values_select: + # If grouping by aliases is allowed assign selected value aliases + # by moving them to annotations. + group_by_annotations = {} + values_select = {} + for alias, expr in zip(self.values_select, self.select): + if isinstance(expr, Col): + values_select[alias] = expr + else: + group_by_annotations[alias] = expr + self.annotations = {**group_by_annotations, **self.annotations} + self.append_annotation_mask(group_by_annotations) + self.select = tuple(values_select.values()) + self.values_select = tuple(values_select) group_by = list(self.select) for alias, annotation in self.annotation_select.items(): if not (group_by_cols := annotation.get_group_by_cols()): continue - if ( - allow_aliases - and alias not in column_names - and not annotation.contains_aggregate - ): + if allow_aliases and not annotation.contains_aggregate: group_by.append(Ref(alias, annotation)) else: group_by.extend(group_by_cols) -- cgit v1.3