Code

Ticket #12822: ticket_12822_tests_with_fix.diff

File ticket_12822_tests_with_fix.diff, 3.0 KB (added by tobias, 4 years ago)

patch with tests + fix

Line 
1diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
2--- a/django/db/models/sql/query.py
3+++ b/django/db/models/sql/query.py
4@@ -240,10 +240,12 @@
5             obj.aggregate_select_mask = None
6         else:
7             obj.aggregate_select_mask = self.aggregate_select_mask.copy()
8-        if self._aggregate_select_cache is None:
9-            obj._aggregate_select_cache = None
10-        else:
11-            obj._aggregate_select_cache = self._aggregate_select_cache.copy()
12+        # _aggregate_select_cache cannot be copied, as doing so breaks the
13+        # (necessary) state in which both aggregates and
14+        # _aggregate_select_cache point to the same underlying objects.
15+        # It will get re-populated in the cloned queryset the next time it's
16+        # used.
17+        obj._aggregate_select_cache = None
18         obj.max_depth = self.max_depth
19         obj.extra = self.extra.copy()
20         if self.extra_select_mask is None:
21diff --git a/tests/regressiontests/aggregation_regress/tests.py b/tests/regressiontests/aggregation_regress/tests.py
22new file mode 100644
23--- /dev/null
24+++ b/tests/regressiontests/aggregation_regress/tests.py
25@@ -0,0 +1,48 @@
26+from django.test import TestCase
27+from django.db.models import Max
28+
29+from regressiontests.aggregation_regress.models import *
30+
31+
32+class AggregationTests(TestCase):
33+
34+    def test_aggregates_in_where_clause(self):
35+        """
36+        Regression test for #12822: DatabaseError: aggregates not allowed in
37+        WHERE clause
38+
39+        Tests that the subselect works and returns results equivalent to a
40+        query with the IDs listed.
41+       
42+        Before the corresponding fix for this bug, this test passed in 1.1 and
43+        failed in 1.2-beta (trunk).
44+        """
45+        qs = Book.objects.values('contact').annotate(Max('id'))
46+        qs = qs.order_by('contact').values_list('id__max', flat=True)
47+        # don't do anything with the queryset (qs) before including it as a
48+        # subquery
49+        books = Book.objects.order_by('id')
50+        qs1 = books.filter(id__in=qs)
51+        qs2 = books.filter(id__in=list(qs))
52+        self.assertEqual(list(qs1), list(qs2))
53+
54+    def test_aggregates_in_where_clause_pre_eval(self):
55+        """
56+        Regression test for #12822: DatabaseError: aggregates not allowed in
57+        WHERE clause
58+
59+        Same as the above test, but evaluates the queryset for the subquery
60+        before it's used as a subquery.
61+       
62+        Before the corresponding fix for this bug, this test failed in both
63+        1.1 and 1.2-beta (trunk).
64+        """
65+        qs = Book.objects.values('contact').annotate(Max('id'))
66+        qs = qs.order_by('contact').values_list('id__max', flat=True)
67+        # force the queryset (qs) for the subquery to be evaluated in its
68+        # current state
69+        list(qs)
70+        books = Book.objects.order_by('id')
71+        qs1 = books.filter(id__in=qs)
72+        qs2 = books.filter(id__in=list(qs))
73+        self.assertEqual(list(qs1), list(qs2))