Fixed #14423 -- corrected incorrect SQL being generated when a nullable, inherited field was used in an exclude. Thanks to PhiR_42 for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14600 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Alex Gaynor 2010-11-17 16:46:50 +00:00
parent c0248f6f07
commit 0eb31d3dc9
2 changed files with 34 additions and 10 deletions

View File

@ -921,8 +921,7 @@ class Query(object):
""" """
opts = model._meta opts = model._meta
field_list = aggregate.lookup.split(LOOKUP_SEP) field_list = aggregate.lookup.split(LOOKUP_SEP)
if (len(field_list) == 1 and if len(field_list) == 1 and aggregate.lookup in self.aggregates:
aggregate.lookup in self.aggregates.keys()):
# Aggregate is over an annotation # Aggregate is over an annotation
field_name = field_list[0] field_name = field_list[0]
col = field_name col = field_name
@ -1090,11 +1089,14 @@ class Query(object):
if self.alias_map[alias][JOIN_TYPE] == self.LOUTER: if self.alias_map[alias][JOIN_TYPE] == self.LOUTER:
j_col = self.alias_map[alias][RHS_JOIN_COL] j_col = self.alias_map[alias][RHS_JOIN_COL]
entry = self.where_class() entry = self.where_class()
entry.add((Constraint(alias, j_col, None), 'isnull', True), AND) entry.add(
(Constraint(alias, j_col, None), 'isnull', True),
AND
)
entry.negate() entry.negate()
self.where.add(entry, AND) self.where.add(entry, AND)
break break
elif not (lookup_type == 'in' if not (lookup_type == 'in'
and not hasattr(value, 'as_sql') and not hasattr(value, 'as_sql')
and not hasattr(value, '_as_sql') and not hasattr(value, '_as_sql')
and not value) and field.null: and not value) and field.null:

View File

@ -3,12 +3,16 @@ Regression tests for Model inheritance behaviour.
""" """
import datetime import datetime
from operator import attrgetter
from django.test import TestCase from django.test import TestCase
from regressiontests.model_inheritance_regress.models import (
Place, Restaurant, ItalianRestaurant, ParkingLot, ParkingLot2, from models import (Place, Restaurant, ItalianRestaurant, ParkingLot,
ParkingLot3, Supplier, Wholesaler, Child, SelfRefChild, ArticleWithAuthor, ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent,
M2MChild, QualityControl, DerivedM, Person, BirthdayParty, BachelorParty, SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM,
MessyBachelorParty, InternalCertificationAudit) Person, BirthdayParty, BachelorParty, MessyBachelorParty,
InternalCertificationAudit)
class ModelInheritanceTest(TestCase): class ModelInheritanceTest(TestCase):
def test_model_inheritance(self): def test_model_inheritance(self):
@ -355,7 +359,10 @@ class ModelInheritanceTest(TestCase):
self.assertEqual(parties, [bachelor, messy_parent]) self.assertEqual(parties, [bachelor, messy_parent])
def test_11369(self): def test_11369(self):
"""verbose_name_plural correctly inherited from ABC if inheritance chain includes an abstract model.""" """
verbose_name_plural correctly inherited from ABC if inheritance chain
includes an abstract model.
"""
# Regression test for #11369: verbose_name_plural should be inherited # Regression test for #11369: verbose_name_plural should be inherited
# from an ABC even when there are one or more intermediate # from an ABC even when there are one or more intermediate
# abstract models in the inheritance chain, for consistency with # abstract models in the inheritance chain, for consistency with
@ -364,3 +371,18 @@ class ModelInheritanceTest(TestCase):
InternalCertificationAudit._meta.verbose_name_plural, InternalCertificationAudit._meta.verbose_name_plural,
u'Audits' u'Audits'
) )
def test_inherited_nullable_exclude(self):
obj = SelfRefChild.objects.create(child_data=37, parent_data=42)
self.assertQuerysetEqual(
SelfRefParent.objects.exclude(self_data=72), [
obj.pk
],
attrgetter("pk")
)
self.assertQuerysetEqual(
SelfRefChild.objects.exclude(self_data=72), [
obj.pk
],
attrgetter("pk")
)