Author: lukeplant
Date: 2011-05-05 13:26:26 -0700 (Thu, 05 May 2011)
New Revision: 16159

Modified:
   django/trunk/django/db/models/sql/query.py
   django/trunk/tests/regressiontests/null_fk/models.py
   django/trunk/tests/regressiontests/null_fk/tests.py
Log:
Fixed #15823 - incorrect join condition when combining Q objects

Thanks to dcwatson for the excellent report and patch.

Modified: django/trunk/django/db/models/sql/query.py
===================================================================
--- django/trunk/django/db/models/sql/query.py  2011-05-05 00:29:16 UTC (rev 
16158)
+++ django/trunk/django/db/models/sql/query.py  2011-05-05 20:26:26 UTC (rev 
16159)
@@ -457,7 +457,11 @@
                 # An unused alias.
                 continue
             promote = (rhs.alias_map[alias][JOIN_TYPE] == self.LOUTER)
-            new_alias = self.join(rhs.rev_join_map[alias],
+            lhs, table, lhs_col, col = rhs.rev_join_map[alias]
+            # If the left side of the join was already relabeled, use the
+            # updated alias.
+            lhs = change_map.get(lhs, lhs)
+            new_alias = self.join((lhs, table, lhs_col, col),
                     (conjunction and not first), used, promote, not 
conjunction)
             used.add(new_alias)
             change_map[alias] = new_alias

Modified: django/trunk/tests/regressiontests/null_fk/models.py
===================================================================
--- django/trunk/tests/regressiontests/null_fk/models.py        2011-05-05 
00:29:16 UTC (rev 16158)
+++ django/trunk/tests/regressiontests/null_fk/models.py        2011-05-05 
20:26:26 UTC (rev 16159)
@@ -31,3 +31,16 @@
 
     def __unicode__(self):
         return self.comment_text
+
+# Ticket 15823
+
+class Item(models.Model):
+    title = models.CharField(max_length=100)
+
+class PropertyValue(models.Model):
+    label = models.CharField(max_length=100)
+
+class Property(models.Model):
+    item = models.ForeignKey(Item, related_name='props')
+    key = models.CharField(max_length=100)
+    value = models.ForeignKey(PropertyValue, null=True)

Modified: django/trunk/tests/regressiontests/null_fk/tests.py
===================================================================
--- django/trunk/tests/regressiontests/null_fk/tests.py 2011-05-05 00:29:16 UTC 
(rev 16158)
+++ django/trunk/tests/regressiontests/null_fk/tests.py 2011-05-05 20:26:26 UTC 
(rev 16159)
@@ -1,4 +1,5 @@
 from django.test import TestCase
+from django.db.models import Q
 
 from regressiontests.null_fk.models import *
 
@@ -40,3 +41,25 @@
             ],
             transform = lambda c: (c.id, c.comment_text, repr(c.post))
         )
+
+    def test_combine_isnull(self):
+        item = Item.objects.create(title='Some Item')
+        pv = PropertyValue.objects.create(label='Some Value')
+        item.props.create(key='a', value=pv)
+        item.props.create(key='b') # value=NULL
+        q1 = Q(props__key='a', props__value=pv)
+        q2 = Q(props__key='b', props__value__isnull=True)
+
+        # Each of these individually should return the item.
+        self.assertEqual(Item.objects.get(q1), item)
+        self.assertEqual(Item.objects.get(q2), item)
+
+        # Logically, qs1 and qs2, and qs3 and qs4 should be the same.
+        qs1 = Item.objects.filter(q1) & Item.objects.filter(q2)
+        qs2 = Item.objects.filter(q2) & Item.objects.filter(q1)
+        qs3 = Item.objects.filter(q1) | Item.objects.filter(q2)
+        qs4 = Item.objects.filter(q2) | Item.objects.filter(q1)
+
+        # Regression test for #15823.
+        self.assertEqual(list(qs1), list(qs2))
+        self.assertEqual(list(qs3), list(qs4))

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to