From 0eb31d3dc9435b18680f7a41bc9067685beb8344 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 17 Nov 2010 16:46:50 +0000 Subject: [PATCH] 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 --- django/db/models/sql/query.py | 10 +++--- .../model_inheritance_regress/tests.py | 34 +++++++++++++++---- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index c0449e7047..b8638fe909 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -921,8 +921,7 @@ class Query(object): """ opts = model._meta field_list = aggregate.lookup.split(LOOKUP_SEP) - if (len(field_list) == 1 and - aggregate.lookup in self.aggregates.keys()): + if len(field_list) == 1 and aggregate.lookup in self.aggregates: # Aggregate is over an annotation field_name = field_list[0] col = field_name @@ -1090,11 +1089,14 @@ class Query(object): if self.alias_map[alias][JOIN_TYPE] == self.LOUTER: j_col = self.alias_map[alias][RHS_JOIN_COL] 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() self.where.add(entry, AND) 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 value) and field.null: diff --git a/tests/regressiontests/model_inheritance_regress/tests.py b/tests/regressiontests/model_inheritance_regress/tests.py index 569cef5845..dac2cb5de5 100644 --- a/tests/regressiontests/model_inheritance_regress/tests.py +++ b/tests/regressiontests/model_inheritance_regress/tests.py @@ -3,12 +3,16 @@ Regression tests for Model inheritance behaviour. """ import datetime +from operator import attrgetter + from django.test import TestCase -from regressiontests.model_inheritance_regress.models import ( - Place, Restaurant, ItalianRestaurant, ParkingLot, ParkingLot2, - ParkingLot3, Supplier, Wholesaler, Child, SelfRefChild, ArticleWithAuthor, - M2MChild, QualityControl, DerivedM, Person, BirthdayParty, BachelorParty, - MessyBachelorParty, InternalCertificationAudit) + +from models import (Place, Restaurant, ItalianRestaurant, ParkingLot, + ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent, + SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM, + Person, BirthdayParty, BachelorParty, MessyBachelorParty, + InternalCertificationAudit) + class ModelInheritanceTest(TestCase): def test_model_inheritance(self): @@ -355,7 +359,10 @@ class ModelInheritanceTest(TestCase): self.assertEqual(parties, [bachelor, messy_parent]) 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 # from an ABC even when there are one or more intermediate # abstract models in the inheritance chain, for consistency with @@ -364,3 +371,18 @@ class ModelInheritanceTest(TestCase): InternalCertificationAudit._meta.verbose_name_plural, 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") + )