mirror of
https://github.com/django/django.git
synced 2025-11-27 22:05:04 +00:00
Fixed #31094 -- Included columns referenced by subqueries in GROUP BY on aggregations.
Thanks Johannes Hoppe for the report.
Regression in fb3f034f1c.
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
a0f34d8fef
commit
5a4d7285bd
5 changed files with 58 additions and 18 deletions
|
|
@ -157,7 +157,8 @@ class Query(BaseExpression):
|
|||
# Sometimes the query contains references to aliases in outer queries (as
|
||||
# a result of split_exclude). Correct alias quoting needs to know these
|
||||
# aliases too.
|
||||
self.external_aliases = set()
|
||||
# Map external tables to whether they are aliased.
|
||||
self.external_aliases = {}
|
||||
self.table_map = {} # Maps table names to list of aliases.
|
||||
self.default_cols = True
|
||||
self.default_ordering = True
|
||||
|
|
@ -855,8 +856,11 @@ class Query(BaseExpression):
|
|||
if alias == old_alias:
|
||||
table_aliases[pos] = new_alias
|
||||
break
|
||||
self.external_aliases = {change_map.get(alias, alias)
|
||||
for alias in self.external_aliases}
|
||||
self.external_aliases = {
|
||||
# Table is aliased or it's being changed and thus is aliased.
|
||||
change_map.get(alias, alias): (aliased or alias in change_map)
|
||||
for alias, aliased in self.external_aliases.items()
|
||||
}
|
||||
|
||||
def bump_prefix(self, outer_query):
|
||||
"""
|
||||
|
|
@ -1030,19 +1034,23 @@ class Query(BaseExpression):
|
|||
for key, value in clone.annotations.items():
|
||||
resolved = value.resolve_expression(query, *args, **kwargs)
|
||||
if hasattr(resolved, 'external_aliases'):
|
||||
resolved.external_aliases.update(clone.alias_map)
|
||||
resolved.external_aliases.update(clone.external_aliases)
|
||||
clone.annotations[key] = resolved
|
||||
# Outer query's aliases are considered external.
|
||||
clone.external_aliases.update(
|
||||
alias for alias, table in query.alias_map.items()
|
||||
if (
|
||||
isinstance(table, Join) and table.join_field.related_model._meta.db_table != alias
|
||||
) or (
|
||||
isinstance(table, BaseTable) and table.table_name != table.table_alias
|
||||
for alias, table in query.alias_map.items():
|
||||
clone.external_aliases[alias] = (
|
||||
(isinstance(table, Join) and table.join_field.related_model._meta.db_table != alias) or
|
||||
(isinstance(table, BaseTable) and table.table_name != table.table_alias)
|
||||
)
|
||||
)
|
||||
return clone
|
||||
|
||||
def get_external_cols(self):
|
||||
exprs = chain(self.annotations.values(), self.where.children)
|
||||
return [
|
||||
col for col in self._gen_cols(exprs)
|
||||
if col.alias in self.external_aliases
|
||||
]
|
||||
|
||||
def as_sql(self, compiler, connection):
|
||||
sql, params = self.get_compiler(connection=connection).as_sql()
|
||||
if self.subquery:
|
||||
|
|
@ -1635,12 +1643,16 @@ class Query(BaseExpression):
|
|||
return targets, joins[-1], joins
|
||||
|
||||
@classmethod
|
||||
def _gen_col_aliases(cls, exprs):
|
||||
def _gen_cols(cls, exprs):
|
||||
for expr in exprs:
|
||||
if isinstance(expr, Col):
|
||||
yield expr.alias
|
||||
yield expr
|
||||
else:
|
||||
yield from cls._gen_col_aliases(expr.get_source_expressions())
|
||||
yield from cls._gen_cols(expr.get_source_expressions())
|
||||
|
||||
@classmethod
|
||||
def _gen_col_aliases(cls, exprs):
|
||||
yield from (expr.alias for expr in cls._gen_cols(exprs))
|
||||
|
||||
def resolve_ref(self, name, allow_joins=True, reuse=None, summarize=False):
|
||||
if not allow_joins and LOOKUP_SEP in name:
|
||||
|
|
@ -1733,7 +1745,7 @@ class Query(BaseExpression):
|
|||
lookup = lookup_class(pk.get_col(query.select[0].alias),
|
||||
pk.get_col(alias))
|
||||
query.where.add(lookup, AND)
|
||||
query.external_aliases.add(alias)
|
||||
query.external_aliases[alias] = True
|
||||
|
||||
condition, needed_inner = self.build_filter(
|
||||
('%s__in' % trimmed_prefix, query),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue