summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/models/sql/query.py10
-rw-r--r--tests/regressiontests/aggregation_regress/tests.py48
2 files changed, 54 insertions, 4 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 6b9f4b6d56..f09dc313bc 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -215,10 +215,12 @@ class BaseQuery(object):
obj.aggregate_select_mask = None
else:
obj.aggregate_select_mask = self.aggregate_select_mask.copy()
- if self._aggregate_select_cache is None:
- obj._aggregate_select_cache = None
- else:
- obj._aggregate_select_cache = self._aggregate_select_cache.copy()
+ # _aggregate_select_cache cannot be copied, as doing so breaks the
+ # (necessary) state in which both aggregates and
+ # _aggregate_select_cache point to the same underlying objects.
+ # It will get re-populated in the cloned queryset the next time it's
+ # used.
+ obj._aggregate_select_cache = None
obj.max_depth = self.max_depth
obj.extra = self.extra.copy()
if self.extra_select_mask is None:
diff --git a/tests/regressiontests/aggregation_regress/tests.py b/tests/regressiontests/aggregation_regress/tests.py
new file mode 100644
index 0000000000..cf0f58a9a8
--- /dev/null
+++ b/tests/regressiontests/aggregation_regress/tests.py
@@ -0,0 +1,48 @@
+from django.test import TestCase
+from django.db.models import Max
+
+from regressiontests.aggregation_regress.models import *
+
+
+class AggregationTests(TestCase):
+
+ def test_aggregates_in_where_clause(self):
+ """
+ Regression test for #12822: DatabaseError: aggregates not allowed in
+ WHERE clause
+
+ Tests that the subselect works and returns results equivalent to a
+ query with the IDs listed.
+
+ Before the corresponding fix for this bug, this test passed in 1.1 and
+ failed in 1.2-beta (trunk).
+ """
+ qs = Book.objects.values('contact').annotate(Max('id'))
+ qs = qs.order_by('contact').values_list('id__max', flat=True)
+ # don't do anything with the queryset (qs) before including it as a
+ # subquery
+ books = Book.objects.order_by('id')
+ qs1 = books.filter(id__in=qs)
+ qs2 = books.filter(id__in=list(qs))
+ self.assertEqual(list(qs1), list(qs2))
+
+ def test_aggregates_in_where_clause_pre_eval(self):
+ """
+ Regression test for #12822: DatabaseError: aggregates not allowed in
+ WHERE clause
+
+ Same as the above test, but evaluates the queryset for the subquery
+ before it's used as a subquery.
+
+ Before the corresponding fix for this bug, this test failed in both
+ 1.1 and 1.2-beta (trunk).
+ """
+ qs = Book.objects.values('contact').annotate(Max('id'))
+ qs = qs.order_by('contact').values_list('id__max', flat=True)
+ # force the queryset (qs) for the subquery to be evaluated in its
+ # current state
+ list(qs)
+ books = Book.objects.order_by('id')
+ qs1 = books.filter(id__in=qs)
+ qs2 = books.filter(id__in=list(qs))
+ self.assertEqual(list(qs1), list(qs2))