summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2020-05-19 12:30:49 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-05-19 22:50:36 +0200
commit937314dc05ee06eca91fcbb3ddf4380a60275b59 (patch)
tree20c8fbdf746838ca761dc159f3ce2f5cc6680b20
parent844e0591f9591854a0411fb8d90282737f17c40c (diff)
[3.1.x] Fixed #31607 -- Fixed evaluated Subquery equality.
Regression in 691def10a0197d83d2d108bd9043b0916d0f09b4. Backport of a125da6a7c79b1d4c55677d0bed6f9b1d7d77353 from master
-rw-r--r--django/db/models/expressions.py9
-rw-r--r--tests/expressions/tests.py19
2 files changed, 27 insertions, 1 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index eb5fafc90b..89332699d5 100644
--- a/django/db/models/expressions.py
+++ b/django/db/models/expressions.py
@@ -1021,11 +1021,18 @@ class Subquery(Expression):
def __init__(self, queryset, output_field=None, **extra):
self.query = queryset.query
self.extra = extra
+ # Prevent the QuerySet from being evaluated.
+ self.queryset = queryset._chain(_result_cache=[], prefetch_done=True)
super().__init__(output_field)
def __getstate__(self):
state = super().__getstate__()
- state.pop('_constructor_args', None)
+ args, kwargs = state['_constructor_args']
+ if args:
+ args = (self.queryset, *args[1:])
+ else:
+ kwargs['queryset'] = self.queryset
+ state['_constructor_args'] = args, kwargs
return state
def get_source_expressions(self):
diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py
index b17a286d5d..72bca4f205 100644
--- a/tests/expressions/tests.py
+++ b/tests/expressions/tests.py
@@ -511,6 +511,25 @@ class BasicExpressionsTests(TestCase):
Employee.objects.exclude(company_point_of_contact_set=None).values('pk')
)
+ def test_subquery_eq(self):
+ qs = Employee.objects.annotate(
+ is_ceo=Exists(Company.objects.filter(ceo=OuterRef('pk'))),
+ is_point_of_contact=Exists(
+ Company.objects.filter(point_of_contact=OuterRef('pk')),
+ ),
+ small_company=Exists(
+ queryset=Company.objects.filter(num_employees__lt=200),
+ ),
+ ).filter(is_ceo=True, is_point_of_contact=False, small_company=True)
+ self.assertNotEqual(
+ qs.query.annotations['is_ceo'],
+ qs.query.annotations['is_point_of_contact'],
+ )
+ self.assertNotEqual(
+ qs.query.annotations['is_ceo'],
+ qs.query.annotations['small_company'],
+ )
+
def test_in_subquery(self):
# This is a contrived test (and you really wouldn't write this query),
# but it is a succinct way to test the __in=Subquery() construct.