diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 5100869b34..b3f130c0b4 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -696,6 +696,7 @@ class Query(BaseExpression): # except if the alias is the base table since it must be present in the # query on both sides. initial_alias = self.get_initial_alias() + rhs = rhs.clone() rhs.bump_prefix(self, exclude={initial_alias}) # Work out how to relabel the rhs aliases, if necessary. diff --git a/tests/queries/tests.py b/tests/queries/tests.py index 48d610bb2b..7ac8a65d42 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -1357,6 +1357,24 @@ class Queries1Tests(TestCase): ) self.assertSequenceEqual(Note.objects.exclude(negate=True), [self.n3]) + def test_combining_does_not_mutate(self): + all_authors = Author.objects.all() + authors_with_report = Author.objects.filter( + Exists(Report.objects.filter(creator__pk=OuterRef("id"))) + ) + authors_without_report = all_authors.exclude(pk__in=authors_with_report) + items_before = Item.objects.filter(creator__in=authors_without_report) + self.assertCountEqual(items_before, [self.i2, self.i3, self.i4]) + # Combining querysets doesn't mutate them. + all_authors | authors_with_report + all_authors & authors_with_report + + authors_without_report = all_authors.exclude(pk__in=authors_with_report) + items_after = Item.objects.filter(creator__in=authors_without_report) + + self.assertCountEqual(items_after, [self.i2, self.i3, self.i4]) + self.assertCountEqual(items_before, items_after) + class Queries2Tests(TestCase): @classmethod