Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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...
commit 0e15932be392ab56fa0087f9c13b234af7749e2e 1 parent ed3d273
Russell Keith-Magee authored January 23, 2009
8  django/db/models/sql/query.py
@@ -217,6 +217,8 @@ def resolve_aggregate(self, value, aggregate):
217 217
         to return Decimal and long types when they are not needed.
218 218
         """
219 219
         if value is None:
  220
+            if aggregate.is_ordinal:
  221
+                return 0
220 222
             # Return None as-is
221 223
             return value
222 224
         elif aggregate.is_ordinal:
@@ -295,10 +297,14 @@ def get_aggregation(self):
295 297
         query.related_select_cols = []
296 298
         query.related_select_fields = []
297 299
 
  300
+        result = query.execute_sql(SINGLE)
  301
+        if result is None:
  302
+            result = [None for q in query.aggregate_select.items()]
  303
+
298 304
         return dict([
299 305
             (alias, self.resolve_aggregate(val, aggregate))
300 306
             for (alias, aggregate), val
301  
-            in zip(query.aggregate_select.items(), query.execute_sql(SINGLE))
  307
+            in zip(query.aggregate_select.items(), result)
302 308
         ])
303 309
 
304 310
     def get_count(self):
8  tests/modeltests/aggregation/fixtures/initial_data.json
@@ -32,6 +32,14 @@
32 32
         }
33 33
     },
34 34
     {
  35
+        "pk": 5,
  36
+        "model": "aggregation.publisher",
  37
+        "fields": {
  38
+            "name": "Jonno's House of Books",
  39
+            "num_awards": 0
  40
+        }
  41
+    },
  42
+    {
35 43
         "pk": 1,
36 44
         "model": "aggregation.book",
37 45
         "fields": {
4  tests/modeltests/aggregation/models.py
@@ -194,7 +194,7 @@ class Clues(models.Model):
194 194
 # Annotate each publisher with the sum of the price of all books sold
195 195
 >>> publishers = Publisher.objects.all().annotate(Sum('book__price'))
196 196
 >>> sorted([(p.name, p.book__price__sum) for p in publishers])
197  
-[(u'Apress', Decimal("59.69")), (u'Morgan Kaufmann', Decimal("75.00")), (u'Prentice Hall', Decimal("112.49")), (u'Sams', Decimal("23.09"))]
  197
+[(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"))]
198 198
 
199 199
 # Calls to values() are not commutative over annotate().
200 200
 
@@ -356,7 +356,7 @@ class Clues(models.Model):
356 356
 []
357 357
 
358 358
 # Aggregates also work on dates, times and datetimes
359  
->>> Publisher.objects.annotate(earliest_book=Min('book__pubdate')).order_by('earliest_book').values()
  359
+>>> Publisher.objects.annotate(earliest_book=Min('book__pubdate')).exclude(earliest_book=None).order_by('earliest_book').values()
360 360
 [{'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'}]
361 361
 
362 362
 >>> Store.objects.aggregate(Max('friday_night_closing'), Min("original_opening"))
8  tests/regressiontests/aggregation_regress/fixtures/initial_data.json
@@ -32,6 +32,14 @@
32 32
         }
33 33
     },
34 34
     {
  35
+        "pk": 5,
  36
+        "model": "aggregation_regress.publisher",
  37
+        "fields": {
  38
+            "name": "Jonno's House of Books",
  39
+            "num_awards": 0
  40
+        }
  41
+    },
  42
+    {
35 43
         "pk": 1,
36 44
         "model": "aggregation_regress.book",
37 45
         "fields": {
10  tests/regressiontests/aggregation_regress/models.py
@@ -164,6 +164,16 @@ def __unicode__(self):
164 164
 >>> len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__lt=2).filter(num_authors__lt=3))
165 165
 2
166 166
 
  167
+# Regression for #10089: Check handling of empty result sets with aggregates
  168
+>>> Book.objects.filter(id__in=[]).count()
  169
+0
  170
+
  171
+>>> 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'))
  172
+{'max_authors': None, 'max_rating': None, 'num_authors': 0, 'avg_authors': None, 'max_price': None}
  173
+
  174
+>>> 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()
  175
+[{'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}]
  176
+
167 177
 """
168 178
 }
169 179
 

0 notes on commit 0e15932

Please sign in to comment.
Something went wrong with that request. Please try again.