#14146: Incorrect query being generated by .exclude() in some inheritance cases
------------------------------------------+---------------------------------
 Reporter:  coleifer                      |       Owner:  nobody    
   Status:  new                           |   Milestone:            
Component:  Database layer (models, ORM)  |     Version:  1.2       
 Keywords:                                |       Stage:  Unreviewed
Has_patch:  0                             |  
------------------------------------------+---------------------------------
 This is a particularly nasty bug because the results are not always
 immediately obvious.  Essentially, assume you have some models:


 {{{
 class BasePost(models.Model):
     author = models.ForeignKey(User, related_name='posts')
     title = models.CharField(max_length=100)

     class Meta:
         ordering = ['id']

 class PostSubclass(BasePost):
     pass

 STATUS_GOOD = 1
 STATUS_BAD = 2
 STATUS_CHOICES = (
     (STATUS_GOOD, 'Good'),
     (STATUS_BAD, 'Bad'),
 )
 class AuthorProfile(models.Model):
     user = models.OneToOneField(User)
     status = models.IntegerField(choices=STATUS_CHOICES)
 }}}


 You want to get Posts by authors whose status is *NOT* BAD:

 {{{
 good_post_qs = PostSubclass.objects.filter(
             author__authorprofile__status=STATUS_GOOD
         )
 }}}

 That works as expected, but it doesn't take into consideration that some
 authors may not have a profile and in that case you want to get their
 posts as well.  Essentially anything *but* the bad ('''why dont we have a
 __ne filter again?''') -- you would have to do this:

 {{{
 not_bad_post_qs = PostSubclass.objects.exclude(
             author__authorprofile__status=STATUS_BAD
         )
 }}}

 This generates incorrect query - see the joining done by the subquery:

 {{{
 SELECT "model_inheritance_basepost"."id",
 "model_inheritance_basepost"."author_id",
 "model_inheritance_basepost"."title",
 "model_inheritance_postsubclass"."basepost_ptr_id"
         FROM "model_inheritance_postsubclass"

         INNER JOIN "model_inheritance_basepost"
             ON ("model_inheritance_postsubclass"."basepost_ptr_id" =
 "model_inheritance_basepost"."id")

         WHERE NOT ((
             "model_inheritance_basepost"."author_id" IN (

                 SELECT U1."id" FROM "model_inheritance_basepost" U1
                 INNER JOIN "auth_user" U2
                     ON (U1."author_id" = U2."id")
                 INNER JOIN "model_inheritance_authorprofile" U3
                     ON (U2."id" = U3."user_id")
                 WHERE U3."status" = 2
             ) AND
             "model_inheritance_basepost"."author_id" IS NOT NULL
         ))

         ORDER BY "model_inheritance_postsubclass"."basepost_ptr_id" ASC
 }}}

-- 
Ticket URL: <http://code.djangoproject.com/ticket/14146>
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