Skip to content

Commit

Permalink
Fixed #17877 -- Ensured that extra WHERE clauses get correctly ANDed …
Browse files Browse the repository at this point in the history
…when they contain OR operations. Thanks to Marek Brzóska for the report, to eleather for the test case and to Adrien Lemaire for the patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17880 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jphalip committed Apr 9, 2012
1 parent 5c53e30 commit 93d1fdb
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 3 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -326,6 +326,7 @@ answer newbie questions, and generally made Django that much better:
lcordier@point45.com lcordier@point45.com
Jeong-Min Lee <falsetru@gmail.com> Jeong-Min Lee <falsetru@gmail.com>
Tai Lee <real.human@mrmachine.net> Tai Lee <real.human@mrmachine.net>
Adrien Lemaire <lemaire.adrien@gmail.com>
Christopher Lenz <http://www.cmlenz.net/> Christopher Lenz <http://www.cmlenz.net/>
lerouxb@gmail.com lerouxb@gmail.com
Piotr Lewandowski <piotr.lewandowski@gmail.com> Piotr Lewandowski <piotr.lewandowski@gmail.com>
Expand Down
3 changes: 2 additions & 1 deletion django/db/models/sql/where.py
Expand Up @@ -281,7 +281,8 @@ def __init__(self, sqls, params):
self.params = params self.params = params


def as_sql(self, qn=None, connection=None): def as_sql(self, qn=None, connection=None):
return " AND ".join(self.sqls), tuple(self.params or ()) sqls = ["(%s)" % sql for sql in self.sqls]
return " AND ".join(sqls), tuple(self.params or ())


class Constraint(object): class Constraint(object):
""" """
Expand Down
4 changes: 2 additions & 2 deletions docs/ref/models/querysets.txt
Expand Up @@ -968,11 +968,11 @@ of the arguments is required, but you should use at least one of them.


Example:: Example::


Entry.objects.extra(where=['id IN (3, 4, 5, 20)']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])


...translates (roughly) into the following SQL:: ...translates (roughly) into the following SQL::


SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20); SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')


Be careful when using the ``tables`` parameter if you're specifying Be careful when using the ``tables`` parameter if you're specifying
tables that are already used in the query. When you add extra tables tables that are already used in the query. When you add extra tables
Expand Down
31 changes: 31 additions & 0 deletions tests/regressiontests/extra_regress/tests.py
Expand Up @@ -313,3 +313,34 @@ def test_regression_10847(self):
TestObject.objects.extra(where=["id > %s"], params=[obj.pk]), TestObject.objects.extra(where=["id > %s"], params=[obj.pk]),
['<TestObject: TestObject: first,second,third>'] ['<TestObject: TestObject: first,second,third>']
) )

def test_regression_17877(self):
"""
Ensure that extra WHERE clauses get correctly ANDed, even when they
contain OR operations.
"""
# Test Case 1: should appear in queryset.
t = TestObject(first='a', second='a', third='a')
t.save()
# Test Case 2: should appear in queryset.
t = TestObject(first='b', second='a', third='a')
t.save()
# Test Case 3: should not appear in queryset, bug case.
t = TestObject(first='a', second='a', third='b')
t.save()
# Test Case 4: should not appear in queryset.
t = TestObject(first='b', second='a', third='b')
t.save()
# Test Case 5: should not appear in queryset.
t = TestObject(first='b', second='b', third='a')
t.save()
# Test Case 6: should not appear in queryset, bug case.
t = TestObject(first='a', second='b', third='b')
t.save()

self.assertQuerysetEqual(
TestObject.objects.extra(
where=["first = 'a' OR second = 'a'", "third = 'a'"],
),
['<TestObject: TestObject: a,a,a>', '<TestObject: TestObject: b,a,a>']
)

0 comments on commit 93d1fdb

Please sign in to comment.