Fixed #7872 -- Fixed a missed case of promoting table joins when using
disjunctive filters. Thanks to Michael Radziej for the failing test case. problem. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8107 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4774c8d673
commit
4fee39c63c
|
@ -1089,20 +1089,23 @@ class Query(object):
|
||||||
join_it = iter(join_list)
|
join_it = iter(join_list)
|
||||||
table_it = iter(self.tables)
|
table_it = iter(self.tables)
|
||||||
join_it.next(), table_it.next()
|
join_it.next(), table_it.next()
|
||||||
|
table_promote = False
|
||||||
for join in join_it:
|
for join in join_it:
|
||||||
table = table_it.next()
|
table = table_it.next()
|
||||||
if join == table and self.alias_refcount[join] > 1:
|
if join == table and self.alias_refcount[join] > 1:
|
||||||
continue
|
continue
|
||||||
self.promote_alias(join)
|
join_promote = self.promote_alias(join)
|
||||||
if table != join:
|
if table != join:
|
||||||
self.promote_alias(table)
|
table_promote = self.promote_alias(table)
|
||||||
break
|
break
|
||||||
for join in join_it:
|
for join in join_it:
|
||||||
self.promote_alias(join)
|
if self.promote_alias(join, join_promote):
|
||||||
|
join_promote = True
|
||||||
for table in table_it:
|
for table in table_it:
|
||||||
# Some of these will have been promoted from the join_list, but
|
# Some of these will have been promoted from the join_list, but
|
||||||
# that's harmless.
|
# that's harmless.
|
||||||
self.promote_alias(table)
|
if self.promote_alias(table, table_promote):
|
||||||
|
table_promote = True
|
||||||
|
|
||||||
self.where.add((alias, col, field, lookup_type, value), connector)
|
self.where.add((alias, col, field, lookup_type, value), connector)
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,19 @@ class TvChef(Celebrity):
|
||||||
class Fan(models.Model):
|
class Fan(models.Model):
|
||||||
fan_of = models.ForeignKey(Celebrity)
|
fan_of = models.ForeignKey(Celebrity)
|
||||||
|
|
||||||
|
# Multiple foreign keys
|
||||||
|
class LeafA(models.Model):
|
||||||
|
data = models.CharField(max_length=10)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
class LeafB(models.Model):
|
||||||
|
data = models.CharField(max_length=10)
|
||||||
|
|
||||||
|
class Join(models.Model):
|
||||||
|
a = models.ForeignKey(LeafA)
|
||||||
|
b = models.ForeignKey(LeafB)
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
>>> t1 = Tag.objects.create(name='t1')
|
>>> t1 = Tag.objects.create(name='t1')
|
||||||
|
@ -334,6 +347,16 @@ constraints.
|
||||||
>>> Number.objects.filter(Q(num__gt=7) & Q(num__lt=12) | Q(num__lt=4))
|
>>> Number.objects.filter(Q(num__gt=7) & Q(num__lt=12) | Q(num__lt=4))
|
||||||
[<Number: 8>]
|
[<Number: 8>]
|
||||||
|
|
||||||
|
Bug #7872
|
||||||
|
Another variation on the disjunctive filtering theme.
|
||||||
|
|
||||||
|
# For the purposes of this regression test, it's important that there is no
|
||||||
|
# Join object releated to the LeafA we create.
|
||||||
|
>>> LeafA.objects.create(data='first')
|
||||||
|
<LeafA: first>
|
||||||
|
>>> LeafA.objects.filter(Q(data='first')|Q(join__b__data='second'))
|
||||||
|
[<LeafA: first>]
|
||||||
|
|
||||||
Bug #6074
|
Bug #6074
|
||||||
Merging two empty result sets shouldn't leave a queryset with no constraints
|
Merging two empty result sets shouldn't leave a queryset with no constraints
|
||||||
(which would match everything).
|
(which would match everything).
|
||||||
|
@ -430,9 +453,9 @@ Bug #5324, #6704
|
||||||
>>> query.LOUTER not in [x[2] for x in query.alias_map.values()]
|
>>> query.LOUTER not in [x[2] for x in query.alias_map.values()]
|
||||||
True
|
True
|
||||||
|
|
||||||
Similarly, when one of the joins cannot possibly, ever, involve NULL values (Author -> ExtraInfo, in the following), it should never be promoted to a left outer join. So hte following query should only involve one "left outer" join (Author -> Item is 0-to-many).
|
Similarly, when one of the joins cannot possibly, ever, involve NULL values (Author -> ExtraInfo, in the following), it should never be promoted to a left outer join. So the following query should only involve one "left outer" join (Author -> Item is 0-to-many).
|
||||||
>>> qs = Author.objects.filter(id=a1.id).filter(Q(extra__note=n1)|Q(item__note=n3))
|
>>> qs = Author.objects.filter(id=a1.id).filter(Q(extra__note=n1)|Q(item__note=n3))
|
||||||
>>> len([x[2] for x in qs.query.alias_map.values() if x[2] == query.LOUTER])
|
>>> len([x[2] for x in qs.query.alias_map.values() if x[2] == query.LOUTER and qs.query.alias_refcount[x[1]]])
|
||||||
1
|
1
|
||||||
|
|
||||||
The previous changes shouldn't affect nullable foreign key joins.
|
The previous changes shouldn't affect nullable foreign key joins.
|
||||||
|
|
Loading…
Reference in New Issue