Fixed #10182 -- Corrected realiasing and the process of evaluating values() for queries with aggregate clauses. This means that aggregate queries can now be used as subqueries (such as in an __in clause). Thanks to omat for the report.

This involves a slight change to the interaction of annotate() and values() clauses that specify a list of columns. See the docs for details.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9888 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2009-02-23 14:47:59 +00:00
parent 4bd24474c0
commit 542709d0d1
7 changed files with 102 additions and 32 deletions

View file

@ -596,7 +596,7 @@ class QuerySet(object):
obj = self._clone()
obj._setup_aggregate_query()
obj._setup_aggregate_query(kwargs.keys())
# Add the aggregates to the query
for (alias, aggregate_expr) in kwargs.items():
@ -693,7 +693,7 @@ class QuerySet(object):
"""
pass
def _setup_aggregate_query(self):
def _setup_aggregate_query(self, aggregates):
"""
Prepare the query for computing a result that contains aggregate annotations.
"""
@ -773,6 +773,8 @@ class ValuesQuerySet(QuerySet):
self.query.select = []
self.query.add_fields(self.field_names, False)
if self.aggregate_names is not None:
self.query.set_aggregate_mask(self.aggregate_names)
def _clone(self, klass=None, setup=False, **kwargs):
"""
@ -798,13 +800,17 @@ class ValuesQuerySet(QuerySet):
raise TypeError("Merging '%s' classes must involve the same values in each case."
% self.__class__.__name__)
def _setup_aggregate_query(self):
def _setup_aggregate_query(self, aggregates):
"""
Prepare the query for computing a result that contains aggregate annotations.
"""
self.query.set_group_by()
super(ValuesQuerySet, self)._setup_aggregate_query()
if self.aggregate_names is not None:
self.aggregate_names.extend(aggregates)
self.query.set_aggregate_mask(self.aggregate_names)
super(ValuesQuerySet, self)._setup_aggregate_query(aggregates)
def as_sql(self):
"""
@ -824,6 +830,7 @@ class ValuesListQuerySet(ValuesQuerySet):
def iterator(self):
if self.extra_names is not None:
self.query.trim_extra_select(self.extra_names)
if self.flat and len(self._fields) == 1:
for row in self.query.results_iter():
yield row[0]
@ -837,6 +844,7 @@ class ValuesListQuerySet(ValuesQuerySet):
extra_names = self.query.extra_select.keys()
field_names = self.field_names
aggregate_names = self.query.aggregate_select.keys()
names = extra_names + field_names + aggregate_names
# If a field list has been specified, use it. Otherwise, use the