1
0
mirror of https://github.com/django/django.git synced 2025-06-05 03:29:12 +00:00

Fixed #35744 -- Relabelled external aliases of combined queries.

Just like normal queries, combined queries' outer references might fully
resolve before their reference is assigned its final alias.

Refs #29338.

Thanks Antony_K for the report and example, and thanks Mariusz Felisiak
for the review.
This commit is contained in:
Simon Charette 2024-10-14 19:21:48 -04:00 committed by Ryan Cheley
parent 5afaaf2c57
commit 6c7733842e
2 changed files with 41 additions and 1 deletions

View File

@ -1021,11 +1021,21 @@ class Query(BaseExpression):
if alias == old_alias: if alias == old_alias:
table_aliases[pos] = new_alias table_aliases[pos] = new_alias
break break
# 3. Rename the direct external aliases and the ones of combined
# queries (union, intersection, difference).
self.external_aliases = { self.external_aliases = {
# Table is aliased or it's being changed and thus is aliased. # Table is aliased or it's being changed and thus is aliased.
change_map.get(alias, alias): (aliased or alias in change_map) change_map.get(alias, alias): (aliased or alias in change_map)
for alias, aliased in self.external_aliases.items() for alias, aliased in self.external_aliases.items()
} }
for combined_query in self.combined_queries:
external_change_map = {
alias: aliased
for alias, aliased in change_map.items()
if alias in combined_query.external_aliases
}
combined_query.change_aliases(external_change_map)
def bump_prefix(self, other_query, exclude=None): def bump_prefix(self, other_query, exclude=None):
""" """

View File

@ -14,7 +14,16 @@ from django.db.models.functions import Mod
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
from django.test.utils import CaptureQueriesContext from django.test.utils import CaptureQueriesContext
from .models import Author, Celebrity, ExtraInfo, Number, ReservedName from .models import (
Annotation,
Author,
Celebrity,
ExtraInfo,
Note,
Number,
ReservedName,
Tag,
)
@skipUnlessDBFeature("supports_select_union") @skipUnlessDBFeature("supports_select_union")
@ -450,6 +459,27 @@ class QuerySetSetOperationTests(TestCase):
[8, 1], [8, 1],
) )
@skipUnlessDBFeature("supports_select_intersection")
def test_intersection_in_nested_subquery(self):
tag = Tag.objects.create(name="tag")
note = Note.objects.create(tag=tag)
annotation = Annotation.objects.create(tag=tag)
tags = Tag.objects.order_by()
tags = tags.filter(id=OuterRef("tag_id")).intersection(
tags.filter(id=OuterRef(OuterRef("tag_id")))
)
qs = Note.objects.filter(
Exists(
Annotation.objects.filter(
Exists(tags),
notes__in=OuterRef("pk"),
)
)
)
self.assertIsNone(qs.first())
annotation.notes.add(note)
self.assertEqual(qs.first(), note)
def test_union_in_subquery_related_outerref(self): def test_union_in_subquery_related_outerref(self):
e1 = ExtraInfo.objects.create(value=7, info="e3") e1 = ExtraInfo.objects.create(value=7, info="e3")
e2 = ExtraInfo.objects.create(value=5, info="e2") e2 = ExtraInfo.objects.create(value=5, info="e2")