Ticket #10113: aggr_joins.diff

File aggr_joins.diff, 5.9 KB (added by Koen Biermans <koen.biermans@…>, 7 years ago)

small testcase demonstrating the problem

  • tests/regressiontests/aggr_joins/fixtures/initial_data.json

     
     1[
     2    {
     3        "pk": 1,
     4        "model": "aggr_joins.category",
     5        "fields": {
     6            "name": "Cat 1",
     7            "order": 2
     8        }
     9    },
     10    {
     11        "pk": 2,
     12        "model": "aggr_joins.category",
     13        "fields": {
     14            "name": "Cat 2",
     15            "order": 1
     16        }
     17    },
     18    {
     19        "pk": 1,
     20        "model": "aggr_joins.group",
     21        "fields": {
     22            "name": "Group 1",
     23            "category": 1
     24        }
     25    },
     26    {
     27        "pk": 2,
     28        "model": "aggr_joins.group",
     29        "fields": {
     30            "name": "Group 2",
     31            "category": 2
     32        }
     33    },
     34    {
     35        "pk": 3,
     36        "model": "aggr_joins.group",
     37        "fields": {
     38            "name": "Group 3",
     39            "category": 1
     40        }
     41    },
     42    {
     43        "pk": 4,
     44        "model": "aggr_joins.group",
     45        "fields": {
     46            "name": "Group 4",
     47            "category": 2
     48        }
     49    },
     50    {
     51        "pk": 1,
     52        "model": "aggr_joins.registration",
     53        "fields": {
     54            "group": 1,
     55            "type": 1,
     56            "time": 1
     57        }
     58    },
     59    {
     60        "pk": 2,
     61        "model": "aggr_joins.registration",
     62        "fields": {
     63            "group": 1,
     64            "type": 2,
     65            "time": 2
     66        }
     67    },
     68    {
     69        "pk": 3,
     70        "model": "aggr_joins.registration",
     71        "fields": {
     72            "group": 2,
     73            "type": 1,
     74            "time": 4
     75        }
     76    },
     77    {
     78        "pk": 4,
     79        "model": "aggr_joins.registration",
     80        "fields": {
     81            "group": 2,
     82            "type": 2,
     83            "time": 8
     84        }
     85    },
     86    {
     87        "pk": 5,
     88        "model": "aggr_joins.registration",
     89        "fields": {
     90            "group": 3,
     91            "type": 1,
     92            "time": 16
     93        }
     94    },
     95    {
     96        "pk": 6,
     97        "model": "aggr_joins.registration",
     98        "fields": {
     99            "group": 3,
     100            "type": 2,
     101            "time": 32
     102        }
     103    }
     104]
  • tests/regressiontests/aggr_joins/models.py

     
     1# coding: utf-8
     2# test for fault in joins with aggregates
     3from django.db import models
     4
     5class Category(models.Model):
     6    name = models.CharField(max_length=100)
     7    order = models.IntegerField()
     8
     9    def __unicode__(self):
     10        return self.name
     11
     12class 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
     19class 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"""}
Back to Top