[1.5.x] Fixed #19672 -- Error in negated Q() filtering
There was a variable overwrite error in negated join filtering. This happened when add_filter() was adding the IS NULL condition to the WHERE clause. This is not a backport from master as there have been some other refactorings which made this patch irrelevant. The patch is from Ian Kelly.
This commit is contained in:
parent
8d4342f2c9
commit
8ad436636f
|
@ -1193,15 +1193,15 @@ class Query(object):
|
||||||
self.promote_joins(join_list)
|
self.promote_joins(join_list)
|
||||||
if lookup_type != 'isnull':
|
if lookup_type != 'isnull':
|
||||||
if len(join_list) > 1:
|
if len(join_list) > 1:
|
||||||
for alias in join_list:
|
for j_alias in join_list:
|
||||||
if self.alias_map[alias].join_type == self.LOUTER:
|
if self.alias_map[j_alias].join_type == self.LOUTER:
|
||||||
j_col = self.alias_map[alias].rhs_join_col
|
j_col = self.alias_map[j_alias].rhs_join_col
|
||||||
# The join promotion logic should never produce
|
# The join promotion logic should never produce
|
||||||
# a LOUTER join for the base join - assert that.
|
# a LOUTER join for the base join - assert that.
|
||||||
assert j_col is not None
|
assert j_col is not None
|
||||||
entry = self.where_class()
|
entry = self.where_class()
|
||||||
entry.add(
|
entry.add(
|
||||||
(Constraint(alias, j_col, None), 'isnull', True),
|
(Constraint(j_alias, j_col, None), 'isnull', True),
|
||||||
AND
|
AND
|
||||||
)
|
)
|
||||||
entry.negate()
|
entry.negate()
|
||||||
|
|
|
@ -64,6 +64,7 @@ class Annotation(models.Model):
|
||||||
class ExtraInfo(models.Model):
|
class ExtraInfo(models.Model):
|
||||||
info = models.CharField(max_length=100)
|
info = models.CharField(max_length=100)
|
||||||
note = models.ForeignKey(Note)
|
note = models.ForeignKey(Note)
|
||||||
|
value = models.IntegerField(null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['info']
|
ordering = ['info']
|
||||||
|
|
|
@ -51,8 +51,8 @@ class Queries1Tests(BaseQuerysetTest):
|
||||||
|
|
||||||
# Create these out of order so that sorting by 'id' will be different to sorting
|
# Create these out of order so that sorting by 'id' will be different to sorting
|
||||||
# by 'info'. Helps detect some problems later.
|
# by 'info'. Helps detect some problems later.
|
||||||
self.e2 = ExtraInfo.objects.create(info='e2', note=n2)
|
self.e2 = ExtraInfo.objects.create(info='e2', note=n2, value=41)
|
||||||
e1 = ExtraInfo.objects.create(info='e1', note=self.n1)
|
e1 = ExtraInfo.objects.create(info='e1', note=self.n1, value=42)
|
||||||
|
|
||||||
self.a1 = Author.objects.create(name='a1', num=1001, extra=e1)
|
self.a1 = Author.objects.create(name='a1', num=1001, extra=e1)
|
||||||
self.a2 = Author.objects.create(name='a2', num=2002, extra=e1)
|
self.a2 = Author.objects.create(name='a2', num=2002, extra=e1)
|
||||||
|
@ -880,6 +880,14 @@ class Queries1Tests(BaseQuerysetTest):
|
||||||
Item.objects.filter(Q(tags__name__in=['t4', 't3'])),
|
Item.objects.filter(Q(tags__name__in=['t4', 't3'])),
|
||||||
[repr(i) for i in Item.objects.filter(~~Q(tags__name__in=['t4', 't3']))])
|
[repr(i) for i in Item.objects.filter(~~Q(tags__name__in=['t4', 't3']))])
|
||||||
|
|
||||||
|
def test_ticket19672(self):
|
||||||
|
self.assertQuerysetEqual(
|
||||||
|
Report.objects.filter(Q(creator__isnull=False) &
|
||||||
|
~Q(creator__extra__value=41)),
|
||||||
|
['<Report: r1>']
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Queries2Tests(TestCase):
|
class Queries2Tests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
Number.objects.create(num=4)
|
Number.objects.create(num=4)
|
||||||
|
|
Loading…
Reference in New Issue