summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/models/sql/query.py6
-rw-r--r--tests/regressiontests/null_fk/models.py13
-rw-r--r--tests/regressiontests/null_fk/tests.py23
3 files changed, 41 insertions, 1 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index c29673ecdd..9a5666b143 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -457,7 +457,11 @@ class Query(object):
# 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
diff --git a/tests/regressiontests/null_fk/models.py b/tests/regressiontests/null_fk/models.py
index 3cce319496..d96118c5c1 100644
--- a/tests/regressiontests/null_fk/models.py
+++ b/tests/regressiontests/null_fk/models.py
@@ -31,3 +31,16 @@ class Comment(models.Model):
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)
diff --git a/tests/regressiontests/null_fk/tests.py b/tests/regressiontests/null_fk/tests.py
index ab4bd522a0..2825cc9c8b 100644
--- a/tests/regressiontests/null_fk/tests.py
+++ b/tests/regressiontests/null_fk/tests.py
@@ -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 @@ class NullFkTests(TestCase):
],
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))