Django

Code

Changeset 8107

Show
Ignore:
Timestamp:
07/27/08 13:16:17 (4 months ago)
Author:
mtredinnick
Message:

Fixed #7872 -- Fixed a missed case of promoting table joins when using
disjunctive filters. Thanks to Michael Radziej for the failing test case.
problem.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/models/sql/query.py

    r8053 r8107  
    10901090            table_it = iter(self.tables) 
    10911091            join_it.next(), table_it.next() 
     1092            table_promote = False 
    10921093            for join in join_it: 
    10931094                table = table_it.next() 
    10941095                if join == table and self.alias_refcount[join] > 1: 
    10951096                    continue 
    1096                 self.promote_alias(join) 
     1097                join_promote = self.promote_alias(join) 
    10971098                if table != join: 
    1098                     self.promote_alias(table) 
     1099                    table_promote = self.promote_alias(table) 
    10991100                break 
    11001101            for join in join_it: 
    1101                 self.promote_alias(join) 
     1102                if self.promote_alias(join, join_promote): 
     1103                    join_promote = True 
    11021104            for table in table_it: 
    11031105                # Some of these will have been promoted from the join_list, but 
    11041106                # that's harmless. 
    1105                 self.promote_alias(table) 
     1107                if self.promote_alias(table, table_promote): 
     1108                    table_promote = True 
    11061109 
    11071110        self.where.add((alias, col, field, lookup_type, value), connector) 
  • django/trunk/tests/regressiontests/queries/models.py

    r8100 r8107  
    204204    fan_of = models.ForeignKey(Celebrity) 
    205205 
     206# Multiple foreign keys 
     207class LeafA(models.Model): 
     208    data = models.CharField(max_length=10) 
     209 
     210    def __unicode__(self): 
     211        return self.data 
     212 
     213class LeafB(models.Model): 
     214    data = models.CharField(max_length=10) 
     215 
     216class Join(models.Model): 
     217    a = models.ForeignKey(LeafA) 
     218    b = models.ForeignKey(LeafB) 
    206219 
    207220__test__ = {'API_TESTS':""" 
     
    335348[<Number: 8>] 
    336349 
     350Bug #7872 
     351Another variation on the disjunctive filtering theme. 
     352 
     353# For the purposes of this regression test, it's important that there is no 
     354# Join object releated to the LeafA we create. 
     355>>> LeafA.objects.create(data='first') 
     356<LeafA: first> 
     357>>> LeafA.objects.filter(Q(data='first')|Q(join__b__data='second')) 
     358[<LeafA: first>] 
     359 
    337360Bug #6074 
    338361Merging two empty result sets shouldn't leave a queryset with no constraints 
     
    431454True 
    432455 
    433 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). 
     456Similarly, 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). 
    434457>>> qs = Author.objects.filter(id=a1.id).filter(Q(extra__note=n1)|Q(item__note=n3)) 
    435 >>> len([x[2] for x in qs.query.alias_map.values() if x[2] == query.LOUTER]) 
     458>>> len([x[2] for x in qs.query.alias_map.values() if x[2] == query.LOUTER and qs.query.alias_refcount[x[1]]]) 
    4364591 
    437460