Skip to content

Commit 03b111c

Browse files
committed
[1.2.X] Fixed #12687 -- fixed an issue with aggregates and counts in conjunction with annotations where the QuerySet was provably empty. Backport of [14586].
git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@14587 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 929b8ff commit 03b111c

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

django/db/models/sql/aggregates.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class AggregateField(object):
88
"""
99
def __init__(self, internal_type):
1010
self.internal_type = internal_type
11+
1112
def get_internal_type(self):
1213
return self.internal_type
1314

django/db/models/sql/query.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def get_aggregation(self, using):
337337
# information but retrieves only the first row. Aggregate
338338
# over the subquery instead.
339339
if self.group_by is not None:
340-
from subqueries import AggregateQuery
340+
from django.db.models.sql.subqueries import AggregateQuery
341341
query = AggregateQuery(self.model)
342342

343343
obj = self.clone()
@@ -349,7 +349,13 @@ def get_aggregation(self, using):
349349
query.aggregate_select[alias] = aggregate
350350
del obj.aggregate_select[alias]
351351

352-
query.add_subquery(obj, using)
352+
try:
353+
query.add_subquery(obj, using)
354+
except EmptyResultSet:
355+
return dict(
356+
(alias, None)
357+
for alias in query.aggregate_select
358+
)
353359
else:
354360
query = self
355361
self.select = []
@@ -382,13 +388,19 @@ def get_count(self, using):
382388
# If a select clause exists, then the query has already started to
383389
# specify the columns that are to be returned.
384390
# In this case, we need to use a subquery to evaluate the count.
385-
from subqueries import AggregateQuery
391+
from django.db.models.sql.subqueries import AggregateQuery
386392
subquery = obj
387393
subquery.clear_ordering(True)
388394
subquery.clear_limits()
389395

390396
obj = AggregateQuery(obj.model)
391-
obj.add_subquery(subquery, using=using)
397+
try:
398+
obj.add_subquery(subquery, using=using)
399+
except EmptyResultSet:
400+
# add_subquery evaluates the query, if it's an EmptyResultSet
401+
# then there are can be no results, and therefore there the
402+
# count is obviously 0
403+
return 0
392404

393405
obj.add_count_column()
394406
number = obj.get_aggregation(using=using)[None]

django/db/models/sql/subqueries.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from django.db.models.sql.query import Query
1111
from django.db.models.sql.where import AND, Constraint
1212

13+
1314
__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery',
1415
'AggregateQuery']
1516

tests/regressiontests/aggregation_regress/tests.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,24 @@ def test_more_more_more(self):
641641
lambda: Book.objects.annotate(mean_age=Avg('authors__age')).annotate(Avg('mean_age'))
642642
)
643643

644+
def test_empty_filter_count(self):
645+
self.assertEqual(
646+
Author.objects.filter(id__in=[]).annotate(Count("friends")).count(),
647+
0
648+
)
649+
650+
def test_empty_filter_aggregate(self):
651+
self.assertEqual(
652+
Author.objects.filter(id__in=[]).annotate(Count("friends")).aggregate(Count("pk")),
653+
{"pk__count": None}
654+
)
655+
656+
def test_annotate_and_join(self):
657+
self.assertEqual(
658+
Author.objects.annotate(c=Count("friends__name")).exclude(friends__name="Joe").count(),
659+
Author.objects.count()
660+
)
661+
644662
if run_stddev_tests():
645663
def test_stddev(self):
646664
self.assertEqual(

0 commit comments

Comments
 (0)