mirror of
https://github.com/django/django.git
synced 2025-10-29 08:36:09 +00:00
Fixed #31679 -- Delayed annotating aggregations.
By avoiding to annotate aggregations meant to be possibly pushed to an outer query until their references are resolved it is possible to aggregate over a query with the same alias. Even if #34176 is a convoluted case to support, this refactor seems worth it given the reduction in complexity it brings with regards to annotation removal when performing a subquery pushdown.
This commit is contained in:
committed by
Mariusz Felisiak
parent
d526d1569c
commit
1297c0d0d7
@@ -23,7 +23,7 @@ from django.db import (
|
||||
from django.db.models import AutoField, DateField, DateTimeField, Field, sql
|
||||
from django.db.models.constants import LOOKUP_SEP, OnConflict
|
||||
from django.db.models.deletion import Collector
|
||||
from django.db.models.expressions import Case, F, Ref, Value, When
|
||||
from django.db.models.expressions import Case, F, Value, When
|
||||
from django.db.models.functions import Cast, Trunc
|
||||
from django.db.models.query_utils import FilteredRelation, Q
|
||||
from django.db.models.sql.constants import CURSOR, GET_ITERATOR_CHUNK_SIZE
|
||||
@@ -589,24 +589,7 @@ class QuerySet(AltersData):
|
||||
raise TypeError("Complex aggregates require an alias")
|
||||
kwargs[arg.default_alias] = arg
|
||||
|
||||
query = self.query.chain()
|
||||
for (alias, aggregate_expr) in kwargs.items():
|
||||
query.add_annotation(aggregate_expr, alias, is_summary=True)
|
||||
annotation = query.annotations[alias]
|
||||
if not annotation.contains_aggregate:
|
||||
raise TypeError("%s is not an aggregate expression" % alias)
|
||||
for expr in annotation.get_source_expressions():
|
||||
if (
|
||||
expr.contains_aggregate
|
||||
and isinstance(expr, Ref)
|
||||
and expr.refs in kwargs
|
||||
):
|
||||
name = expr.refs
|
||||
raise exceptions.FieldError(
|
||||
"Cannot compute %s('%s'): '%s' is an aggregate"
|
||||
% (annotation.name, name, name)
|
||||
)
|
||||
return query.get_aggregation(self.db, kwargs)
|
||||
return self.query.chain().get_aggregation(self.db, kwargs)
|
||||
|
||||
async def aaggregate(self, *args, **kwargs):
|
||||
return await sync_to_async(self.aggregate)(*args, **kwargs)
|
||||
@@ -1655,7 +1638,6 @@ class QuerySet(AltersData):
|
||||
clone.query.add_annotation(
|
||||
annotation,
|
||||
alias,
|
||||
is_summary=False,
|
||||
select=select,
|
||||
)
|
||||
for alias, annotation in clone.query.annotations.items():
|
||||
|
||||
Reference in New Issue
Block a user