Ticket #12252: 12252.1.diff
File 12252.1.diff, 5.3 KB (added by , 14 years ago) |
---|
-
django/db/models/sql/query.py
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
a b 446 446 "Cannot combine a unique query with a non-unique query." 447 447 448 448 self.remove_inherited_models() 449 l_tables = set([a for a in self.tables if self.alias_refcount[a]]) 450 r_tables = set([a for a in rhs.tables if rhs.alias_refcount[a]]) 449 451 # Work out how to relabel the rhs aliases, if necessary. 450 452 change_map = {} 451 453 used = set() … … 463 465 first = False 464 466 465 467 # So that we don't exclude valid results in an "or" query combination, 466 # the first join that is exclusive to the lhs (self)must be converted468 # all joins exclusive to either the lhs or the rhs must be converted 467 469 # to an outer join. 468 470 if not conjunction: 469 for alias in self.tables[1:]: 470 if self.alias_refcount[alias] == 1: 471 self.promote_alias(alias, True) 472 break 471 # Update r_tables aliases. 472 for alias in change_map: 473 if alias in r_tables: 474 r_tables.remove(alias) 475 r_tables.add(change_map[alias]) 476 # Find aliases that are exclusive to rhs or lhs. 477 # These are promoted to outer joins. 478 outer_aliases = (l_tables | r_tables) - (l_tables & r_tables) 479 for alias in outer_aliases: 480 self.promote_alias(alias, True) 473 481 474 482 # Now relabel a copy of the rhs where-clause and add it to the current 475 483 # one. -
tests/regressiontests/queries/models.py
diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
a b 294 294 295 295 def __unicode__(self): 296 296 return u"%s" % self.num 297 298 # Bug #12252 299 class ObjectA(models.Model): 300 name = models.CharField(max_length=50) 301 302 def __unicode__(self): 303 return self.name 304 305 class ObjectB(models.Model): 306 name = models.CharField(max_length=50) 307 objecta = models.ForeignKey(ObjectA) 308 number = models.PositiveSmallIntegerField() 309 310 def __unicode__(self): 311 return self.name 312 313 class ObjectC(models.Model): 314 name = models.CharField(max_length=50) 315 objecta = models.ForeignKey(ObjectA) 316 objectb = models.ForeignKey(ObjectB) 317 318 def __unicode__(self): 319 return self.name -
tests/regressiontests/queries/tests.py
diff --git a/tests/regressiontests/queries/tests.py b/tests/regressiontests/queries/tests.py
a b 14 14 from models import (Annotation, Article, Author, Celebrity, Child, Cover, Detail, 15 15 DumbCategory, ExtraInfo, Fan, Item, LeafA, LoopX, LoopZ, ManagedModel, 16 16 Member, NamedCategory, Note, Number, Plaything, PointerA, Ranking, Related, 17 Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node) 17 Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node, ObjectA, ObjectB, 18 ObjectC) 18 19 19 20 20 21 class BaseQuerysetTest(TestCase): … … 1658 1659 Number.objects.filter(num__in=numbers).count(), 1659 1660 2500 1660 1661 ) 1662 1663 class UnionTests(unittest.TestCase): 1664 """ 1665 Tests for the union of two querysets. Bug #12252. 1666 """ 1667 def setUp(self): 1668 objectas = [] 1669 objectbs = [] 1670 objectcs = [] 1671 a_info = ['one', 'two', 'three'] 1672 for name in a_info: 1673 o = ObjectA(name=name) 1674 o.save() 1675 objectas.append(o) 1676 b_info = [('un', 1, objectas[0]), ('deux', 2, objectas[0]), ('trois', 3, objectas[2])] 1677 for name, number, objecta in b_info: 1678 o = ObjectB(name=name, number=number, objecta=objecta) 1679 o.save() 1680 objectbs.append(o) 1681 c_info = [('ein', objectas[2], objectbs[2]), ('zwei', objectas[1], objectbs[1])] 1682 for name, objecta, objectb in c_info: 1683 o = ObjectC(name=name, objecta=objecta, objectb=objectb) 1684 o.save() 1685 objectcs.append(o) 1686 1687 def check_union(self, model, Q1, Q2): 1688 filter = model.objects.filter 1689 self.assertEqual(set(filter(Q1) | filter(Q2)), set(filter(Q1 | Q2))) 1690 self.assertEqual(set(filter(Q2) | filter(Q1)), set(filter(Q1 | Q2))) 1691 1692 def test_A_AB(self): 1693 Q1 = Q(name='two') 1694 Q2 = Q(objectb__name='deux') 1695 self.check_union(ObjectA, Q1, Q2) 1696 1697 def test_A_AB2(self): 1698 Q1 = Q(name='two') 1699 Q2 = Q(objectb__name='deux', objectb__number=2) 1700 self.check_union(ObjectA, Q1, Q2) 1701 1702 def test_AB_ACB(self): 1703 Q1 = Q(objectb__name='deux') 1704 Q2 = Q(objectc__objectb__name='deux') 1705 self.check_union(ObjectA, Q1, Q2) 1706 1707 def test_BAB_BAC(self): 1708 Q1 = Q(objecta__objectb__name='deux') 1709 Q2 = Q(objecta__objectc__name='ein') 1710 self.check_union(ObjectB, Q1, Q2) 1711 1712 def test_BAB_BACB(self): 1713 Q1 = Q(objecta__objectb__name='deux') 1714 Q2 = Q(objecta__objectc__objectb__name='trois') 1715 self.check_union(ObjectB, Q1, Q2) 1716 1717 def test_BA_BCA__BAB_BAC_BCA(self): 1718 Q1 = Q(objecta__name='one', objectc__objecta__name='two') 1719 Q2 = Q(objecta__objectc__name='ein', objectc__objecta__name='three', objecta__objectb__name='trois') 1720 self.check_union(ObjectB, Q1, Q2) 1721