Ticket #12252: 12252.diff
File 12252.diff, 5.7 KB (added by , 14 years ago) |
---|
-
django/db/models/sql/query.py
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/tests.py
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. 1666 Bug #12252. 1667 """ 1668 1669 def __init__(self, *args, **kwargs): 1670 super(UnionTests, self).__init__(*args, **kwargs) 1671 1672 def setUp(self): 1673 # Don't bother setting up if already done 1674 if ObjectA.objects.all(): 1675 return 1676 objectas = [] 1677 objectbs = [] 1678 objectcs = [] 1679 a_info = ['one', 'two', 'three'] 1680 for name in a_info: 1681 o = ObjectA(name=name) 1682 o.save() 1683 objectas.append(o) 1684 b_info = [('un', 1, objectas[0]), ('deux', 2, objectas[0]), ('trois', 3, objectas[2])] 1685 for name, number, objecta in b_info: 1686 o = ObjectB(name=name, number=number, objecta=objecta) 1687 o.save() 1688 objectbs.append(o) 1689 c_info = [('ein', objectas[2], objectbs[2]), ('zwei', objectas[1], objectbs[1])] 1690 for name, objecta, objectb in c_info: 1691 o = ObjectC(name=name, objecta=objecta, objectb=objectb) 1692 o.save() 1693 objectcs.append(o) 1694 1695 def check_union(self, model, Q1, Q2): 1696 filter = model.objects.filter 1697 self.assertEqual(set(filter(Q1) | filter(Q2)), set(filter(Q1 | Q2))) 1698 self.assertEqual(set(filter(Q2) | filter(Q1)), set(filter(Q1 | Q2))) 1699 1700 def test_A_AB(self): 1701 Q1 = Q(name='two') 1702 Q2 = Q(objectb__name='deux') 1703 self.check_union(ObjectA, Q1, Q2) 1704 1705 def test_A_AB2(self): 1706 Q1 = Q(name='two') 1707 Q2 = Q(objectb__name='deux', objectb__number=2) 1708 self.check_union(ObjectA, Q1, Q2) 1709 1710 def test_AB_ACB(self): 1711 Q1 = Q(objectb__name='deux') 1712 Q2 = Q(objectc__objectb__name='deux') 1713 self.check_union(ObjectA, Q1, Q2) 1714 1715 def test_BAB_BAC(self): 1716 Q1 = Q(objecta__objectb__name='deux') 1717 Q2 = Q(objecta__objectc__name='ein') 1718 self.check_union(ObjectB, Q1, Q2) 1719 1720 def test_BAB_BACB(self): 1721 Q1 = Q(objecta__objectb__name='deux') 1722 Q2 = Q(objecta__objectc__objectb__name='trois') 1723 self.check_union(ObjectB, Q1, Q2) 1724 1725 def test_BA_BCA__BAB_BAC_BCA(self): 1726 Q1 = Q(objecta__name='one', objectc__objecta__name='two') 1727 Q2 = Q(objecta__objectc__name='ein', objectc__objecta__name='three', objecta__objectb__name='trois') 1728 self.check_union(ObjectB, Q1, Q2) 1729 -
tests/regressiontests/queries/models.py
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