Django

Code

Ticket #4289 (closed: fixed)

Opened 1 year ago

Last modified 3 weeks ago

Misbehaving Q objects

Reported by: Ben Khoo Assigned to: nobody
Component: Database wrapper Version: SVN
Keywords: Q Oracle sqlite OR qs-rf-fixed Cc: mir@noris.de
Triage Stage: Accepted Has patch: 0
Needs documentation: 0 Needs tests: 0
Patch needs improvement: 0

Description (Last modified by bouldersprinters)

Hi,

The following ticket will try to highlight a problem that I have found when using the 'OR' operator on Q objects in the boulder-oracle-sprint branch.

My model looks like this.

class Test(models.Model):
    num = models.IntegerField()

    def __str__(self):
        return 'num=%d'%self.num

The following code will highlight the bug:

In [1]: from testapp.models import *

In [2]: from django.db.models import Q

In [3]: for i in [4,8,12]:
   ...:         Test(num=i).save()
   ...:

In [4]: Test.objects.filter(num__lt=4)
Out[4]: []

In [5]: Test.objects.filter(num__gt=8, num__lt=12)
Out[5]: []

In [6]: Test.objects.filter(Q(num__lt = 4) | Q(num__gt=8, num__lt=12))
Out[6]: [<Test: num=12>, <Test: num=4>, <Test: num=8>]

In [7]: Test.objects.filter(Q(num__gt=8, num__lt=12) | Q(num__lt = 4))
Out[7]: [<Test: num=12>, <Test: num=4>, <Test: num=8>]

In [8]: Test.objects.filter(Q(num__gt=8) & Q(num__lt=12) | Q(num__lt = 4))
Out[8]: []

Lines 6 and 7 illustrate the bug. The query appears to indicate that there are three Test objects where 'num' is less than 4 or, greater than 8 and less than 12. Lines 4 and 5 show that no such object should exist. Line 8 shows how I would expect the query to run.

The following is the formated (but otherwise unmodified) SQL query produced by django.

SELECT * 
FROM "TESTAPP_TEST"
WHERE (("TESTAPP_TEST"."NUM" < 4 OR 
        "TESTAPP_TEST"."NUM" > 8 OR 
        "TESTAPP_TEST"."NUM" < 12))

The issue is that the second 'OR' operator should be an AND operator. Also for the sake of safety/sanity I feel that queries specified within the Q objects should also be surrounded by a bracket.

The corrected query should read

SELECT * 
FROM "TESTAPP_TEST"
WHERE ((("TESTAPP_TEST"."NUM" < 4) OR 
        ("TESTAPP_TEST"."NUM" > 8 AND
         "TESTAPP_TEST"."NUM" < 12)))

Regards Ben

Attachments

Change History

(follow-up: ↓ 3 ) 05/14/07 02:07:45 changed by mtredinnick

  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

This is almost certainly the same problem we have with some Q() constructions on trunk as well and is one of the motivations behind refactoring the QuerySet class.

05/14/07 04:50:15 changed by anonymous

  • cc set to mir@noris.de.

(in reply to: ↑ 1 ) 05/14/07 11:07:19 changed by anonymous

Replying to mtredinnick:

This is almost certainly the same problem we have with some Q() constructions on trunk as well and is one of the motivations behind refactoring the QuerySet class.

Confirmed. I tried this against the sqlite3 backend in the trunk and got the same results.

05/31/07 13:57:21 changed by bouldersprinters

  • keywords changed from Q Oracle OR to Q Oracle sqlite OR.
  • owner changed from jacob to adrian.
  • version changed from other branch to SVN.
  • component changed from Uncategorized to Database wrapper.
  • description changed.

09/14/07 14:12:46 changed by mboersma

I retested trunk during the "worldwide sprint," and the same behavior persists against Oracle and sqlite3 backends, just FYI.

12/01/07 16:02:51 changed by ikelly

  • keywords changed from Q Oracle sqlite OR to Q Oracle sqlite OR qs-rf.

12/01/07 16:05:54 changed by mtredinnick

  • summary changed from Misbehaving Q objects in boulder-oracle-sprint branch to Misbehaving Q objects.
  • stage changed from Unreviewed to Accepted.

12/09/07 02:01:27 changed by mtredinnick

(In [6901]) queryset-refactor: Added a test to show that various Q() combinations work when the same field with different lookup types are combined. Refs #4289.

12/09/07 02:02:56 changed by mtredinnick

  • keywords changed from Q Oracle sqlite OR qs-rf to Q Oracle sqlite OR qs-rf-fixed.

04/26/08 21:50:16 changed by mtredinnick

  • status changed from new to closed.
  • resolution set to fixed.

(In [7477]) Merged the queryset-refactor branch into trunk.

This is a big internal change, but mostly backwards compatible with existing code. Also adds a couple of new features.

Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658


Add/Change #4289 (Misbehaving Q objects)




Change Properties
Action