[3.1.x] Fixed #31607 -- Fixed evaluated Subquery equality.

Regression in 691def10a0.

Backport of a125da6a7c from master
This commit is contained in:
Mariusz Felisiak 2020-05-19 12:30:49 +02:00
parent 844e0591f9
commit 937314dc05
2 changed files with 27 additions and 1 deletions

View File

@ -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):

View File

@ -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.