mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #10089 -- Corrected handling of aggregates when the query set contains 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
This commit is contained in:
		| @@ -217,6 +217,8 @@ class BaseQuery(object): | |||||||
|         to return Decimal and long types when they are not needed. |         to return Decimal and long types when they are not needed. | ||||||
|         """ |         """ | ||||||
|         if value is None: |         if value is None: | ||||||
|  |             if aggregate.is_ordinal: | ||||||
|  |                 return 0 | ||||||
|             # Return None as-is |             # Return None as-is | ||||||
|             return value |             return value | ||||||
|         elif aggregate.is_ordinal: |         elif aggregate.is_ordinal: | ||||||
| @@ -295,10 +297,14 @@ class BaseQuery(object): | |||||||
|         query.related_select_cols = [] |         query.related_select_cols = [] | ||||||
|         query.related_select_fields = [] |         query.related_select_fields = [] | ||||||
|  |  | ||||||
|  |         result = query.execute_sql(SINGLE) | ||||||
|  |         if result is None: | ||||||
|  |             result = [None for q in query.aggregate_select.items()] | ||||||
|  |  | ||||||
|         return dict([ |         return dict([ | ||||||
|             (alias, self.resolve_aggregate(val, aggregate)) |             (alias, self.resolve_aggregate(val, aggregate)) | ||||||
|             for (alias, aggregate), val |             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): |     def get_count(self): | ||||||
|   | |||||||
| @@ -31,6 +31,14 @@ | |||||||
|             "num_awards": 9 |             "num_awards": 9 | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |         "pk": 5, | ||||||
|  |         "model": "aggregation.publisher", | ||||||
|  |         "fields": { | ||||||
|  |             "name": "Jonno's House of Books", | ||||||
|  |             "num_awards": 0 | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|         "pk": 1, |         "pk": 1, | ||||||
|         "model": "aggregation.book", |         "model": "aggregation.book", | ||||||
|   | |||||||
| @@ -194,7 +194,7 @@ u'The Definitive Guide to Django: Web Development Done Right' | |||||||
| # Annotate each publisher with the sum of the price of all books sold | # Annotate each publisher with the sum of the price of all books sold | ||||||
| >>> publishers = Publisher.objects.all().annotate(Sum('book__price')) | >>> publishers = Publisher.objects.all().annotate(Sum('book__price')) | ||||||
| >>> sorted([(p.name, p.book__price__sum) for p in publishers]) | >>> 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(). | # Calls to values() are not commutative over annotate(). | ||||||
|  |  | ||||||
| @@ -356,7 +356,7 @@ True | |||||||
| [] | [] | ||||||
|  |  | ||||||
| # Aggregates also work on dates, times and datetimes | # 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'}] | [{'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")) | >>> Store.objects.aggregate(Max('friday_night_closing'), Min("original_opening")) | ||||||
|   | |||||||
| @@ -31,6 +31,14 @@ | |||||||
|             "num_awards": 9 |             "num_awards": 9 | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |         "pk": 5, | ||||||
|  |         "model": "aggregation_regress.publisher", | ||||||
|  |         "fields": { | ||||||
|  |             "name": "Jonno's House of Books", | ||||||
|  |             "num_awards": 0 | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|         "pk": 1, |         "pk": 1, | ||||||
|         "model": "aggregation_regress.book", |         "model": "aggregation_regress.book", | ||||||
|   | |||||||
| @@ -164,6 +164,16 @@ FieldError: Cannot resolve keyword 'foo' into field. Choices are: authors, id, i | |||||||
| >>> len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__lt=2).filter(num_authors__lt=3)) | >>> len(Book.objects.annotate(num_authors=Count('authors')).exclude(num_authors__lt=2).filter(num_authors__lt=3)) | ||||||
| 2 | 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}] | ||||||
|  |  | ||||||
| """ | """ | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user