App Engine Python SDK version 1.7.4 (2)
[gae.git] / python / lib / django_1_4 / tests / regressiontests / extra_regress / tests.py
blob67efb428ddefd3f4c788db376d1ff7a3343cf35c
1 from __future__ import absolute_import
3 import datetime
5 from django.contrib.auth.models import User
6 from django.test import TestCase
7 from django.utils.datastructures import SortedDict
9 from .models import TestObject, Order, RevisionableModel
12 class ExtraRegressTests(TestCase):
14 def setUp(self):
15 self.u = User.objects.create_user(
16 username="fred",
17 password="secret",
18 email="fred@example.com"
21 def test_regression_7314_7372(self):
22 """
23 Regression tests for #7314 and #7372
24 """
25 rm = RevisionableModel.objects.create(
26 title='First Revision',
27 when=datetime.datetime(2008, 9, 28, 10, 30, 0)
29 self.assertEqual(rm.pk, rm.base.pk)
31 rm2 = rm.new_revision()
32 rm2.title = "Second Revision"
33 rm.when = datetime.datetime(2008, 9, 28, 14, 25, 0)
34 rm2.save()
36 self.assertEqual(rm2.title, 'Second Revision')
37 self.assertEqual(rm2.base.title, 'First Revision')
39 self.assertNotEqual(rm2.pk, rm.pk)
40 self.assertEqual(rm2.base.pk, rm.pk)
42 # Queryset to match most recent revision:
43 qs = RevisionableModel.objects.extra(
44 where=["%(table)s.id IN (SELECT MAX(rev.id) FROM %(table)s rev GROUP BY rev.base_id)" % {
45 'table': RevisionableModel._meta.db_table,
49 self.assertQuerysetEqual(qs,
50 [('Second Revision', 'First Revision')],
51 transform=lambda r: (r.title, r.base.title)
54 # Queryset to search for string in title:
55 qs2 = RevisionableModel.objects.filter(title__contains="Revision")
56 self.assertQuerysetEqual(qs2,
58 ('First Revision', 'First Revision'),
59 ('Second Revision', 'First Revision'),
61 transform=lambda r: (r.title, r.base.title)
64 # Following queryset should return the most recent revision:
65 self.assertQuerysetEqual(qs & qs2,
66 [('Second Revision', 'First Revision')],
67 transform=lambda r: (r.title, r.base.title)
70 def test_extra_stay_tied(self):
71 # Extra select parameters should stay tied to their corresponding
72 # select portions. Applies when portions are updated or otherwise
73 # moved around.
74 qs = User.objects.extra(
75 select=SortedDict((("alpha", "%s"), ("beta", "2"), ("gamma", "%s"))),
76 select_params=(1, 3)
78 qs = qs.extra(select={"beta": 4})
79 qs = qs.extra(select={"alpha": "%s"}, select_params=[5])
80 self.assertEqual(
81 list(qs.filter(id=self.u.id).values('alpha', 'beta', 'gamma')),
82 [{'alpha': 5, 'beta': 4, 'gamma': 3}]
85 def test_regression_7957(self):
86 """
87 Regression test for #7957: Combining extra() calls should leave the
88 corresponding parameters associated with the right extra() bit. I.e.
89 internal dictionary must remain sorted.
90 """
91 self.assertEqual(
92 User.objects.extra(select={"alpha": "%s"}, select_params=(1,)
93 ).extra(select={"beta": "%s"}, select_params=(2,))[0].alpha,
96 self.assertEqual(
97 User.objects.extra(select={"beta": "%s"}, select_params=(1,)
98 ).extra(select={"alpha": "%s"}, select_params=(2,))[0].alpha,
101 def test_regression_7961(self):
103 Regression test for #7961: When not using a portion of an
104 extra(...) in a query, remove any corresponding parameters from the
105 query as well.
107 self.assertEqual(
108 list(User.objects.extra(select={"alpha": "%s"}, select_params=(-6,)
109 ).filter(id=self.u.id).values_list('id', flat=True)),
110 [self.u.id]
113 def test_regression_8063(self):
115 Regression test for #8063: limiting a query shouldn't discard any
116 extra() bits.
118 qs = User.objects.all().extra(where=['id=%s'], params=[self.u.id])
119 self.assertQuerysetEqual(qs, ['<User: fred>'])
120 self.assertQuerysetEqual(qs[:1], ['<User: fred>'])
122 def test_regression_8039(self):
124 Regression test for #8039: Ordering sometimes removed relevant tables
125 from extra(). This test is the critical case: ordering uses a table,
126 but then removes the reference because of an optimisation. The table
127 should still be present because of the extra() call.
129 self.assertQuerysetEqual(
130 Order.objects.extra(where=["username=%s"],
131 params=["fred"],
132 tables=["auth_user"]
133 ).order_by('created_by'),
137 def test_regression_8819(self):
139 Regression test for #8819: Fields in the extra(select=...) list
140 should be available to extra(order_by=...).
142 self.assertQuerysetEqual(
143 User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}).distinct(),
144 ['<User: fred>']
146 self.assertQuerysetEqual(
147 User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']),
148 ['<User: fred>']
150 self.assertQuerysetEqual(
151 User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']).distinct(),
152 ['<User: fred>']
155 def test_dates_query(self):
157 When calling the dates() method on a queryset with extra selection
158 columns, we can (and should) ignore those columns. They don't change
159 the result and cause incorrect SQL to be produced otherwise.
161 rm = RevisionableModel.objects.create(
162 title='First Revision',
163 when=datetime.datetime(2008, 9, 28, 10, 30, 0)
166 self.assertQuerysetEqual(
167 RevisionableModel.objects.extra(select={"the_answer": 'id'}).dates('when', 'month'),
168 ['datetime.datetime(2008, 9, 1, 0, 0)']
171 def test_values_with_extra(self):
173 Regression test for #10256... If there is a values() clause, Extra
174 columns are only returned if they are explicitly mentioned.
176 obj = TestObject(first='first', second='second', third='third')
177 obj.save()
179 self.assertEqual(
180 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values()),
181 [{'bar': u'second', 'third': u'third', 'second': u'second', 'whiz': u'third', 'foo': u'first', 'id': obj.pk, 'first': u'first'}]
184 # Extra clauses after an empty values clause are still included
185 self.assertEqual(
186 list(TestObject.objects.values().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
187 [{'bar': u'second', 'third': u'third', 'second': u'second', 'whiz': u'third', 'foo': u'first', 'id': obj.pk, 'first': u'first'}]
190 # Extra columns are ignored if not mentioned in the values() clause
191 self.assertEqual(
192 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('first', 'second')),
193 [{'second': u'second', 'first': u'first'}]
196 # Extra columns after a non-empty values() clause are ignored
197 self.assertEqual(
198 list(TestObject.objects.values('first', 'second').extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
199 [{'second': u'second', 'first': u'first'}]
202 # Extra columns can be partially returned
203 self.assertEqual(
204 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('first', 'second', 'foo')),
205 [{'second': u'second', 'foo': u'first', 'first': u'first'}]
208 # Also works if only extra columns are included
209 self.assertEqual(
210 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('foo', 'whiz')),
211 [{'foo': u'first', 'whiz': u'third'}]
214 # Values list works the same way
215 # All columns are returned for an empty values_list()
216 self.assertEqual(
217 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list()),
218 [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
221 # Extra columns after an empty values_list() are still included
222 self.assertEqual(
223 list(TestObject.objects.values_list().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
224 [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
227 # Extra columns ignored completely if not mentioned in values_list()
228 self.assertEqual(
229 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second')),
230 [(u'first', u'second')]
233 # Extra columns after a non-empty values_list() clause are ignored completely
234 self.assertEqual(
235 list(TestObject.objects.values_list('first', 'second').extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
236 [(u'first', u'second')]
239 self.assertEqual(
240 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('second', flat=True)),
241 [u'second']
244 # Only the extra columns specified in the values_list() are returned
245 self.assertEqual(
246 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second', 'whiz')),
247 [(u'first', u'second', u'third')]
250 # ...also works if only extra columns are included
251 self.assertEqual(
252 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('foo','whiz')),
253 [(u'first', u'third')]
256 self.assertEqual(
257 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz', flat=True)),
258 [u'third']
261 # ... and values are returned in the order they are specified
262 self.assertEqual(
263 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz','foo')),
264 [(u'third', u'first')]
267 self.assertEqual(
268 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first','id')),
269 [(u'first', obj.pk)]
272 self.assertEqual(
273 list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz', 'first', 'bar', 'id')),
274 [(u'third', u'first', u'second', obj.pk)]
277 def test_regression_10847(self):
279 Regression for #10847: the list of extra columns can always be
280 accurately evaluated. Using an inner query ensures that as_sql() is
281 producing correct output without requiring full evaluation and
282 execution of the inner query.
284 obj = TestObject(first='first', second='second', third='third')
285 obj.save()
287 self.assertEqual(
288 list(TestObject.objects.extra(select={'extra': 1}).values('pk')),
289 [{'pk': obj.pk}]
292 self.assertQuerysetEqual(
293 TestObject.objects.filter(
294 pk__in=TestObject.objects.extra(select={'extra': 1}).values('pk')
296 ['<TestObject: TestObject: first,second,third>']
299 self.assertEqual(
300 list(TestObject.objects.values('pk').extra(select={'extra': 1})),
301 [{'pk': obj.pk}]
304 self.assertQuerysetEqual(
305 TestObject.objects.filter(
306 pk__in=TestObject.objects.values('pk').extra(select={'extra': 1})
308 ['<TestObject: TestObject: first,second,third>']
311 self.assertQuerysetEqual(
312 TestObject.objects.filter(pk=obj.pk) |
313 TestObject.objects.extra(where=["id > %s"], params=[obj.pk]),
314 ['<TestObject: TestObject: first,second,third>']