#12328: subqueries in django 1.1 behave oddly
------------------------------------------+---------------------------------
 Reporter:  wdoekes                       |       Owner:  nobody    
   Status:  new                           |   Milestone:            
Component:  Database layer (models, ORM)  |     Version:  1.1       
 Keywords:                                |       Stage:  Unreviewed
Has_patch:  0                             |  
------------------------------------------+---------------------------------
 Hi, I'm not sure what is wrong exactly. But it looks like subqueries in
 filters (introduced in django 1.1?) do not always work as intended.


 A basic model:
 {{{
 from django.db import models
 class M(models.Model):
     def __unicode__(self):
         return 'M(id=%d)' % self.id
 }}}

 The setup:
 {{{
 $ ./manage shell
 Python 2.5.2 (r252:60911, Jan  4 2009, 21:59:32)
 [GCC 4.3.2] on linux2
 Type "help", "copyright", "credits" or "license" for more information.
 (InteractiveConsole)
 >>> from osso.test.models import M
 >>> M.objects.create(id=1)
 <M: M(id=1)>
 >>> M.objects.create(id=2)
 <M: M(id=2)>
 >>> M.objects.create(id=3)
 <M: M(id=3)>
 >>> M.objects.all()
 [<M: M(id=1)>, <M: M(id=2)>, <M: M(id=3)>]
 >>> M.objects.order_by('id')[:1]
 [<M: M(id=1)>]
 >>> M.objects.order_by('id')[:1].delete()
 Traceback (most recent call last):
   File "<console>", line 1, in <module>
   File "/opt/django11/django/db/models/query.py", line 379, in delete
     "Cannot use 'limit' or 'offset' with delete."
 AssertionError: Cannot use 'limit' or 'offset' with delete.
 }}}

 Bear with me. You have noticed my goal is to delete old records.

 Watch django1.0:
 {{{
 >>> M.objects.filter(id__in=M.objects.order_by('id')[0:1])
 <snip>
 TypeError: int() argument must be a string or a number, not 'M'
 >>>
 M.objects.filter(id__in=M.objects.order_by('id')[0:1].values_list('id',
 flat=True))
 [<M: M(id=1)>]
 >>>
 M.objects.filter(id__in=M.objects.order_by('id')[0:1].values_list('id',
 flat=True)).delete()
 >>> M.objects.all()
 [<M: M(id=2)>, <M: M(id=3)>]
 }}}
 That works as intended.

 And now django 1.1:
 {{{
 >>> M.objects.filter(id__in=M.objects.order_by('id')[:1])
 [<M: M(id=1)>]
 >>> M.objects.filter(id__in=M.objects.order_by('id')[:1]).delete()
 >>> M.objects.all()
 []
 }}}
 (The same happens if I use the values_list() notation as used above.)

 What happens is that the del_query in QuerySet.delete() refers to a newer
 object every time, until all M objects have been deleted.

 The following could be related, or not :)

 After deleting an M object and re-adding it, I notice that ordering in
 subqueries does not work as intended either:
 {{{
 >>> M.objects.order_by('id')
 [<M: M(id=1)>, <M: M(id=2)>, <M: M(id=3)>]
 >>> M.objects.order_by('id')[0:1]
 [<M: M(id=1)>]
 >>> M.objects.filter(id__in=M.objects.order_by('id')[0:1])
 [<M: M(id=2)>]
 >>>
 M.objects.filter(id__in=M.objects.order_by('id')[0:1].values_list('id',
 flat=True))
 [<M: M(id=2)>]
 }}}

 This was tested with postgresql_psycopg2. With MySQL I cannot reproduce
 it, as it disallows LIMIT in subqueries, sending me an early error instead
 of behaving errantly.

 My current workaround is to wrap "M.objects.order_by('id')[:1]" in a
 list() so I do not get a dynamic object as id\_\_in value. Having to force
 early evaluation is a bit frightening though.

 I assume one should be able to reproduce this easily. If not, I'd be happy
 to share more information about my setup.

 Regards,[[br]]
 Walter Doekes

-- 
Ticket URL: <http://code.djangoproject.com/ticket/12328>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

--

You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.


Reply via email to