Ticket #12252: 12252.1.diff

File 12252.1.diff, 5.3 KB (added by ramiro, 4 years ago)

Karen, no enough ORM fu here, but updated the patch removing unneeded code in tests (init(), setUp())

  • django/db/models/sql/query.py

    diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
    a b  
    446446            "Cannot combine a unique query with a non-unique query."
    447447
    448448        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]])
    449451        # Work out how to relabel the rhs aliases, if necessary.
    450452        change_map = {}
    451453        used = set()
     
    463465            first = False
    464466
    465467        # 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 converted
     468        # all joins exclusive to either the lhs or the rhs must be converted
    467469        # to an outer join.
    468470        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)
    473481
    474482        # Now relabel a copy of the rhs where-clause and add it to the current
    475483        # one.
  • tests/regressiontests/queries/models.py

    diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py
    a b  
    294294
    295295    def __unicode__(self):
    296296        return u"%s" % self.num
     297
     298# Bug #12252
     299class ObjectA(models.Model):
     300    name = models.CharField(max_length=50)
     301 
     302    def __unicode__(self):
     303        return self.name
     304
     305class 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
     313class 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  
    1414from models import (Annotation, Article, Author, Celebrity, Child, Cover, Detail,
    1515    DumbCategory, ExtraInfo, Fan, Item, LeafA, LoopX, LoopZ, ManagedModel,
    1616    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)
    1819
    1920
    2021class BaseQuerysetTest(TestCase):
     
    16581659            Number.objects.filter(num__in=numbers).count(),
    16591660            2500
    16601661        )
     1662
     1663class 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
Back to Top