Fixed #12823 -- Was already fixed in master, tests added
Also added a little improvement to sql/query.py to get rid of non-necessary IS NOT NULL check.
This commit is contained in:
parent
481f3f13b5
commit
06de130dae
|
@ -1204,7 +1204,8 @@ class Query(object):
|
||||||
|
|
||||||
if negate:
|
if negate:
|
||||||
self.promote_joins(join_list)
|
self.promote_joins(join_list)
|
||||||
if lookup_type != 'isnull' and (self.is_nullable(target) or len(join_list) > 1):
|
if (lookup_type != 'isnull' and (
|
||||||
|
self.is_nullable(target) or self.alias_map[join_list[-1]].join_type == self.LOUTER)):
|
||||||
# The condition added here will be SQL like this:
|
# The condition added here will be SQL like this:
|
||||||
# NOT (col IS NOT NULL), where the first NOT is added in
|
# NOT (col IS NOT NULL), where the first NOT is added in
|
||||||
# upper layers of code. The reason for addition is that if col
|
# upper layers of code. The reason for addition is that if col
|
||||||
|
@ -1447,7 +1448,7 @@ class Query(object):
|
||||||
# nothing
|
# nothing
|
||||||
if self.is_nullable(query.select[0].field):
|
if self.is_nullable(query.select[0].field):
|
||||||
alias, col = query.select[0].col
|
alias, col = query.select[0].col
|
||||||
query.where.add((Constraint(alias, col, None), 'isnull', False), AND)
|
query.where.add((Constraint(alias, col, query.select[0].field), 'isnull', False), AND)
|
||||||
|
|
||||||
# Still make sure that the trimmed parts in the inner query and
|
# Still make sure that the trimmed parts in the inner query and
|
||||||
# trimmed prefix are in sync. So, use the trimmed_joins to make sure
|
# trimmed prefix are in sync. So, use the trimmed_joins to make sure
|
||||||
|
|
|
@ -454,3 +454,19 @@ class Program(models.Model):
|
||||||
class Channel(models.Model):
|
class Channel(models.Model):
|
||||||
programs = models.ManyToManyField(Program)
|
programs = models.ManyToManyField(Program)
|
||||||
identifier = models.OneToOneField(Identifier)
|
identifier = models.OneToOneField(Identifier)
|
||||||
|
|
||||||
|
class Book(models.Model):
|
||||||
|
title = models.TextField()
|
||||||
|
chapter = models.ForeignKey('Chapter')
|
||||||
|
|
||||||
|
class Chapter(models.Model):
|
||||||
|
title = models.TextField()
|
||||||
|
paragraph = models.ForeignKey('Paragraph')
|
||||||
|
|
||||||
|
|
||||||
|
class Paragraph(models.Model):
|
||||||
|
text = models.TextField()
|
||||||
|
page = models.ManyToManyField('Page')
|
||||||
|
|
||||||
|
class Page(models.Model):
|
||||||
|
text = models.TextField()
|
||||||
|
|
|
@ -24,7 +24,8 @@ from .models import (Annotation, Article, Author, Celebrity, Child, Cover,
|
||||||
Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
|
Node, ObjectA, ObjectB, ObjectC, CategoryItem, SimpleCategory,
|
||||||
SpecialCategory, OneToOneCategory, NullableName, ProxyCategory,
|
SpecialCategory, OneToOneCategory, NullableName, ProxyCategory,
|
||||||
SingleObject, RelatedObject, ModelA, ModelD, Responsibility, Job,
|
SingleObject, RelatedObject, ModelA, ModelD, Responsibility, Job,
|
||||||
JobResponsibilities, BaseA, Identifier, Program, Channel)
|
JobResponsibilities, BaseA, Identifier, Program, Channel, Page, Paragraph,
|
||||||
|
Chapter, Book)
|
||||||
|
|
||||||
|
|
||||||
class BaseQuerysetTest(TestCase):
|
class BaseQuerysetTest(TestCase):
|
||||||
|
@ -2638,3 +2639,25 @@ class ManyToManyExcludeTest(TestCase):
|
||||||
Identifier.objects.exclude(program__channel=None).order_by('name'),
|
Identifier.objects.exclude(program__channel=None).order_by('name'),
|
||||||
['<Identifier: program>']
|
['<Identifier: program>']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_ticket_12823(self):
|
||||||
|
pg3 = Page.objects.create(text='pg3')
|
||||||
|
pg2 = Page.objects.create(text='pg2')
|
||||||
|
pg1 = Page.objects.create(text='pg1')
|
||||||
|
pa1 = Paragraph.objects.create(text='pa1')
|
||||||
|
pa1.page = [pg1, pg2]
|
||||||
|
pa2 = Paragraph.objects.create(text='pa2')
|
||||||
|
pa2.page = [pg2, pg3]
|
||||||
|
pa3 = Paragraph.objects.create(text='pa3')
|
||||||
|
ch1 = Chapter.objects.create(title='ch1', paragraph=pa1)
|
||||||
|
ch2 = Chapter.objects.create(title='ch2', paragraph=pa2)
|
||||||
|
ch3 = Chapter.objects.create(title='ch3', paragraph=pa3)
|
||||||
|
b1 = Book.objects.create(title='b1', chapter=ch1)
|
||||||
|
b2 = Book.objects.create(title='b2', chapter=ch2)
|
||||||
|
b3 = Book.objects.create(title='b3', chapter=ch3)
|
||||||
|
q = Book.objects.exclude(chapter__paragraph__page__text='pg1')
|
||||||
|
self.assertNotIn('IS NOT NULL', str(q.query))
|
||||||
|
self.assertEqual(len(q), 2)
|
||||||
|
self.assertNotIn(b1, q)
|
||||||
|
self.assertIn(b2, q)
|
||||||
|
self.assertIn(b3, q)
|
||||||
|
|
Loading…
Reference in New Issue