| | 1 | # coding: utf-8 |
| | 2 | # test for fault in joins with aggregates |
| | 3 | from django.db import models |
| | 4 | |
| | 5 | class Category(models.Model): |
| | 6 | name = models.CharField(max_length=100) |
| | 7 | order = models.IntegerField() |
| | 8 | |
| | 9 | def __unicode__(self): |
| | 10 | return self.name |
| | 11 | |
| | 12 | class Group(models.Model): |
| | 13 | category = models.ForeignKey(Category) |
| | 14 | name = models.CharField(max_length=300) |
| | 15 | |
| | 16 | def __unicode__(self): |
| | 17 | return self.name |
| | 18 | |
| | 19 | class Registration(models.Model): |
| | 20 | group = models.ForeignKey(Group) |
| | 21 | type = models.SmallIntegerField() |
| | 22 | time = models.IntegerField() |
| | 23 | |
| | 24 | __test__ = {'API_TESTS': """ |
| | 25 | >>> from django.db.models import Sum |
| | 26 | |
| | 27 | # the categories are reversely ordered: |
| | 28 | >>> Category.objects.order_by('order') |
| | 29 | [<Category: Cat 2>, <Category: Cat 1>] |
| | 30 | |
| | 31 | # all groups order by category.order |
| | 32 | >>> qs = Group.objects.order_by('category__order').distinct() |
| | 33 | >>> [(group.id, group.category.id) for group in qs] |
| | 34 | [(2, 2), (4, 2), (1, 1), (3, 1)] |
| | 35 | |
| | 36 | # annotated |
| | 37 | >>> qs = Group.objects.annotate(sum_time = Sum('registration__time') \ |
| | 38 | ).order_by('id') |
| | 39 | >>> [(group.id, group.category.id, group.sum_time) for group in qs] |
| | 40 | [(1, 1, 3), (2, 2, 12), (3, 1, 48), (4, 2, None)] |
| | 41 | |
| | 42 | # annotated and ordered |
| | 43 | # this fails on PostGres because the ordering column is not included in the |
| | 44 | # GROUP BY |
| | 45 | >>> qs = Group.objects.annotate(sum_time = Sum('registration__time') \ |
| | 46 | ).order_by('category__order') |
| | 47 | >>> [(group.id, group.category.id, group.sum_time) for group in qs] |
| | 48 | [(2, 2, 12), (4, 2, None), (1, 1, 3), (3, 1, 48)] |
| | 49 | |
| | 50 | # filtered and ordered |
| | 51 | # this is a dummy filter, but it joins the tables so only the ones |
| | 52 | # with registrations return |
| | 53 | # requires distinct |
| | 54 | # also fails on postgres |
| | 55 | >>> qs = Group.objects.filter(registration__type__gt=0 \ |
| | 56 | ).order_by('category__order').distinct() |
| | 57 | >>> [(group.id, group.category.id) for group in qs] |
| | 58 | [(2, 2), (1, 1), (3, 1)] |
| | 59 | |
| | 60 | # filtered, annotated and ordered |
| | 61 | # this fails on postgres (missing in group by) |
| | 62 | # but also on sqlite: wrong result |
| | 63 | # I get this: [(4, 2, 256), (2, 2, 12), (1, 1, 3), (3, 1, 240)] |
| | 64 | # the result for group 4 includes all registrations |
| | 65 | >>> qs = Group.objects.filter(registration__type__gt=0 \ |
| | 66 | ).annotate(sum_time = Sum('registration__time') \ |
| | 67 | ).order_by('category__order') |
| | 68 | >>> [(group.id, group.category.id, group.sum_time) for group in qs] |
| | 69 | [(2, 2, 12), (1, 1, 3), (3, 1, 48)] |
| | 70 | >>> qs.query.as_sql() |
| | 71 | |
| | 72 | # notice how the inner join for the order_by comes after the left outer joins |
| | 73 | # putting the inner join first gives the correct result |
| | 74 | |
| | 75 | # filtered, annotated, but unordered |
| | 76 | >>> qs = Group.objects.filter(registration__type__gt=0 \ |
| | 77 | ).annotate(sum_time = Sum('registration__time') \ |
| | 78 | ).order_by('id') |
| | 79 | >>> [(group.id, group.category.id, group.sum_time) for group in qs] |
| | 80 | [(1, 1, 3), (2, 2, 12), (3, 1, 48)] |
| | 81 | |
| | 82 | # annotated but unordered and unfiltered |
| | 83 | >>> qs = Group.objects.annotate(sum_time = Sum('registration__time') \ |
| | 84 | ).order_by('id') |
| | 85 | >>> [(group.id, group.category.id, group.sum_time) for group in qs] |
| | 86 | [(1, 1, 3), (2, 2, 12), (3, 1, 48), (4, 2, None)] |
| | 87 | |
| | 88 | # filtered but unordered |
| | 89 | >>> qs = Group.objects.filter(registration__type__gt=0 \ |
| | 90 | ).order_by('id').distinct() |
| | 91 | >>> [(group.id, group.category.id) for group in qs] |
| | 92 | [(1, 1), (2, 2), (3, 1)] |
| | 93 | |
| | 94 | """} |