#10977: In some cases, the intersection of two QuerySets is empty when it 
shouldn't
be
---------------------------------------------------+------------------------
          Reporter:  zain                          |         Owner:  clement
            Status:  new                           |     Milestone:         
         Component:  Database layer (models, ORM)  |       Version:  1.0    
        Resolution:                                |      Keywords:         
             Stage:  Unreviewed                    |     Has_patch:  0      
        Needs_docs:  0                             |   Needs_tests:  0      
Needs_better_patch:  0                             |  
---------------------------------------------------+------------------------
Comment (by clement):

 Well, it seems there's a bug in BaseQuery.combine, when relabeling
 aliases. It happens when the rhs query object contains JOIN ''from'' an
 aliased table; they are converted to JOINs ''from'' the original table
 because the code is building a new join using data coming from
 '''.rev_join_map''' (and not '''.alias_map''') :


 {{{
 #!python
 # django/db/models/sql/query.py, line 501
         for alias in rhs.tables:
             if not rhs.alias_refcount[alias]:
                 # An unused alias.
                 continue
             promote = (rhs.alias_map[alias][JOIN_TYPE] == self.LOUTER)
             new_alias = self.join(rhs.rev_join_map[alias],
                     (conjunction and not first), used, promote, not
 conjunction)
             used.add(new_alias)
             change_map[alias] = new_alias
 }}}

 To recreate this bug, any query joining from an alias will be enough, and
 will give an incorrect SQL query string when combined (right-operand) to a
 simple query, on the same base object. For example, with :

 {{{
 #!python
 class ModelA(models.Model):
   text = models.CharField(max_length=100)
   a = models.ForeignKey('ModelA')
   b = models.ForeignKey('ModelB')

 class ModelB(models.Model):
   text = models.CharField(max_length=100)
 }}}

 That will give:

 {{{
 #!python
 >>> qs_simple = ModelA.objects.all()
 >>> qs_joined =
 
ModelA.objects.filter(b__text__icontains='foo').filter(a__b__text__icontains='bar')
 >>> str(qs_simple.query) # Formatted for clarity
 SELECT "queries_modela"."id", "queries_modela"."text",
 "queries_modela"."a_id", "queries_modela"."b_id"
     FROM "queries_modela"
 >>> str(qs_joined.query) # Formatted for clarity
 SELECT "queries_modela"."id", "queries_modela"."text",
 "queries_modela"."a_id", "queries_modela"."b_id"
     FROM "queries_modela"
     INNER JOIN "queries_modelb"
         ON ("queries_modela"."b_id" = "queries_modelb"."id")
     INNER JOIN "queries_modela" T3
         ON ("queries_modela"."a_id" = T3."id")
     INNER JOIN "queries_modelb" T4
         ON (T3."b_id" = T4."id")
 WHERE ("queries_modelb"."text" LIKE %foo% ESCAPE '\' AND T4."text" LIKE
 %bar% ESCAPE '\' )
 >>> str((qs_simple & qs_joined).query) # Formatted for clarity
 SELECT "queries_modela"."id", "queries_modela"."text",
 "queries_modela"."a_id", "queries_modela"."b_id"
     FROM "queries_modela"
     INNER JOIN "queries_modelb"
         ON ("queries_modela"."b_id" = "queries_modelb"."id")
     INNER JOIN "queries_modela" T3
         ON ("queries_modela"."a_id" = T3."id")
     INNER JOIN "queries_modelb" T4
         ON ("queries_modela"."b_id" = T4."id")
 WHERE ("queries_modelb"."text" LIKE %foo% ESCAPE '\'  AND T4."text" LIKE
 %bar% ESCAPE '\' )
 }}}

 Seeing here that the '''T4''' join ON condition becomes incorrect when
 '''qs_joined''' is combined to '''qs_simple'''

-- 
Ticket URL: <http://code.djangoproject.com/ticket/10977#comment:2>
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 [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to