Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #17877 -- Ensured that extra WHERE clauses get correctly ANDed …

…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...
commit 93d1fdb1304ed5b2e5ea2e0f1e84db7fff5eb7fa 1 parent 5c53e30
Julien Phalip authored April 09, 2012
1  AUTHORS
@@ -326,6 +326,7 @@ answer newbie questions, and generally made Django that much better:
326 326
     lcordier@point45.com
327 327
     Jeong-Min Lee <falsetru@gmail.com>
328 328
     Tai Lee <real.human@mrmachine.net>
  329
+    Adrien Lemaire <lemaire.adrien@gmail.com>
329 330
     Christopher Lenz <http://www.cmlenz.net/>
330 331
     lerouxb@gmail.com
331 332
     Piotr Lewandowski <piotr.lewandowski@gmail.com>
3  django/db/models/sql/where.py
@@ -281,7 +281,8 @@ def __init__(self, sqls, params):
281 281
         self.params = params
282 282
 
283 283
     def as_sql(self, qn=None, connection=None):
284  
-        return " AND ".join(self.sqls), tuple(self.params or ())
  284
+        sqls = ["(%s)" % sql for sql in self.sqls]
  285
+        return " AND ".join(sqls), tuple(self.params or ())
285 286
 
286 287
 class Constraint(object):
287 288
     """
4  docs/ref/models/querysets.txt
@@ -968,11 +968,11 @@ of the arguments is required, but you should use at least one of them.
968 968
 
969 969
   Example::
970 970
 
971  
-      Entry.objects.extra(where=['id IN (3, 4, 5, 20)'])
  971
+      Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
972 972
 
973 973
   ...translates (roughly) into the following SQL::
974 974
 
975  
-      SELECT * FROM blog_entry WHERE id IN (3, 4, 5, 20);
  975
+      SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')
976 976
 
977 977
   Be careful when using the ``tables`` parameter if you're specifying
978 978
   tables that are already used in the query. When you add extra tables
31  tests/regressiontests/extra_regress/tests.py
@@ -313,3 +313,34 @@ def test_regression_10847(self):
313 313
                TestObject.objects.extra(where=["id > %s"], params=[obj.pk]),
314 314
             ['<TestObject: TestObject: first,second,third>']
315 315
         )
  316
+
  317
+    def test_regression_17877(self):
  318
+        """
  319
+        Ensure that extra WHERE clauses get correctly ANDed, even when they
  320
+        contain OR operations.
  321
+        """
  322
+        # Test Case 1: should appear in queryset.
  323
+        t = TestObject(first='a', second='a', third='a')
  324
+        t.save()
  325
+        # Test Case 2: should appear in queryset.
  326
+        t = TestObject(first='b', second='a', third='a')
  327
+        t.save()
  328
+        # Test Case 3: should not appear in queryset, bug case.
  329
+        t = TestObject(first='a', second='a', third='b')
  330
+        t.save()
  331
+        # Test Case 4: should not appear in queryset.
  332
+        t = TestObject(first='b', second='a', third='b')
  333
+        t.save()
  334
+        # Test Case 5: should not appear in queryset.
  335
+        t = TestObject(first='b', second='b', third='a')
  336
+        t.save()
  337
+        # Test Case 6: should not appear in queryset, bug case.
  338
+        t = TestObject(first='a', second='b', third='b')
  339
+        t.save()
  340
+
  341
+        self.assertQuerysetEqual(
  342
+            TestObject.objects.extra(
  343
+                where=["first = 'a' OR second = 'a'", "third = 'a'"],
  344
+            ),
  345
+            ['<TestObject: TestObject: a,a,a>', '<TestObject: TestObject: b,a,a>']
  346
+        )

0 notes on commit 93d1fdb

Please sign in to comment.
Something went wrong with that request. Please try again.