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.
This commit is contained in:
Anssi Kääriäinen 2013-05-27 11:29:43 +03:00
parent ae71e3134e
commit d467e11785
3 changed files with 23 additions and 7 deletions

View File

@ -786,8 +786,7 @@ class SQLCompiler(object):
return list(result) return list(result)
return result return result
def as_subquery_condition(self, alias, columns): def as_subquery_condition(self, alias, columns, qn):
qn = self.quote_name_unless_alias
qn2 = self.connection.ops.quote_name qn2 = self.connection.ops.quote_name
if len(columns) == 1: if len(columns) == 1:
sql, params = self.as_sql() sql, params = self.as_sql()

View File

@ -408,9 +408,12 @@ class SubqueryConstraint(object):
query.clear_ordering(True) query.clear_ordering(True)
query_compiler = query.get_compiler(connection=connection) 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__( return self.__class__(
relabels.get(self.alias, self.alias), self.alias, self.columns, self.targets,
self.columns, self.query_object) self.query_object)

View File

@ -17,7 +17,7 @@ from django.utils import unittest
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from .models import (Annotation, Article, Author, Celebrity, Child, Cover, 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, ManagedModel, Member, NamedCategory, Note, Number, Plaything, PointerA,
Ranking, Related, Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Ranking, Related, Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten,
Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory, Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
@ -2827,3 +2827,17 @@ class ValuesSubqueryTests(TestCase):
self.assertQuerysetEqual( self.assertQuerysetEqual(
Order.objects.filter(items__in=OrderItem.objects.values_list('status')), Order.objects.filter(items__in=OrderItem.objects.values_list('status')),
[o1.pk], lambda x: x.pk) [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)