Permalink
Browse files

Fixed #10089 -- Corrected handling of aggregates when the query set c…

…ontains no items (and the cursor returns None). Thanks to Kyle Fox for the report, and david for the initial patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9786 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent ed3d273 commit 0e15932be392ab56fa0087f9c13b234af7749e2e @freakboy3742 freakboy3742 committed Jan 23, 2009
@@ -217,6 +217,8 @@ def resolve_aggregate(self, value, aggregate):
to return Decimal and long types when they are not needed.
"""
if value is None:
+ if aggregate.is_ordinal:
+ return 0
# Return None as-is
return value
elif aggregate.is_ordinal:
@@ -295,10 +297,14 @@ def get_aggregation(self):
query.related_select_cols = []
query.related_select_fields = []
+ result = query.execute_sql(SINGLE)
+ if result is None:
+ result = [None for q in query.aggregate_select.items()]
+
return dict([
(alias, self.resolve_aggregate(val, aggregate))
for (alias, aggregate), val
- in zip(query.aggregate_select.items(), query.execute_sql(SINGLE))
+ in zip(query.aggregate_select.items(), result)
])
def get_count(self):
@@ -32,6 +32,14 @@
}
},
{
+ "pk": 5,
+ "model": "aggregation.publisher",
+ "fields": {
+ "name": "Jonno's House of Books",
+ "num_awards": 0
+ }
+ },
+ {
"pk": 1,
"model": "aggregation.book",
"fields": {
@@ -194,7 +194,7 @@ class Clues(models.Model):
# Annotate each publisher with the sum of the price of all books sold
>>> publishers = Publisher.objects.all().annotate(Sum('book__price'))
>>> sorted([(p.name, p.book__price__sum) for p in publishers])
-[(u'Apress', Decimal("59.69")), (u'Morgan Kaufmann', Decimal("75.00")), (u'Prentice Hall', Decimal("112.49")), (u'Sams', Decimal("23.09"))]
+[(u'Apress', Decimal("59.69")), (u"Jonno's House of Books", None), (u'Morgan Kaufmann', Decimal("75.00")), (u'Prentice Hall', Decimal("112.49")), (u'Sams', Decimal("23.09"))]
# Calls to values() are not commutative over annotate().
@@ -356,7 +356,7 @@ class Clues(models.Model):
[]
# Aggregates also work on dates, times and datetimes
->>> Publisher.objects.annotate(earliest_book=Min('book__pubdate')).order_by('earliest_book').values()
+>>> Publisher.objects.annotate(earliest_book=Min('book__pubdate')).exclude(earliest_book=None).order_by('earliest_book').values()
[{'earliest_book': datetime.date(1991, 10, 15), 'num_awards': 9, 'id': 4, 'name': u'Morgan Kaufmann'}, {'earliest_book': datetime.date(1995, 1, 15), 'num_awards': 7, 'id': 3, 'name': u'Prentice Hall'}, {'earliest_book': datetime.date(2007, 12, 6), 'num_awards': 3, 'id': 1, 'name': u'Apress'}, {'earliest_book': datetime.date(2008, 3, 3), 'num_awards': 1, 'id': 2, 'name': u'Sams'}]
>>> Store.objects.aggregate(Max('friday_night_closing'), Min("original_opening"))
@@ -32,6 +32,14 @@
}
},
{
+ "pk": 5,
+ "model": "aggregation_regress.publisher",
+ "fields": {
+ "name": "Jonno's House of Books",
+ "num_awards": 0
+ }
+ },
+ {
"pk": 1,
"model": "aggregation_regress.book",
"fields": {
@@ -164,6 +164,16 @@ def __unicode__(self):
>>> len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__lt=2).filter(num_authors__lt=3))
2
+# Regression for #10089: Check handling of empty result sets with aggregates
+>>> Book.objects.filter(id__in=[]).count()
+0
+
+>>> Book.objects.filter(id__in=[]).aggregate(num_authors=Count('authors'), avg_authors=Avg('authors'), max_authors=Max('authors'), max_price=Max('price'), max_rating=Max('rating'))
+{'max_authors': None, 'max_rating': None, 'num_authors': 0, 'avg_authors': None, 'max_price': None}
+
+>>> Publisher.objects.filter(pk=5).annotate(num_authors=Count('book__authors'), avg_authors=Avg('book__authors'), max_authors=Max('book__authors'), max_price=Max('book__price'), max_rating=Max('book__rating')).values()
+[{'max_authors': None, 'name': u"Jonno's House of Books", 'num_awards': 0, 'max_price': None, 'num_authors': 0, 'max_rating': None, 'id': 5, 'avg_authors': None}]
+
"""
}

0 comments on commit 0e15932

Please sign in to comment.