PageRenderTime 313ms CodeModel.GetById 80ms app.highlight 98ms RepoModel.GetById 83ms app.codeStats 0ms

/tests/regressiontests/extra_regress/tests.py

https://code.google.com/p/mango-py/
Python | 314 lines | 273 code | 18 blank | 23 comment | 1 complexity | 501664980e720f32fd38197d6f577880 MD5 | raw file
  1from django.test import TestCase
  2
  3from django.utils.datastructures import SortedDict
  4
  5from django.contrib.auth.models import User
  6from regressiontests.extra_regress.models import TestObject, Order, \
  7        RevisionableModel
  8
  9import datetime
 10
 11class ExtraRegressTests(TestCase):
 12
 13    def setUp(self):
 14        self.u = User.objects.create_user(
 15                    username="fred",
 16                    password="secret",
 17                    email="fred@example.com"
 18        )
 19
 20    def test_regression_7314_7372(self):
 21        """
 22        Regression tests for #7314 and #7372
 23        """
 24        rm = RevisionableModel.objects.create(
 25            title='First Revision',
 26            when=datetime.datetime(2008, 9, 28, 10, 30, 0)
 27        )
 28        self.assertEqual(rm.pk, rm.base.pk)
 29
 30        rm2 = rm.new_revision()
 31        rm2.title = "Second Revision"
 32        rm.when = datetime.datetime(2008, 9, 28, 14, 25, 0)
 33        rm2.save()
 34
 35        self.assertEqual(rm2.title, 'Second Revision')
 36        self.assertEqual(rm2.base.title, 'First Revision')
 37
 38        self.assertNotEqual(rm2.pk, rm.pk)
 39        self.assertEqual(rm2.base.pk, rm.pk)
 40
 41        # Queryset to match most recent revision:
 42        qs = RevisionableModel.objects.extra(
 43                where=["%(table)s.id IN (SELECT MAX(rev.id) FROM %(table)s rev GROUP BY rev.base_id)" % {
 44                    'table': RevisionableModel._meta.db_table,
 45                }]
 46        )
 47
 48        self.assertQuerysetEqual(qs,
 49            [('Second Revision', 'First Revision')],
 50            transform=lambda r: (r.title, r.base.title)
 51        )
 52
 53        # Queryset to search for string in title:
 54        qs2 = RevisionableModel.objects.filter(title__contains="Revision")
 55        self.assertQuerysetEqual(qs2,
 56            [
 57                ('First Revision', 'First Revision'),
 58                ('Second Revision', 'First Revision'),
 59            ],
 60            transform=lambda r: (r.title, r.base.title)
 61        )
 62
 63        # Following queryset should return the most recent revision:
 64        self.assertQuerysetEqual(qs & qs2,
 65            [('Second Revision', 'First Revision')],
 66            transform=lambda r: (r.title, r.base.title)
 67        )
 68
 69    def test_extra_stay_tied(self):
 70        # Extra select parameters should stay tied to their corresponding
 71        # select portions. Applies when portions are updated or otherwise
 72        # moved around.
 73        qs = User.objects.extra(
 74                    select=SortedDict((("alpha", "%s"), ("beta", "2"),  ("gamma", "%s"))),
 75                    select_params=(1, 3)
 76        )
 77        qs = qs.extra(select={"beta": 4})
 78        qs = qs.extra(select={"alpha": "%s"}, select_params=[5])
 79        self.assertEqual(
 80            list(qs.filter(id=self.u.id).values('alpha', 'beta', 'gamma')),
 81            [{'alpha': 5, 'beta': 4, 'gamma': 3}]
 82        )
 83
 84    def test_regression_7957(self):
 85        """
 86        Regression test for #7957: Combining extra() calls should leave the
 87        corresponding parameters associated with the right extra() bit. I.e.
 88        internal dictionary must remain sorted.
 89        """
 90        self.assertEqual(
 91            User.objects.extra(select={"alpha": "%s"}, select_params=(1,)
 92                       ).extra(select={"beta": "%s"}, select_params=(2,))[0].alpha,
 93            1)
 94
 95        self.assertEqual(
 96            User.objects.extra(select={"beta": "%s"}, select_params=(1,)
 97                       ).extra(select={"alpha": "%s"}, select_params=(2,))[0].alpha,
 98            2)
 99
