Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix combination logic for complex queries

Previously combining querysets which used a mix of logical AND and OR operations
behaved unexpectedly.

Thanks to @mjl for the patch and tests in SHA: 9192dbd

Closes #613, #617
  • Loading branch information...
commit 907bdeec823c01bc5284f7bda53a471154ce63e7 1 parent 1fde37a
@acdha acdha authored
View
1  AUTHORS
@@ -65,3 +65,4 @@ Thanks to
* Dan Helfman (witten) for a patch related to highlighting.
* Matt DeBoard for refactor of ``SolrSearchBackend.search`` method to allow simpler extension of the class.
* Rodrigo Guzman (rz) for a fix to query handling in the ``simple`` backend.
+ * Martin J. Laubach (mjl) for fixing the logic used when combining querysets
View
2  haystack/backends/__init__.py
@@ -599,7 +599,7 @@ def add_filter(self, query_filter, use_or=False):
else:
connector = SQ.AND
- if self.query_filter and query_filter.connector != SQ.AND and len(query_filter) > 1:
+ if self.query_filter and query_filter.connector != connector and len(query_filter) > 1:
self.query_filter.start_subtree(connector)
subtree = True
else:
View
26 tests/core/tests/query.py
@@ -726,6 +726,32 @@ def test___or__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
+ def test_and_or(self):
+ """
+ Combining AND queries with OR should give
+ AND(OR(a, b), OR(c, d))
+ """
+ sqs1 = self.msqs.filter(content='foo').filter(content='oof')
+ sqs2 = self.msqs.filter(content='bar').filter(content='rab')
+ sqs = sqs1 | sqs2
+
+ self.assertEqual(sqs.query.query_filter.connector, 'OR')
+ self.assertEqual(repr(sqs.query.query_filter.children[0]), repr(sqs1.query.query_filter))
+ self.assertEqual(repr(sqs.query.query_filter.children[1]), repr(sqs2.query.query_filter))
+
+ def test_or_and(self):
+ """
+ Combining OR queries with AND should give
+ OR(AND(a, b), AND(c, d))
+ """
+ sqs1 = self.msqs.filter(content='foo').filter_or(content='oof')
+ sqs2 = self.msqs.filter(content='bar').filter_or(content='rab')
+ sqs = sqs1 & sqs2
+
+ self.assertEqual(sqs.query.query_filter.connector, 'AND')
+ self.assertEqual(repr(sqs.query.query_filter.children[0]), repr(sqs1.query.query_filter))
+ self.assertEqual(repr(sqs.query.query_filter.children[1]), repr(sqs2.query.query_filter))
+
class ValuesQuerySetTestCase(SearchQuerySetTestCase):
def test_values_sqs(self):
Please sign in to comment.
Something went wrong with that request. Please try again.