Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit 4fee39c63ce781e7af827feeabcc911080d81edc 1 parent 4774c8d
Malcolm Tredinnick authored July 27, 2008
11  django/db/models/sql/query.py
@@ -1089,20 +1089,23 @@ def add_filter(self, filter_expr, connector=AND, negate=False, trim=False,
1089 1089
             join_it = iter(join_list)
1090 1090
             table_it = iter(self.tables)
1091 1091
             join_it.next(), table_it.next()
  1092
+            table_promote = False
1092 1093
             for join in join_it:
1093 1094
                 table = table_it.next()
1094 1095
                 if join == table and self.alias_refcount[join] > 1:
1095 1096
                     continue
1096  
-                self.promote_alias(join)
  1097
+                join_promote = self.promote_alias(join)
1097 1098
                 if table != join:
1098  
-                    self.promote_alias(table)
  1099
+                    table_promote = self.promote_alias(table)
1099 1100
                 break
1100 1101
             for join in join_it:
1101  
-                self.promote_alias(join)
  1102
+                if self.promote_alias(join, join_promote):
  1103
+                    join_promote = True
1102 1104
             for table in table_it:
1103 1105
                 # Some of these will have been promoted from the join_list, but
1104 1106
                 # that's harmless.
1105  
-                self.promote_alias(table)
  1107
+                if self.promote_alias(table, table_promote):
  1108
+                    table_promote = True
1106 1109
 
1107 1110
         self.where.add((alias, col, field, lookup_type, value), connector)
1108 1111
 
27  tests/regressiontests/queries/models.py
@@ -203,6 +203,19 @@ class TvChef(Celebrity):
203 203
 class Fan(models.Model):
204 204
     fan_of = models.ForeignKey(Celebrity)
205 205
 
  206
+# Multiple foreign keys
  207
+class LeafA(models.Model):
  208
+    data = models.CharField(max_length=10)
  209
+
  210
+    def __unicode__(self):
  211
+        return self.data
  212
+
  213
+class LeafB(models.Model):
  214
+    data = models.CharField(max_length=10)
  215
+
  216
+class Join(models.Model):
  217
+    a = models.ForeignKey(LeafA)
  218
+    b = models.ForeignKey(LeafB)
206 219
 
207 220
 __test__ = {'API_TESTS':"""
208 221
 >>> t1 = Tag.objects.create(name='t1')
@@ -334,6 +347,16 @@ class Fan(models.Model):
334 347
 >>> Number.objects.filter(Q(num__gt=7) & Q(num__lt=12) | Q(num__lt=4))
335 348
 [<Number: 8>]
336 349
 
  350
+Bug #7872
  351
+Another 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
+
337 360
 Bug #6074
338 361
 Merging two empty result sets shouldn't leave a queryset with no constraints
339 362
 (which would match everything).
@@ -430,9 +453,9 @@ class Fan(models.Model):
430 453
 >>> query.LOUTER not in [x[2] for x in query.alias_map.values()]
431 454
 True
432 455
 
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).
  456
+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).
434 457
 >>> 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]]])
436 459
 1
437 460
 
438 461
 The previous changes shouldn't affect nullable foreign key joins.

0 notes on commit 4fee39c

Please sign in to comment.
Something went wrong with that request. Please try again.