#32717: Incorrect SQL generation filtering OR-combined queries
-------------------------------------+-------------------------------------
     Reporter:  Shaheed Haque        |                    Owner:  Simon
                                     |  Charette
         Type:  Bug                  |                   Status:  assigned
    Component:  Database layer       |                  Version:  3.2
  (models, ORM)                      |
     Severity:  Release blocker      |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Simon Charette):

 I started looking into this one and it seems the issue is two fold.

 One
 
[https://github.com/django/django/blob/205c36b58fed5a1a0ff462593fc61b58189027d8/django/utils/tree.py#L93-L94
 the ''optimization''] in `Node.add` strikes again this time for `Lookup`
 equality as it was introduced in bbf141bcdc31f1324048af9233583a523ac54c94.
 As we already know [https://code.djangoproject.com/ticket/32632#comment:4
 this code is poorly tested] and this issue just uncovered that it's
 actually flawed as it should also make sure that connectors are matching.

 What's happening here is that the query has a `WHERE` tree of the form
 `(jurisdiction = 'US' OR ...)` and it wrongfully consider that an addition
 of a `AND jurisdiction = 'US'` is noop because it doesn't compare the
 connector `AND != OR`. The following patch should address that.

 {{{#!diff
 diff --git a/django/utils/tree.py b/django/utils/tree.py
 index 302cd37d5f..f8d3e3586a 100644
 --- a/django/utils/tree.py
 +++ b/django/utils/tree.py
 @@ -90,7 +90,7 @@ def add(self, data, conn_type, squash=True):
          If `squash` is False the data is prepared and added as a child to
          this tree without further logic.
          """
 -        if data in self.children:
 +        if (self.connector == conn_type or len(self) == 1) and data in
 self.children:
              return data
          if not squash:
              self.children.append(data)
 }}}

 The reason why this is not an issue for most cases though is that the only
 way to craft a query with a root `Where` node with an `OR` connector is
 through a `|` combination of query like described here. That explains why
 queries of the form `filter(Q(foo="bar") |
 Q(baz="foo")).filter(foo="bar")` are not affected by this `Node.add` bug
 and resulting in a large number of failures in the test suite.

 I personally think that we should prevent `Query.combine` from ever
 generating queries with root `Where(connector='OR')` as I wouldn't be
 surprised if it caused other subtle issues down the line given the poor
 coverage we have for queryset combinations. If that makes sense to you
 I'll prepare a patch with two commits, one for the `Node.add` adjustments
 and a following one with the `Query.combine` proposed adjustments meant to
 be backported.

 I also think that we should just nuke the `if data in self.children`
 entirely in the main branch as I've expressed in #32632 as it's wasteful
 99% of the time and I'm willing to shepherd an optimization ticket if
 that's deemed appropriate.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32717#comment:4>
Django <https://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 unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/070.a5bc8d0e914d432eadc090dce4e399ce%40djangoproject.com.

Reply via email to