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:
|
||||
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:
|
||||
# NOT (col IS NOT NULL), where the first NOT is added in
|
||||
# upper layers of code. The reason for addition is that if col
|
||||
|
@ -1447,7 +1448,7 @@ class Query(object):
|
|||
# nothing
|
||||
if self.is_nullable(query.select[0].field):
|
||||
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
|
||||
# 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):
|
||||
programs = models.ManyToManyField(Program)
|
||||
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,
|
||||
SpecialCategory, OneToOneCategory, NullableName, ProxyCategory,
|
||||
SingleObject, RelatedObject, ModelA, ModelD, Responsibility, Job,
|
||||
JobResponsibilities, BaseA, Identifier, Program, Channel)
|
||||
JobResponsibilities, BaseA, Identifier, Program, Channel, Page, Paragraph,
|
||||
Chapter, Book)
|
||||
|
||||
|
||||
class BaseQuerysetTest(TestCase):
|
||||
|
@ -2638,3 +2639,25 @@ class ManyToManyExcludeTest(TestCase):
|
|||
Identifier.objects.exclude(program__channel=None).order_by('name'),
|
||||
['<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