100    def test_regression_7961(self):
101        """
102        Regression test for #7961: When not using a portion of an
103        extra(...) in a query, remove any corresponding parameters from the
104        query as well.
105        """
106        self.assertEqual(
107            list(User.objects.extra(select={"alpha": "%s"}, select_params=(-6,)
108                    ).filter(id=self.u.id).values_list('id', flat=True)),
109            [self.u.id]
110        )
111
112    def test_regression_8063(self):
113        """
114        Regression test for #8063: limiting a query shouldn't discard any
115        extra() bits.
116        """
117        qs = User.objects.all().extra(where=['id=%s'], params=[self.u.id])
118        self.assertQuerysetEqual(qs, ['<User: fred>'])
119        self.assertQuerysetEqual(qs[:1], ['<User: fred>'])
120
121    def test_regression_8039(self):
122        """
123        Regression test for #8039: Ordering sometimes removed relevant tables
124        from extra(). This test is the critical case: ordering uses a table,
125        but then removes the reference because of an optimisation. The table
126        should still be present because of the extra() call.
127        """
128        self.assertQuerysetEqual(
129                Order.objects.extra(where=["username=%s"],
130                                    params=["fred"],
131                                    tables=["auth_user"]
132                            ).order_by('created_by'),
133                []
134        )
135
136    def test_regression_8819(self):
137        """
138        Regression test for #8819: Fields in the extra(select=...) list
139        should be available to extra(order_by=...).
140        """
141        self.assertQuerysetEqual(
142            User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}).distinct(),
143            ['<User: fred>']
144        )
145        self.assertQuerysetEqual(
146            User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']),
147            ['<User: fred>']
148        )
149        self.assertQuerysetEqual(
150            User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']).distinct(),
151            ['<User: fred>']
152        )
153
154    def test_dates_query(self):
155        """
156        When calling the dates() method on a queryset with extra selection
157        columns, we can (and should) ignore those columns. They don't change
158        the result and cause incorrect SQL to be produced otherwise.
159        """
160        rm = RevisionableModel.objects.create(
161            title='First Revision',
162            when=datetime.datetime(2008, 9, 28, 10, 30, 0)
163        )
164
165        self.assertQuerysetEqual(
166            RevisionableModel.objects.extra(select={"the_answer": 'id'}).dates('when', 'month'),
167            ['datetime.datetime(2008, 9, 1, 0, 0)']
168        )
169
170    def test_values_with_extra(self):
171        """
172        Regression test for #10256... If there is a values() clause, Extra
173        columns are only returned if they are explicitly mentioned.
174        """
175        obj = TestObject(first='first', second='second', third='third')
176        obj.save()
177
178        self.assertEqual(
179            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values()),
180            [{'bar': u'second', 'third': u'third', 'second': u'second', 'whiz': u'third', 'foo': u'first', 'id': obj.pk, 'first': u'first'}]
181        )
182
183        # Extra clauses after an empty values clause are still included
184        self.assertEqual(
185            list(TestObject.objects.values().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
186            [{'bar': u'second', 'third': u'third', 'second': u'second', 'whiz': u'third', 'foo': u'first', 'id': obj.pk, 'first': u'first'}]
187        )
188
189        # Extra columns are ignored if not mentioned in the values() clause
190        self.assertEqual(
191            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('first', 'second')),
192            [{'second': u'second', 'first': u'first'}]
193        )
194
195        # Extra columns after a non-empty values() clause are ignored
196        self.assertEqual(
197            list(TestObject.objects.values('first', 'second').extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
198            [{'second': u'second', 'first': u'first'}]
199        )
200
201        # Extra columns can be partially returned
202        self.assertEqual(
203            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('first', 'second', 'foo')),
204            [{'second': u'second', 'foo': u'first', 'first': u'first'}]
205        )
206
207        # Also works if only extra columns are included
208        self.assertEqual(
209            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values('foo', 'whiz')),
210            [{'foo': u'first', 'whiz': u'third'}]
211        )
212
213        # Values list works the same way
214        # All columns are returned for an empty values_list()
215        self.assertEqual(
216            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list()),
217            [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
218        )
219
220        # Extra columns after an empty values_list() are still included
221        self.assertEqual(
222            list(TestObject.objects.values_list().extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
223            [(u'first', u'second', u'third', obj.pk, u'first', u'second', u'third')]
224        )
225
226        # Extra columns ignored completely if not mentioned in values_list()
227        self.assertEqual(
228            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second')),
229            [(u'first', u'second')]
230        )
231
232        # Extra columns after a non-empty values_list() clause are ignored completely
233        self.assertEqual(
234            list(TestObject.objects.values_list('first', 'second').extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third'))))),
235            [(u'first', u'second')]
236        )
237
238        self.assertEqual(
239            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('second', flat=True)),
240            [u'second']
241        )
242
243        # Only the extra columns specified in the values_list() are returned
244        self.assertEqual(
245            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first', 'second', 'whiz')),
246            [(u'first', u'second', u'third')]
247        )
248
249        # ...also works if only extra columns are included
250        self.assertEqual(
251            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('foo','whiz')),
252            [(u'first', u'third')]
253        )
254
255        self.assertEqual(
256            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz', flat=True)),
257            [u'third']
258        )
259
260        # ... and values are returned in the order they are specified
261        self.assertEqual(
262            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz','foo')),
263            [(u'third', u'first')]
264        )
265
266        self.assertEqual(
267            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('first','id')),
268            [(u'first', obj.pk)]
269        )
270
271        self.assertEqual(
272            list(TestObject.objects.extra(select=SortedDict((('foo','first'), ('bar','second'), ('whiz','third')))).values_list('whiz', 'first', 'bar', 'id')),
273            [(u'third', u'first', u'second', obj.pk)]
274        )
275
276    def test_regression_10847(self):
277        """
278        Regression for #10847: the list of extra columns can always be
279        accurately evaluated. Using an inner query ensures that as_sql() is
280        producing correct output without requiring full evaluation and
281        execution of the inner query.
282        """
283        obj = TestObject(first='first', second='second', third='third')
284        obj.save()
285
286        self.assertEqual(
287            list(TestObject.objects.extra(select={'extra': 1}).values('pk')),
288            [{'pk': obj.pk}]
289        )
290
291        self.assertQuerysetEqual(
292            TestObject.objects.filter(
293                    pk__in=TestObject.objects.extra(select={'extra': 1}).values('pk')
294            ),
295            ['<TestObject: TestObject: first,second,third>']
296        )
297
298        self.assertEqual(
299            list(TestObject.objects.values('pk').extra(select={'extra': 1})),
300            [{'pk': obj.pk}]
301        )
302
303        self.assertQuerysetEqual(
304            TestObject.objects.filter(
305                 pk__in=TestObject.objects.values('pk').extra(select={'extra': 1})
306            ),
307            ['<TestObject: TestObject: first,second,third>']
308        )
309
310        self.assertQuerysetEqual(
311            TestObject.objects.filter(pk=obj.pk) |
312               TestObject.objects.extra(where=["id > %s"], params=[obj.pk]),
313            ['<TestObject: TestObject: first,second,third>']
314        )