Commit d467e117 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen
Browse files

Fixed #20507 -- SubqueryConstraint alias relabeling

The SubqueryConstraint defined relabeled_clone(), but that was never
called. Instead there is now clone() and relabel_aliases() methods for
SubqueryConstraint.

A related problem was that SubqueryConstraint didn't correctly use
quote_name_unless_alias() of the outer query. This resulted in failures
when running under PostgreSQL.
parent ae71e313
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -786,8 +786,7 @@ class SQLCompiler(object):
            return list(result)
        return result

    def as_subquery_condition(self, alias, columns):
        qn = self.quote_name_unless_alias
    def as_subquery_condition(self, alias, columns, qn):
        qn2 = self.connection.ops.quote_name
        if len(columns) == 1:
            sql, params = self.as_sql()
+7 −4
Original line number Diff line number Diff line
@@ -408,9 +408,12 @@ class SubqueryConstraint(object):
            query.clear_ordering(True)

        query_compiler = query.get_compiler(connection=connection)
        return query_compiler.as_subquery_condition(self.alias, self.columns)
        return query_compiler.as_subquery_condition(self.alias, self.columns, qn)

    def relabeled_clone(self, relabels):
    def relabel_aliases(self, change_map):
        self.alias = change_map.get(self.alias, self.alias)

    def clone(self):
        return self.__class__(
            relabels.get(self.alias, self.alias),
            self.columns, self.query_object)
            self.alias, self.columns, self.targets,
            self.query_object)
+15 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ from django.utils import unittest
from django.utils.datastructures import SortedDict

from .models import (Annotation, Article, Author, Celebrity, Child, Cover,
    Detail, DumbCategory, ExtraInfo, Fan, Item, LeafA, LoopX, LoopZ,
    Detail, DumbCategory, ExtraInfo, Fan, Item, LeafA, Join, LeafB, LoopX, LoopZ,
    ManagedModel, Member, NamedCategory, Note, Number, Plaything, PointerA,
    Ranking, Related, Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten,
    Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
@@ -2827,3 +2827,17 @@ class ValuesSubqueryTests(TestCase):
        self.assertQuerysetEqual(
            Order.objects.filter(items__in=OrderItem.objects.values_list('status')),
            [o1.pk], lambda x: x.pk)

class DoubleInSubqueryTests(TestCase):
    def test_double_subquery_in(self):
        lfa1 = LeafA.objects.create(data='foo')
        lfa2 = LeafA.objects.create(data='bar')
        lfb1 = LeafB.objects.create(data='lfb1')
        lfb2 = LeafB.objects.create(data='lfb2')
        Join.objects.create(a=lfa1, b=lfb1)
        Join.objects.create(a=lfa2, b=lfb2)
        leaf_as = LeafA.objects.filter(data='foo').values_list('pk', flat=True)
        joins = Join.objects.filter(a__in=leaf_as).values_list('b__id', flat=True)
        qs = LeafB.objects.filter(pk__in=joins)
        self.assertQuerysetEqual(
            qs, [lfb1], lambda x: x)