Author: Alex Date: 2010-11-16 20:58:59 -0600 (Tue, 16 Nov 2010) New Revision: 14587
Modified: django/branches/releases/1.2.X/django/db/models/sql/aggregates.py django/branches/releases/1.2.X/django/db/models/sql/query.py django/branches/releases/1.2.X/django/db/models/sql/subqueries.py django/branches/releases/1.2.X/tests/regressiontests/aggregation_regress/tests.py Log: [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]. Modified: django/branches/releases/1.2.X/django/db/models/sql/aggregates.py =================================================================== --- django/branches/releases/1.2.X/django/db/models/sql/aggregates.py 2010-11-17 02:57:14 UTC (rev 14586) +++ django/branches/releases/1.2.X/django/db/models/sql/aggregates.py 2010-11-17 02:58:59 UTC (rev 14587) @@ -8,6 +8,7 @@ """ def __init__(self, internal_type): self.internal_type = internal_type + def get_internal_type(self): return self.internal_type Modified: django/branches/releases/1.2.X/django/db/models/sql/query.py =================================================================== --- django/branches/releases/1.2.X/django/db/models/sql/query.py 2010-11-17 02:57:14 UTC (rev 14586) +++ django/branches/releases/1.2.X/django/db/models/sql/query.py 2010-11-17 02:58:59 UTC (rev 14587) @@ -337,7 +337,7 @@ # information but retrieves only the first row. Aggregate # over the subquery instead. if self.group_by is not None: - from subqueries import AggregateQuery + from django.db.models.sql.subqueries import AggregateQuery query = AggregateQuery(self.model) obj = self.clone() @@ -349,7 +349,13 @@ query.aggregate_select[alias] = aggregate del obj.aggregate_select[alias] - query.add_subquery(obj, using) + try: + query.add_subquery(obj, using) + except EmptyResultSet: + return dict( + (alias, None) + for alias in query.aggregate_select + ) else: query = self self.select = [] @@ -382,13 +388,19 @@ # If a select clause exists, then the query has already started to # specify the columns that are to be returned. # In this case, we need to use a subquery to evaluate the count. - from subqueries import AggregateQuery + from django.db.models.sql.subqueries import AggregateQuery subquery = obj subquery.clear_ordering(True) subquery.clear_limits() obj = AggregateQuery(obj.model) - obj.add_subquery(subquery, using=using) + try: + obj.add_subquery(subquery, using=using) + except EmptyResultSet: + # add_subquery evaluates the query, if it's an EmptyResultSet + # then there are can be no results, and therefore there the + # count is obviously 0 + return 0 obj.add_count_column() number = obj.get_aggregation(using=using)[None] Modified: django/branches/releases/1.2.X/django/db/models/sql/subqueries.py =================================================================== --- django/branches/releases/1.2.X/django/db/models/sql/subqueries.py 2010-11-17 02:57:14 UTC (rev 14586) +++ django/branches/releases/1.2.X/django/db/models/sql/subqueries.py 2010-11-17 02:58:59 UTC (rev 14587) @@ -10,6 +10,7 @@ from django.db.models.sql.query import Query from django.db.models.sql.where import AND, Constraint + __all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery', 'AggregateQuery'] Modified: django/branches/releases/1.2.X/tests/regressiontests/aggregation_regress/tests.py =================================================================== --- django/branches/releases/1.2.X/tests/regressiontests/aggregation_regress/tests.py 2010-11-17 02:57:14 UTC (rev 14586) +++ django/branches/releases/1.2.X/tests/regressiontests/aggregation_regress/tests.py 2010-11-17 02:58:59 UTC (rev 14587) @@ -641,6 +641,24 @@ lambda: Book.objects.annotate(mean_age=Avg('authors__age')).annotate(Avg('mean_age')) ) + def test_empty_filter_count(self): + self.assertEqual( + Author.objects.filter(id__in=[]).annotate(Count("friends")).count(), + 0 + ) + + def test_empty_filter_aggregate(self): + self.assertEqual( + Author.objects.filter(id__in=[]).annotate(Count("friends")).aggregate(Count("pk")), + {"pk__count": None} + ) + + def test_annotate_and_join(self): + self.assertEqual( + Author.objects.annotate(c=Count("friends__name")).exclude(friends__name="Joe").count(), + Author.objects.count() + ) + if run_stddev_tests(): def test_stddev(self): self.assertEqual( -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.