-
Notifications
You must be signed in to change notification settings - Fork 1
/
12890.Django-1.3.diff
103 lines (98 loc) · 5.47 KB
/
12890.Django-1.3.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
diff -ru Django-1.3/django/db/models/sql/compiler.py Django-1.3-patched/django/db/models/sql/compiler.py
--- Django-1.3/django/db/models/sql/compiler.py 2011-06-21 15:30:20.155858552 +0300
+++ Django-1.3-patched/django/db/models/sql/compiler.py 2011-06-21 15:46:53.399857085 +0300
@@ -462,13 +462,14 @@
result.append('%s%s%s' % (connector, qn(name), alias_str))
first = False
for t in self.query.extra_tables:
- alias, unused = self.query.table_alias(t)
+ alias, unused = self.query.table_alias(t, True)
# Only add the alias if it's not already present (the table_alias()
# calls increments the refcount, so an alias refcount of one means
# this is the only reference.
if alias not in self.query.alias_map or self.query.alias_refcount[alias] == 1:
connector = not first and ', ' or ''
- result.append('%s%s' % (connector, qn(alias)))
+ alias_str = (alias != t and ' %s' % alias or '')
+ result.append('%s%s%s' % (connector, qn(t), alias_str))
first = False
return result, []
diff -ru Django-1.3/django/db/models/sql/query.py Django-1.3-patched/django/db/models/sql/query.py
--- Django-1.3/django/db/models/sql/query.py 2011-06-21 15:30:20.159858921 +0300
+++ Django-1.3-patched/django/db/models/sql/query.py 2011-06-21 15:47:31.679857341 +0300
@@ -643,7 +643,7 @@
# Create a new alias for this table.
if current:
- alias = '%s%d' % (self.alias_prefix, len(self.alias_map) + 1)
+ alias = '%s%d' % (self.alias_prefix, sum([len(li) for li in self.table_map.values()]) + 1)
current.append(alias)
else:
# The first occurence of a table uses the table name directly.
diff -ru Django-1.3/tests/regressiontests/queries/models.py Django-1.3-patched/tests/regressiontests/queries/models.py
--- Django-1.3/tests/regressiontests/queries/models.py 2011-06-21 15:34:07.275858569 +0300
+++ Django-1.3-patched/tests/regressiontests/queries/models.py 2011-06-21 15:48:54.303858636 +0300
@@ -317,3 +317,9 @@
def __unicode__(self):
return self.name
+
+class NestedNode(models.Model):
+ lft = models.IntegerField()
+ rght = models.IntegerField()
+ name = models.CharField(max_length=100)
+ parent = models.ForeignKey("self", null=True)
diff -ru Django-1.3/tests/regressiontests/queries/tests.py Django-1.3-patched/tests/regressiontests/queries/tests.py
--- Django-1.3/tests/regressiontests/queries/tests.py 2011-06-21 15:34:07.275858569 +0300
+++ Django-1.3-patched/tests/regressiontests/queries/tests.py 2011-06-21 15:49:21.959359059 +0300
@@ -15,7 +15,7 @@
DumbCategory, ExtraInfo, Fan, Item, LeafA, LoopX, LoopZ, ManagedModel,
Member, NamedCategory, Note, Number, Plaything, PointerA, Ranking, Related,
Report, ReservedName, Tag, TvChef, Valid, X, Food, Eaten, Node, ObjectA, ObjectB,
- ObjectC)
+ ObjectC, NestedNode)
class BaseQuerysetTest(TestCase):
@@ -1735,3 +1735,45 @@
Q1 = Q(objecta__name='one', objectc__objecta__name='two')
Q2 = Q(objecta__objectc__name='ein', objectc__objecta__name='three', objecta__objectb__name='trois')
self.check_union(ObjectB, Q1, Q2)
+
+class ExtraTablesTest(TestCase):
+ def test_ticket12890(self):
+ """
+ This tests that self-joins, using extra(tables=...) work properly.
+ In the below example, a simple nested set model is used
+ (http://en.wikipedia.org/wiki/Nested_set_model), and the number
+ of children of each root node (including the node itself) are
+ calculated.
+
+ If the aliasing doesn't work properly, this test case will fail
+ with an error at the commented line. The further assertions check
+ that the results are also calculated correctly.
+ """
+ af = NestedNode.objects.create(name='Africa', lft=0, rght=10, parent=None)
+ ug = NestedNode.objects.create(name='Uganda', lft=1, rght=3, parent=af)
+ kla = NestedNode.objects.create(name='Kampala', lft=2,rght=2,parent=ug)
+ rw = NestedNode.objects.create(name='Rwanda', lft=4, rght=4, parent=af)
+ tz = NestedNode.objects.create(name='Tanzania', lft=5, rght=9, parent=af)
+ zb = NestedNode.objects.create(name='Zanzibar', lft=6, rght=8, parent=tz)
+ st = NestedNode.objects.create(name='Stone Town', lft=7, rght=7, parent=zb)
+
+ eu = NestedNode.objects.create(name='Europe',lft=11, rght=13,parent=None)
+ es = NestedNode.objects.create(name='Spain',lft=12,rght=12,parent=eu)
+
+ # The below query will fail with errors unless extra table aliasing is done
+ # properly
+ extra_query = list(NestedNode.objects\
+ .extra(tables=['queries_nestednode'],
+ where=['T2.lft <= queries_nestednode.lft',
+ 'T2.rght >= queries_nestednode.rght',
+ 'T2.parent_id is NULL'])\
+ .extra(select={'continent_name':'T2.name'})\
+ .values('continent_name')\
+ .annotate(Count('pk')).extra(order_by=['continent_name']))
+
+ # make sure the result is correct as well
+ self.assertEqual(extra_query[0]['continent_name'], 'Africa')
+ self.assertEqual(extra_query[0]['pk__count'], 7)
+
+ self.assertEqual(extra_query[1]['continent_name'], 'Europe')
+ self.assertEqual(extra_query[1]['pk__count'], 2)