Permalink
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...
1 parent 1fde37a commit 907bdeec823c01bc5284f7bda53a471154ce63e7 @acdha acdha committed Nov 25, 2012
Showing with 28 additions and 1 deletion.
  1. +1 −0 AUTHORS
  2. +1 −1 haystack/backends/__init__.py
  3. +26 −0 tests/core/tests/query.py
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):

0 comments on commit 907bdee

Please sign in to comment.