﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
4289	Misbehaving Q objects in boulder-oracle-sprint branch	Ben Khoo	Adrian Holovaty	"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
[[BR]]
"		new	Database wrapper	SVN			Q Oracle sqlite OR	mir@…	Unreviewed	0	0	0	0	0	0
