From 903aaa35e5ceaa33bfc9b19b7f6da65ce5a91dd4 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Thu, 30 Sep 2021 11:26:17 +0200 Subject: [PATCH] Fixed #33159 -- Reverted "Fixed #32970 -- Changed WhereNode.clone() to create a shallow copy of children." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e441847ecae99dd1ccd0d9ce76dbcff51afa863c. A shallow copy is not enough because querysets can be reused and evaluated in nested nodes, which shouldn't mutate JOIN aliases. Thanks Michal Čihař for the report. --- django/db/models/sql/where.py | 6 +++++- tests/queries/tests.py | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index 160d5733b8..50ff13be75 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -148,7 +148,11 @@ class WhereNode(tree.Node): clone = self.__class__._new_instance( children=None, connector=self.connector, negated=self.negated, ) - clone.children = self.children[:] + for child in self.children: + if hasattr(child, 'clone'): + clone.children.append(child.clone()) + else: + clone.children.append(child) return clone def relabeled_clone(self, change_map): diff --git a/tests/queries/tests.py b/tests/queries/tests.py index fa87e7859c..9c1b41a395 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -1663,6 +1663,12 @@ class Queries5Tests(TestCase): 'bar %s' ) + def test_queryset_reuse(self): + # Using querysets doesn't mutate aliases. + authors = Author.objects.filter(Q(name='a1') | Q(name='nonexistent')) + self.assertEqual(Ranking.objects.filter(author__in=authors).get(), self.rank3) + self.assertEqual(authors.count(), 1) + class SelectRelatedTests(TestCase): def test_tickets_3045_3288(self):