1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +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 GitHub
parent 97c05a64ca
commit 53ea4cce2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 1 deletions

View File

@ -1021,11 +1021,21 @@ class Query(BaseExpression):
if alias == old_alias:
table_aliases[pos] = new_alias
break
# 3. Rename the direct external aliases and the ones of combined
# queries (union, intersection, difference).
self.external_aliases = {
# Table is aliased or it's being changed and thus is aliased.
change_map.get(alias, alias): (aliased or alias in change_map)
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):
"""

View File

@ -14,7 +14,16 @@ from django.db.models.functions import Mod
from django.test import TestCase, skipIfDBFeature, skipUnlessDBFeature
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")
@ -450,6 +459,27 @@ class QuerySetSetOperationTests(TestCase):
[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):
e1 = ExtraInfo.objects.create(value=7, info="e3")
e2 = ExtraInfo.objects.create(value=5, info="e2")