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:
parent
97c05a64ca
commit
53ea4cce2f
@ -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):
|
||||
"""
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user