Ticket #15316: ticket15316.2.diff

File ticket15316.2.diff, 10.6 KB (added by ethlinn, 4 years ago)

Changed patch --- in case isnull=False trim_join() skip trimming join_list

  • AUTHORS

     
    448448    schwank@gmail.com
    449449    scott@staplefish.com
    450450    Ilya Semenov <semenov@inetss.com>
     451    Aleksandra Sendecka <asendecka@hauru.eu>
    451452    serbaut@gmail.com
    452453    John Shaffer <jshaffer2112@gmail.com>
    453454    Pete Shinners <pete@shinners.org>
  • django/db/models/sql/query.py

     
    10981098
    10991099        # Process the join list to see if we can remove any inner joins from
    11001100        # the far end (fewer tables in a query is better).
    1101         col, alias, join_list = self.trim_joins(target, join_list, last, trim)
     1101        isnull_skip = lookup_type == 'isnull' and value is False
     1102        col, alias, join_list = self.trim_joins(target, join_list, last, trim, isnull_skip)
    11021103        if connector == OR:
    11031104            # Some joins may need to be promoted when adding a new filter to a
    11041105            # disjunction. We walk the list of new joins and where it diverges
     
    14351436
    14361437        return field, target, opts, joins, last, extra_filters
    14371438
    1438     def trim_joins(self, target, join_list, last, trim):
     1439    def trim_joins(self, target, join_list, last, trim, isnull_skip = False):
    14391440        """
    14401441        Sometimes joins at the end of a multi-table sequence can be trimmed. If
    14411442        the final join is against the same column as we are comparing against,
     
    14761477        alias = join_list[-1]
    14771478        while final > 1:
    14781479            join = self.alias_map[alias]
    1479             if col != join[RHS_JOIN_COL] or join[JOIN_TYPE] != self.INNER:
     1480            if col != join[RHS_JOIN_COL] or join[JOIN_TYPE] != self.INNER or isnull_skip:
    14801481                break
    14811482            self.unref_alias(alias)
    14821483            alias = join[LHS_ALIAS]
  • tests/regressiontests/queries/tests.py

     
    1515    DumbCategory, ExtraInfo, Fan, Item, LeafA, LoopX, LoopZ, ManagedModel,
    1616    Member, NamedCategory, Note, Number, Plaything, PointerA, Ranking, Related,
    1717    Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node, ObjectA, ObjectB,
    18     ObjectC)
     18    ObjectC, CategoryItem, SimpleCategory, SpecialCategory, OneToOneCategory)
    1919
    2020
    2121class BaseQuerysetTest(TestCase):
     
    10431043            []
    10441044        )
    10451045
     1046    def test_ticket15316_filter_false(self):
     1047        c1 = SimpleCategory(name="category1")
     1048        c2 = SpecialCategory(name="named category1", special_name="special1")
     1049        c3 = SpecialCategory(name="named category2", special_name="special2")
     1050        c1.save()
     1051        c2.save()
     1052        c3.save()
    10461053
     1054        ci1 = CategoryItem(category=c1)
     1055        ci2 = CategoryItem(category=c2)
     1056        ci3 = CategoryItem(category=c3)
     1057        ci1.save()
     1058        ci2.save()
     1059        ci3.save()
     1060
     1061        self.assertEqual(
     1062        CategoryItem.objects.filter(category__specialcategory__isnull=False).count(),
     1063            2
     1064        )
     1065        self.assertItemsEqual(
     1066            CategoryItem.objects.filter(category__specialcategory__isnull=False),
     1067            CategoryItem.objects.filter(pk__in=[ci2.pk, ci3.pk])
     1068        )
     1069
     1070    def test_ticket15316_exclude_false(self):
     1071        c1 = SimpleCategory(name="category1")
     1072        c2 = SpecialCategory(name="named category1", special_name="special1")
     1073        c3 = SpecialCategory(name="named category2", special_name="special2")
     1074        c1.save()
     1075        c2.save()
     1076        c3.save()
     1077
     1078        ci1 = CategoryItem(category=c1)
     1079        ci2 = CategoryItem(category=c2)
     1080        ci3 = CategoryItem(category=c3)
     1081        ci1.save()
     1082        ci2.save()
     1083        ci3.save()
     1084
     1085        self.assertEqual(
     1086            CategoryItem.objects.exclude(category__specialcategory__isnull=False).count(),
     1087            1
     1088        )
     1089        self.assertItemsEqual(
     1090            CategoryItem.objects.exclude(category__specialcategory__isnull=False),
     1091            CategoryItem.objects.filter(pk__in=[ci1.pk])
     1092        )
     1093
     1094    def test_ticket15316_filter_true(self):
     1095        c1 = SimpleCategory(name="category1")
     1096        c2 = SpecialCategory(name="named category1", special_name="special1")
     1097        c3 = SpecialCategory(name="named category2", special_name="special2")
     1098        c1.save()
     1099        c2.save()
     1100        c3.save()
     1101        ci1 = CategoryItem(category=c1)
     1102        ci2 = CategoryItem(category=c2)
     1103        ci3 = CategoryItem(category=c3)
     1104        ci1.save()
     1105        ci2.save()
     1106        ci3.save()
     1107
     1108        self.assertEqual(
     1109            CategoryItem.objects.filter(category__specialcategory__isnull=True).count(),
     1110            1
     1111        )
     1112
     1113        self.assertItemsEqual(
     1114            CategoryItem.objects.filter(category__specialcategory__isnull=True),
     1115            CategoryItem.objects.filter(pk__in=[ci1.pk])
     1116        )
     1117
     1118    def test_ticket15316_exclude_true(self):
     1119        c1 = SimpleCategory(name="category1")
     1120        c2 = SpecialCategory(name="named category1", special_name="special1")
     1121        c3 = SpecialCategory(name="named category2", special_name="special2")
     1122        c1.save()
     1123        c2.save()
     1124        c3.save()
     1125
     1126        ci1 = CategoryItem(category=c1)
     1127        ci2 = CategoryItem(category=c2)
     1128        ci3 = CategoryItem(category=c3)
     1129        ci1.save()
     1130        ci2.save()
     1131        ci3.save()
     1132
     1133        self.assertEqual(
     1134            CategoryItem.objects.exclude(category__specialcategory__isnull=True).count(),
     1135            2
     1136        )
     1137
     1138        self.assertItemsEqual(
     1139            CategoryItem.objects.exclude(category__specialcategory__isnull=True),
     1140            CategoryItem.objects.filter(pk__in=[ci2.pk, ci3.pk])
     1141        )
     1142
     1143    def test_ticket15316_one2one_filter_false(self):
     1144        c  = SimpleCategory(name="cat")
     1145        c0 = SimpleCategory(name="cat0")
     1146        c1 = SimpleCategory(name="category1")
     1147
     1148        c.save()
     1149        c0.save()
     1150        c1.save()
     1151       
     1152        c2 = OneToOneCategory(category = c1, new_name="new1")
     1153        c3 = OneToOneCategory(category = c0, new_name="new2")
     1154
     1155        c2.save()
     1156        c3.save()
     1157
     1158        ci1 = CategoryItem(category=c)
     1159        ci2 = CategoryItem(category=c0)
     1160        ci3 = CategoryItem(category=c1)
     1161        ci1.save()
     1162        ci2.save()
     1163        ci3.save()
     1164
     1165        self.assertEqual(
     1166        CategoryItem.objects.filter(category__onetoonecategory__isnull=False).count(),
     1167            2
     1168        )
     1169        self.assertItemsEqual(
     1170            CategoryItem.objects.filter(category__onetoonecategory__isnull=False),
     1171            CategoryItem.objects.filter(pk__in=[ci2.pk, ci3.pk])
     1172        )
     1173
     1174    def test_ticket15316_one2one_exclude_false(self):
     1175        c  = SimpleCategory(name="cat")
     1176        c0 = SimpleCategory(name="cat0")
     1177        c1 = SimpleCategory(name="category1")
     1178
     1179        c.save()
     1180        c0.save()
     1181        c1.save()
     1182
     1183        c2 = OneToOneCategory(category = c1, new_name="new1")
     1184        c3 = OneToOneCategory(category = c0, new_name="new2")
     1185
     1186        c2.save()
     1187        c3.save()
     1188
     1189        ci1 = CategoryItem(category=c)
     1190        ci2 = CategoryItem(category=c0)
     1191        ci3 = CategoryItem(category=c1)
     1192        ci1.save()
     1193        ci2.save()
     1194        ci3.save()
     1195
     1196        self.assertEqual(
     1197            CategoryItem.objects.exclude(category__onetoonecategory__isnull=False).count(),
     1198            1
     1199        )
     1200        self.assertItemsEqual(
     1201            CategoryItem.objects.exclude(category__onetoonecategory__isnull=False),
     1202            CategoryItem.objects.filter(pk__in=[ci1.pk])
     1203        )
     1204
     1205    def test_ticket15316_one2one_filter_true(self):
     1206        c  = SimpleCategory(name="cat")
     1207        c0 = SimpleCategory(name="cat0")
     1208        c1 = SimpleCategory(name="category1")
     1209
     1210        c.save()
     1211        c0.save()
     1212        c1.save()
     1213
     1214        c2 = OneToOneCategory(category = c1, new_name="new1")
     1215        c3 = OneToOneCategory(category = c0, new_name="new2")
     1216
     1217        c2.save()
     1218        c3.save()
     1219
     1220        ci1 = CategoryItem(category=c)
     1221        ci2 = CategoryItem(category=c0)
     1222        ci3 = CategoryItem(category=c1)
     1223        ci1.save()
     1224        ci2.save()
     1225        ci3.save()
     1226
     1227        self.assertEqual(
     1228            CategoryItem.objects.filter(category__onetoonecategory__isnull=True).count(),
     1229            1
     1230        )
     1231
     1232        self.assertItemsEqual(
     1233            CategoryItem.objects.filter(category__onetoonecategory__isnull=True),
     1234            CategoryItem.objects.filter(pk__in=[ci1.pk])
     1235        )
     1236
     1237    def test_ticket15316_one2one_exclude_true(self):
     1238        c  = SimpleCategory(name="cat")
     1239        c0 = SimpleCategory(name="cat0")
     1240        c1 = SimpleCategory(name="category1")
     1241
     1242        c.save()
     1243        c0.save()
     1244        c1.save()
     1245
     1246        c2 = OneToOneCategory(category = c1, new_name="new1")
     1247        c3 = OneToOneCategory(category = c0, new_name="new2")
     1248
     1249        c2.save()
     1250        c3.save()
     1251
     1252        ci1 = CategoryItem(category=c)
     1253        ci2 = CategoryItem(category=c0)
     1254        ci3 = CategoryItem(category=c1)
     1255        ci1.save()
     1256        ci2.save()
     1257        ci3.save()
     1258
     1259        self.assertEqual(
     1260            CategoryItem.objects.exclude(category__onetoonecategory__isnull=True).count(),
     1261            2
     1262        )
     1263
     1264        self.assertItemsEqual(
     1265            CategoryItem.objects.exclude(category__onetoonecategory__isnull=True),
     1266            CategoryItem.objects.filter(pk__in=[ci2.pk, ci3.pk])
     1267        )
     1268
     1269
     1270
    10471271class Queries5Tests(TestCase):
    10481272    def setUp(self):
    10491273        # Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
  • tests/regressiontests/queries/models.py

     
    317317
    318318    def __unicode__(self):
    319319       return self.name
     320
     321class SimpleCategory(models.Model):
     322    name = models.CharField(max_length=10)
     323
     324    def __unicode__(self):
     325        return self.name
     326
     327class SpecialCategory(SimpleCategory):
     328    special_name = models.CharField(max_length=10)
     329
     330    def __unicode__(self):
     331        return self.name + " " + self.special_name
     332
     333class CategoryItem(models.Model):
     334    category = models.ForeignKey(SimpleCategory)
     335
     336    def __unicode__(self):
     337            return "category item: " + str(self.category)
     338
     339class OneToOneCategory(models.Model):
     340    new_name = models.CharField(max_length=10)
     341    category = models.OneToOneField(SimpleCategory)
     342
     343    def __unicode__(self):
     344        return "one2one " + self.new_name
     345   
     346 No newline at end of file
Back to Top