Ticket #12890: 12890.Django-1.3.diff

File 12890.Django-1.3.diff, 5.5 KB (added by daveycrockett, 13 years ago)

Patch with fix and test case (for trunk)

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

    diff -ru Django-1.3/django/db/models/sql/compiler.py Django-1.3-patched/django/db/models/sql/compiler.py
    old new  
    462462                result.append('%s%s%s' % (connector, qn(name), alias_str))
    463463            first = False
    464464        for t in self.query.extra_tables:
    465             alias, unused = self.query.table_alias(t)
     465            alias, unused = self.query.table_alias(t, True)
    466466            # Only add the alias if it's not already present (the table_alias()
    467467            # calls increments the refcount, so an alias refcount of one means
    468468            # this is the only reference.
    469469            if alias not in self.query.alias_map or self.query.alias_refcount[alias] == 1:
    470470                connector = not first and ', ' or ''
    471                 result.append('%s%s' % (connector, qn(alias)))
     471                alias_str = (alias != t and ' %s' % alias or '')
     472                result.append('%s%s%s' % (connector, qn(t), alias_str))
    472473                first = False
    473474        return result, []
    474475
  • django/db/models/sql/query.py

    diff -ru Django-1.3/django/db/models/sql/query.py Django-1.3-patched/django/db/models/sql/query.py
    old new  
    643643
    644644        # Create a new alias for this table.
    645645        if current:
    646             alias = '%s%d' % (self.alias_prefix, len(self.alias_map) + 1)
     646            alias = '%s%d' % (self.alias_prefix, sum([len(li) for li in self.table_map.values()]) + 1)
    647647            current.append(alias)
    648648        else:
    649649            # The first occurence of a table uses the table name directly.
  • tests/regressiontests/queries/models.py

    diff -ru Django-1.3/tests/regressiontests/queries/models.py Django-1.3-patched/tests/regressiontests/queries/models.py
    old new  
    317317
    318318    def __unicode__(self):
    319319       return self.name
     320   
     321class NestedNode(models.Model):
     322    lft = models.IntegerField()
     323    rght = models.IntegerField()
     324    name = models.CharField(max_length=100)
     325    parent = models.ForeignKey("self", null=True)
  • tests/regressiontests/queries/tests.py

    diff -ru Django-1.3/tests/regressiontests/queries/tests.py Django-1.3-patched/tests/regressiontests/queries/tests.py
    old new  
    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, NestedNode)
    1919
    2020
    2121class BaseQuerysetTest(TestCase):
     
    17351735        Q1 = Q(objecta__name='one', objectc__objecta__name='two')
    17361736        Q2 = Q(objecta__objectc__name='ein', objectc__objecta__name='three', objecta__objectb__name='trois')
    17371737        self.check_union(ObjectB, Q1, Q2)
     1738
     1739class ExtraTablesTest(TestCase):
     1740    def test_ticket12890(self):
     1741        """
     1742            This tests that self-joins, using extra(tables=...) work properly.
     1743            In the below example, a simple nested set model is used
     1744            (http://en.wikipedia.org/wiki/Nested_set_model), and the number
     1745            of children of each root node (including the node itself) are
     1746            calculated.
     1747           
     1748            If the aliasing doesn't work properly, this test case will fail
     1749            with an error at the commented line.  The further assertions check
     1750            that the results are also calculated correctly.
     1751        """
     1752        af = NestedNode.objects.create(name='Africa', lft=0, rght=10, parent=None)
     1753        ug = NestedNode.objects.create(name='Uganda', lft=1, rght=3, parent=af)
     1754        kla = NestedNode.objects.create(name='Kampala', lft=2,rght=2,parent=ug)
     1755        rw = NestedNode.objects.create(name='Rwanda', lft=4, rght=4, parent=af)
     1756        tz = NestedNode.objects.create(name='Tanzania', lft=5, rght=9, parent=af)
     1757        zb = NestedNode.objects.create(name='Zanzibar', lft=6, rght=8, parent=tz)
     1758        st = NestedNode.objects.create(name='Stone Town', lft=7, rght=7, parent=zb)
     1759       
     1760        eu = NestedNode.objects.create(name='Europe',lft=11, rght=13,parent=None)
     1761        es = NestedNode.objects.create(name='Spain',lft=12,rght=12,parent=eu)
     1762       
     1763        # The below query will fail with errors unless extra table aliasing is done
     1764        # properly
     1765        extra_query = list(NestedNode.objects\
     1766            .extra(tables=['queries_nestednode'],
     1767                   where=['T2.lft <= queries_nestednode.lft',
     1768                          'T2.rght >= queries_nestednode.rght',
     1769                          'T2.parent_id is NULL'])\
     1770            .extra(select={'continent_name':'T2.name'})\
     1771            .values('continent_name')\
     1772            .annotate(Count('pk')).extra(order_by=['continent_name']))
     1773       
     1774        # make sure the result is correct as well
     1775        self.assertEqual(extra_query[0]['continent_name'], 'Africa')
     1776        self.assertEqual(extra_query[0]['pk__count'], 7)
     1777
     1778        self.assertEqual(extra_query[1]['continent_name'], 'Europe')
     1779        self.assertEqual(extra_query[1]['pk__count'], 2)
Back to Top