Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed a bug with query construction. Thanks to dstufft for the report!

This goes back to erroring on the side of too many parens, where there weren't enough before. The engines will no-op them when they're not important.
  • Loading branch information...
commit 50eb733f885f482b5fa584fbe99824293f183369 1 parent ea5dbd5
Daniel Lindsley toastdriven authored
3  haystack/backends/elasticsearch_backend.py
View
@@ -726,6 +726,9 @@ def build_query_fragment(self, field, filter_type, value):
query_frag = filter_types[filter_type] % prepared_value
+ if len(query_frag) and not query_frag.startswith('(') and not query_frag.endswith(')'):
+ query_frag = "(%s)" % query_frag
+
return u"%s%s" % (index_fieldname, query_frag)
def build_alt_parser_query(self, parser_name, query_string='', **kwargs):
3  haystack/backends/solr_backend.py
View
@@ -580,6 +580,9 @@ def build_query_fragment(self, field, filter_type, value):
query_frag = filter_types[filter_type] % prepared_value
+ if len(query_frag) and not query_frag.startswith('(') and not query_frag.endswith(')'):
+ query_frag = "(%s)" % query_frag
+
return u"%s%s" % (index_fieldname, query_frag)
def build_alt_parser_query(self, parser_name, query_string='', **kwargs):
3  haystack/backends/whoosh_backend.py
View
@@ -848,6 +848,9 @@ def build_query_fragment(self, field, filter_type, value):
query_frag = filter_types[filter_type] % prepared_value
+ if len(query_frag) and not query_frag.startswith('(') and not query_frag.endswith(')'):
+ query_frag = "(%s)" % query_frag
+
return u"%s%s" % (index_fieldname, query_frag)
49 tests/elasticsearch_tests/tests/elasticsearch_backend.py
View
@@ -8,6 +8,7 @@
from django.test import TestCase
from haystack import connections, connection_router, reset_search_queries
from haystack import indexes
+from haystack.inputs import AutoQuery
from haystack.models import SearchResult
from haystack.query import SearchQuerySet, RelatedSearchQuerySet, SQ
from haystack.utils.loading import UnifiedIndex
@@ -536,7 +537,7 @@ def test_log_query(self):
self.sq.add_filter(SQ(name='bar'))
len(self.sq.get_results())
self.assertEqual(len(connections['default'].queries), 1)
- self.assertEqual(connections['default'].queries[0]['query_string'], 'name:bar')
+ self.assertEqual(connections['default'].queries[0]['query_string'], 'name:(bar)')
# And again, for good measure.
self.sq = connections['default'].query()
@@ -544,8 +545,8 @@ def test_log_query(self):
self.sq.add_filter(SQ(text='moof'))
len(self.sq.get_results())
self.assertEqual(len(connections['default'].queries), 2)
- self.assertEqual(connections['default'].queries[0]['query_string'], 'name:bar')
- self.assertEqual(connections['default'].queries[1]['query_string'], u'(name:bar AND text:moof)')
+ self.assertEqual(connections['default'].queries[0]['query_string'], 'name:(bar)')
+ self.assertEqual(connections['default'].queries[1]['query_string'], u'(name:(bar) AND text:(moof))')
# Restore.
settings.DEBUG = old_debug
@@ -668,7 +669,7 @@ def test___and__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
- self.assertEqual(sqs.query.build_query(), u'(foo AND bar)')
+ self.assertEqual(sqs.query.build_query(), u'((foo) AND (bar))')
# Now for something more complex...
sqs3 = self.sqs.exclude(title='moof').filter(SQ(content='foo') | SQ(content='baz'))
@@ -677,7 +678,7 @@ def test___and__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 3)
- self.assertEqual(sqs.query.build_query(), u'(NOT (title:moof) AND (foo OR baz) AND bar)')
+ self.assertEqual(sqs.query.build_query(), u'(NOT (title:(moof)) AND ((foo) OR (baz)) AND (bar))')
def test___or__(self):
sqs1 = self.sqs.filter(content='foo')
@@ -686,7 +687,7 @@ def test___or__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
- self.assertEqual(sqs.query.build_query(), u'(foo OR bar)')
+ self.assertEqual(sqs.query.build_query(), u'((foo) OR (bar))')
# Now for something more complex...
sqs3 = self.sqs.exclude(title='moof').filter(SQ(content='foo') | SQ(content='baz'))
@@ -695,7 +696,7 @@ def test___or__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
- self.assertEqual(sqs.query.build_query(), u'((NOT (title:moof) AND (foo OR baz)) OR bar)')
+ self.assertEqual(sqs.query.build_query(), u'((NOT (title:(moof)) AND ((foo) OR (baz))) OR (bar))')
def test_auto_query(self):
# Ensure bits in exact matches get escaped properly as well.
@@ -703,7 +704,7 @@ def test_auto_query(self):
sqs = self.sqs.auto_query('"pants:rule"')
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(repr(sqs.query.query_filter), '<SQ: AND content__contains="pants:rule">')
- self.assertEqual(sqs.query.build_query(), u'"pants\\:rule"')
+ self.assertEqual(sqs.query.build_query(), u'("pants\\:rule")')
self.assertEqual(len(sqs), 0)
# Regressions
@@ -817,50 +818,54 @@ def test_related_cache_is_full(self):
def test_quotes_regression(self):
sqs = self.sqs.auto_query(u"44°48'40''N 20°28'32''E")
# Should not have empty terms.
- self.assertEqual(sqs.query.build_query(), u"44\xb048'40''N 20\xb028'32''E")
+ self.assertEqual(sqs.query.build_query(), u"(44\xb048'40''N 20\xb028'32''E)")
# Should not cause Elasticsearch to 500.
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('blazing')
- self.assertEqual(sqs.query.build_query(), u'blazing')
+ self.assertEqual(sqs.query.build_query(), u'(blazing)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('blazing saddles')
- self.assertEqual(sqs.query.build_query(), u'blazing saddles')
+ self.assertEqual(sqs.query.build_query(), u'(blazing saddles)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles')
- self.assertEqual(sqs.query.build_query(), u'\\"blazing saddles')
+ self.assertEqual(sqs.query.build_query(), u'(\\"blazing saddles)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles"')
- self.assertEqual(sqs.query.build_query(), u'"blazing saddles"')
+ self.assertEqual(sqs.query.build_query(), u'("blazing saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing saddles"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'saddles"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'saddles"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'\'saddles"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'\'saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'\'saddles"\'')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles" \'')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'\'saddles" \')')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'\'saddles"\'"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles" \'\\"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'\'saddles" \'\\")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles" mel')
- self.assertEqual(sqs.query.build_query(), u'"blazing saddles" mel')
+ self.assertEqual(sqs.query.build_query(), u'("blazing saddles" mel)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles" mel brooks')
- self.assertEqual(sqs.query.build_query(), u'"blazing saddles" mel brooks')
+ self.assertEqual(sqs.query.build_query(), u'("blazing saddles" mel brooks)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing saddles" brooks')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles" brooks')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing saddles" brooks)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing saddles" "brooks')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles" \\"brooks')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing saddles" \\"brooks)')
self.assertEqual(sqs.count(), 0)
+ def test_query_generation(self):
+ sqs = self.sqs.filter(SQ(content=AutoQuery("hello world")) | SQ(title=AutoQuery("hello world")))
+ self.assertEqual(sqs.query.build_query(), u"((hello world) OR title:(hello world))")
+
def test_result_class(self):
# Assert that we're defaulting to ``SearchResult``.
sqs = self.sqs.all()
36 tests/elasticsearch_tests/tests/elasticsearch_query.py
View
@@ -17,48 +17,48 @@ def test_build_query_all(self):
def test_build_query_single_word(self):
self.sq.add_filter(SQ(content='hello'))
- self.assertEqual(self.sq.build_query(), 'hello')
+ self.assertEqual(self.sq.build_query(), '(hello)')
def test_build_query_boolean(self):
self.sq.add_filter(SQ(content=True))
- self.assertEqual(self.sq.build_query(), 'True')
+ self.assertEqual(self.sq.build_query(), '(True)')
def test_build_query_datetime(self):
self.sq.add_filter(SQ(content=datetime.datetime(2009, 5, 8, 11, 28)))
- self.assertEqual(self.sq.build_query(), '2009-05-08T11:28:00')
+ self.assertEqual(self.sq.build_query(), '(2009-05-08T11:28:00)')
def test_build_query_multiple_words_and(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_filter(SQ(content='world'))
- self.assertEqual(self.sq.build_query(), '(hello AND world)')
+ self.assertEqual(self.sq.build_query(), '((hello) AND (world))')
def test_build_query_multiple_words_not(self):
self.sq.add_filter(~SQ(content='hello'))
self.sq.add_filter(~SQ(content='world'))
- self.assertEqual(self.sq.build_query(), '(NOT (hello) AND NOT (world))')
+ self.assertEqual(self.sq.build_query(), '(NOT ((hello)) AND NOT ((world)))')
def test_build_query_multiple_words_or(self):
self.sq.add_filter(~SQ(content='hello'))
self.sq.add_filter(SQ(content='hello'), use_or=True)
- self.assertEqual(self.sq.build_query(), '(NOT (hello) OR hello)')
+ self.assertEqual(self.sq.build_query(), '(NOT ((hello)) OR (hello))')
def test_build_query_multiple_words_mixed(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(content='hello'), use_or=True)
self.sq.add_filter(~SQ(content='world'))
- self.assertEqual(self.sq.build_query(), u'((why OR hello) AND NOT (world))')
+ self.assertEqual(self.sq.build_query(), u'(((why) OR (hello)) AND NOT ((world)))')
def test_build_query_phrase(self):
self.sq.add_filter(SQ(content='hello world'))
self.assertEqual(self.sq.build_query(), '(hello AND world)')
self.sq.add_filter(SQ(content__exact='hello world'))
- self.assertEqual(self.sq.build_query(), u'((hello AND world) AND "hello world")')
+ self.assertEqual(self.sq.build_query(), u'((hello AND world) AND ("hello world"))')
def test_build_query_boost(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_boost('world', 5)
- self.assertEqual(self.sq.build_query(), "hello world^5")
+ self.assertEqual(self.sq.build_query(), "(hello) world^5")
def test_build_query_multiple_filter_types(self):
self.sq.add_filter(SQ(content='why'))
@@ -68,7 +68,7 @@ def test_build_query_multiple_filter_types(self):
self.sq.add_filter(SQ(title__gte='B'))
self.sq.add_filter(SQ(id__in=[1, 2, 3]))
self.sq.add_filter(SQ(rating__range=[3, 5]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:[* TO "2009-02-10 01:59:00"] AND author:{"daniel" TO *} AND created:{* TO "2009-02-12 12:13:00"} AND title:["B" TO *] AND id:("1" OR "2" OR "3") AND rating:["3" TO "5"])')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:([* TO "2009-02-10 01:59:00"]) AND author:({"daniel" TO *}) AND created:({* TO "2009-02-12 12:13:00"}) AND title:(["B" TO *]) AND id:("1" OR "2" OR "3") AND rating:(["3" TO "5"]))')
def test_build_query_multiple_filter_types_with_datetimes(self):
self.sq.add_filter(SQ(content='why'))
@@ -78,27 +78,27 @@ def test_build_query_multiple_filter_types_with_datetimes(self):
self.sq.add_filter(SQ(title__gte='B'))
self.sq.add_filter(SQ(id__in=[1, 2, 3]))
self.sq.add_filter(SQ(rating__range=[3, 5]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:[* TO "2009-02-10T01:59:00"] AND author:{"daniel" TO *} AND created:{* TO "2009-02-12T12:13:00"} AND title:["B" TO *] AND id:("1" OR "2" OR "3") AND rating:["3" TO "5"])')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:([* TO "2009-02-10T01:59:00"]) AND author:({"daniel" TO *}) AND created:({* TO "2009-02-12T12:13:00"}) AND title:(["B" TO *]) AND id:("1" OR "2" OR "3") AND rating:(["3" TO "5"]))')
def test_build_query_in_filter_multiple_words(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=["A Famous Paper", "An Infamous Article"]))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("A Famous Paper" OR "An Infamous Article"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("A Famous Paper" OR "An Infamous Article"))')
def test_build_query_in_filter_datetime(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(pub_date__in=[datetime.datetime(2009, 7, 6, 1, 56, 21)]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:("2009-07-06T01:56:21"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:("2009-07-06T01:56:21"))')
def test_build_query_in_with_set(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=set(["A Famous Paper", "An Infamous Article"])))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("A Famous Paper" OR "An Infamous Article"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("A Famous Paper" OR "An Infamous Article"))')
def test_build_query_wildcard_filter_types(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__startswith='haystack'))
- self.assertEqual(self.sq.build_query(), u'(why AND title:haystack*)')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:(haystack*))')
def test_clean(self):
self.assertEqual(self.sq.clean('hello world'), 'hello world')
@@ -109,10 +109,10 @@ def test_clean(self):
def test_build_query_with_models(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_model(MockModel)
- self.assertEqual(self.sq.build_query(), 'hello')
+ self.assertEqual(self.sq.build_query(), '(hello)')
self.sq.add_model(AnotherMockModel)
- self.assertEqual(self.sq.build_query(), u'hello')
+ self.assertEqual(self.sq.build_query(), u'(hello)')
def test_set_result_class(self):
# Assert that we're defaulting to ``SearchResult``.
@@ -132,4 +132,4 @@ class IttyBittyResult(object):
def test_in_filter_values_list(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=MockModel.objects.values_list('id', flat=True)))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("1" OR "2" OR "3"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("1" OR "2" OR "3"))')
4 tests/overrides/tests/altered_internal_names.py
View
@@ -36,10 +36,10 @@ def test_altered_names(self):
sq.add_filter(SQ(content='hello'))
sq.add_model(MockModel)
- self.assertEqual(sq.build_query(), u'hello')
+ self.assertEqual(sq.build_query(), u'(hello)')
sq.add_model(AnotherMockModel)
- self.assertEqual(sq.build_query(), u'hello')
+ self.assertEqual(sq.build_query(), u'(hello)')
def test_solr_schema(self):
command = Command()
53 tests/solr_tests/tests/solr_backend.py
View
@@ -9,6 +9,7 @@
from django.test import TestCase
from haystack import connections, connection_router, reset_search_queries
from haystack import indexes
+from haystack.inputs import AutoQuery
from haystack.models import SearchResult
from haystack.query import SearchQuerySet, RelatedSearchQuerySet, SQ
from haystack.utils.loading import UnifiedIndex
@@ -613,8 +614,8 @@ def tearDown(self):
def test_get_spelling(self):
self.sq.add_filter(SQ(content='Indexy'))
- self.assertEqual(self.sq.get_spelling_suggestion(), u'index')
- self.assertEqual(self.sq.get_spelling_suggestion('indexy'), u'index')
+ self.assertEqual(self.sq.get_spelling_suggestion(), u'(index)')
+ self.assertEqual(self.sq.get_spelling_suggestion('indexy'), u'(index)')
def test_log_query(self):
from django.conf import settings
@@ -634,7 +635,7 @@ def test_log_query(self):
self.sq.add_filter(SQ(name='bar'))
len(self.sq.get_results())
self.assertEqual(len(connections['default'].queries), 1)
- self.assertEqual(connections['default'].queries[0]['query_string'], 'name:bar')
+ self.assertEqual(connections['default'].queries[0]['query_string'], 'name:(bar)')
# And again, for good measure.
self.sq = connections['default'].query()
@@ -642,8 +643,8 @@ def test_log_query(self):
self.sq.add_filter(SQ(text='moof'))
len(self.sq.get_results())
self.assertEqual(len(connections['default'].queries), 2)
- self.assertEqual(connections['default'].queries[0]['query_string'], 'name:bar')
- self.assertEqual(connections['default'].queries[1]['query_string'], u'(name:bar AND text:moof)')
+ self.assertEqual(connections['default'].queries[0]['query_string'], 'name:(bar)')
+ self.assertEqual(connections['default'].queries[1]['query_string'], u'(name:(bar) AND text:(moof))')
# Restore.
settings.DEBUG = old_debug
@@ -766,7 +767,7 @@ def test___and__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
- self.assertEqual(sqs.query.build_query(), u'(foo AND bar)')
+ self.assertEqual(sqs.query.build_query(), u'((foo) AND (bar))')
# Now for something more complex...
sqs3 = self.sqs.exclude(title='moof').filter(SQ(content='foo') | SQ(content='baz'))
@@ -775,7 +776,7 @@ def test___and__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 3)
- self.assertEqual(sqs.query.build_query(), u'(NOT (title:moof) AND (foo OR baz) AND bar)')
+ self.assertEqual(sqs.query.build_query(), u'(NOT (title:(moof)) AND ((foo) OR (baz)) AND (bar))')
def test___or__(self):
sqs1 = self.sqs.filter(content='foo')
@@ -784,7 +785,7 @@ def test___or__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
- self.assertEqual(sqs.query.build_query(), u'(foo OR bar)')
+ self.assertEqual(sqs.query.build_query(), u'((foo) OR (bar))')
# Now for something more complex...
sqs3 = self.sqs.exclude(title='moof').filter(SQ(content='foo') | SQ(content='baz'))
@@ -793,7 +794,7 @@ def test___or__(self):
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(len(sqs.query.query_filter), 2)
- self.assertEqual(sqs.query.build_query(), u'((NOT (title:moof) AND (foo OR baz)) OR bar)')
+ self.assertEqual(sqs.query.build_query(), u'((NOT (title:(moof)) AND ((foo) OR (baz))) OR (bar))')
def test_auto_query(self):
# Ensure bits in exact matches get escaped properly as well.
@@ -801,7 +802,7 @@ def test_auto_query(self):
sqs = self.sqs.auto_query('"pants:rule"')
self.assertTrue(isinstance(sqs, SearchQuerySet))
self.assertEqual(repr(sqs.query.query_filter), '<SQ: AND content__contains="pants:rule">')
- self.assertEqual(sqs.query.build_query(), u'"pants\\:rule"')
+ self.assertEqual(sqs.query.build_query(), u'("pants\\:rule")')
self.assertEqual(len(sqs), 0)
# Regressions
@@ -915,50 +916,54 @@ def test_related_cache_is_full(self):
def test_quotes_regression(self):
sqs = self.sqs.auto_query(u"44°48'40''N 20°28'32''E")
# Should not have empty terms.
- self.assertEqual(sqs.query.build_query(), u"44\xb048'40''N 20\xb028'32''E")
+ self.assertEqual(sqs.query.build_query(), u"(44\xb048'40''N 20\xb028'32''E)")
# Should not cause Solr to 500.
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('blazing')
- self.assertEqual(sqs.query.build_query(), u'blazing')
+ self.assertEqual(sqs.query.build_query(), u'(blazing)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('blazing saddles')
- self.assertEqual(sqs.query.build_query(), u'blazing saddles')
+ self.assertEqual(sqs.query.build_query(), u'(blazing saddles)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles')
- self.assertEqual(sqs.query.build_query(), u'\\"blazing saddles')
+ self.assertEqual(sqs.query.build_query(), u'(\\"blazing saddles)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles"')
- self.assertEqual(sqs.query.build_query(), u'"blazing saddles"')
+ self.assertEqual(sqs.query.build_query(), u'("blazing saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing saddles"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'saddles"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'saddles"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'\'saddles"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'\'saddles")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'\'saddles"\'')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles" \'')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'\'saddles" \')')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing \'\'saddles"\'"')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing \'\'saddles" \'\\"')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing \'\'saddles" \'\\")')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles" mel')
- self.assertEqual(sqs.query.build_query(), u'"blazing saddles" mel')
+ self.assertEqual(sqs.query.build_query(), u'("blazing saddles" mel)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('"blazing saddles" mel brooks')
- self.assertEqual(sqs.query.build_query(), u'"blazing saddles" mel brooks')
+ self.assertEqual(sqs.query.build_query(), u'("blazing saddles" mel brooks)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing saddles" brooks')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles" brooks')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing saddles" brooks)')
self.assertEqual(sqs.count(), 0)
sqs = self.sqs.auto_query('mel "blazing saddles" "brooks')
- self.assertEqual(sqs.query.build_query(), u'mel "blazing saddles" \\"brooks')
+ self.assertEqual(sqs.query.build_query(), u'(mel "blazing saddles" \\"brooks)')
self.assertEqual(sqs.count(), 0)
+ def test_query_generation(self):
+ sqs = self.sqs.filter(SQ(content=AutoQuery("hello world")) | SQ(title=AutoQuery("hello world")))
+ self.assertEqual(sqs.query.build_query(), u"((hello world) OR title:(hello world))")
+
def test_result_class(self):
# Assert that we're defaulting to ``SearchResult``.
sqs = self.sqs.all()
38 tests/solr_tests/tests/solr_query.py
View
@@ -17,52 +17,52 @@ def test_build_query_all(self):
def test_build_query_single_word(self):
self.sq.add_filter(SQ(content='hello'))
- self.assertEqual(self.sq.build_query(), 'hello')
+ self.assertEqual(self.sq.build_query(), '(hello)')
def test_build_query_boolean(self):
self.sq.add_filter(SQ(content=True))
- self.assertEqual(self.sq.build_query(), 'true')
+ self.assertEqual(self.sq.build_query(), '(true)')
def test_build_query_datetime(self):
self.sq.add_filter(SQ(content=datetime.datetime(2009, 5, 8, 11, 28)))
- self.assertEqual(self.sq.build_query(), '2009-05-08T11:28:00Z')
+ self.assertEqual(self.sq.build_query(), '(2009-05-08T11:28:00Z)')
def test_build_query_multiple_words_and(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_filter(SQ(content='world'))
- self.assertEqual(self.sq.build_query(), '(hello AND world)')
+ self.assertEqual(self.sq.build_query(), '((hello) AND (world))')
def test_build_query_multiple_words_not(self):
self.sq.add_filter(~SQ(content='hello'))
self.sq.add_filter(~SQ(content='world'))
- self.assertEqual(self.sq.build_query(), '(NOT (hello) AND NOT (world))')
+ self.assertEqual(self.sq.build_query(), '(NOT ((hello)) AND NOT ((world)))')
def test_build_query_multiple_words_or(self):
self.sq.add_filter(~SQ(content='hello'))
self.sq.add_filter(SQ(content='hello'), use_or=True)
- self.assertEqual(self.sq.build_query(), '(NOT (hello) OR hello)')
+ self.assertEqual(self.sq.build_query(), '(NOT ((hello)) OR (hello))')
def test_build_query_multiple_words_mixed(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(content='hello'), use_or=True)
self.sq.add_filter(~SQ(content='world'))
- self.assertEqual(self.sq.build_query(), u'((why OR hello) AND NOT (world))')
+ self.assertEqual(self.sq.build_query(), u'(((why) OR (hello)) AND NOT ((world)))')
def test_build_query_phrase(self):
self.sq.add_filter(SQ(content='hello world'))
self.assertEqual(self.sq.build_query(), '(hello AND world)')
self.sq.add_filter(SQ(content__exact='hello world'))
- self.assertEqual(self.sq.build_query(), u'((hello AND world) AND "hello world")')
+ self.assertEqual(self.sq.build_query(), u'((hello AND world) AND ("hello world"))')
def test_build_query_boost(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_boost('world', 5)
- self.assertEqual(self.sq.build_query(), "hello world^5")
+ self.assertEqual(self.sq.build_query(), "(hello) world^5")
def test_correct_exact(self):
self.sq.add_filter(SQ(content=Exact('hello world')))
- self.assertEqual(self.sq.build_query(), '"hello world"')
+ self.assertEqual(self.sq.build_query(), '("hello world")')
def test_build_query_multiple_filter_types(self):
self.sq.add_filter(SQ(content='why'))
@@ -72,7 +72,7 @@ def test_build_query_multiple_filter_types(self):
self.sq.add_filter(SQ(title__gte='B'))
self.sq.add_filter(SQ(id__in=[1, 2, 3]))
self.sq.add_filter(SQ(rating__range=[3, 5]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:[* TO "2009-02-10 01:59:00"] AND author:{"daniel" TO *} AND created:{* TO "2009-02-12 12:13:00"} AND title:["B" TO *] AND id:("1" OR "2" OR "3") AND rating:["3" TO "5"])')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:([* TO "2009-02-10 01:59:00"]) AND author:({"daniel" TO *}) AND created:({* TO "2009-02-12 12:13:00"}) AND title:(["B" TO *]) AND id:("1" OR "2" OR "3") AND rating:(["3" TO "5"]))')
def test_build_query_multiple_filter_types_with_datetimes(self):
self.sq.add_filter(SQ(content='why'))
@@ -82,27 +82,27 @@ def test_build_query_multiple_filter_types_with_datetimes(self):
self.sq.add_filter(SQ(title__gte='B'))
self.sq.add_filter(SQ(id__in=[1, 2, 3]))
self.sq.add_filter(SQ(rating__range=[3, 5]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:[* TO "2009-02-10T01:59:00Z"] AND author:{"daniel" TO *} AND created:{* TO "2009-02-12T12:13:00Z"} AND title:["B" TO *] AND id:("1" OR "2" OR "3") AND rating:["3" TO "5"])')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:([* TO "2009-02-10T01:59:00Z"]) AND author:({"daniel" TO *}) AND created:({* TO "2009-02-12T12:13:00Z"}) AND title:(["B" TO *]) AND id:("1" OR "2" OR "3") AND rating:(["3" TO "5"]))')
def test_build_query_in_filter_multiple_words(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=["A Famous Paper", "An Infamous Article"]))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("A Famous Paper" OR "An Infamous Article"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("A Famous Paper" OR "An Infamous Article"))')
def test_build_query_in_filter_datetime(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(pub_date__in=[datetime.datetime(2009, 7, 6, 1, 56, 21)]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:("2009-07-06T01:56:21Z"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:("2009-07-06T01:56:21Z"))')
def test_build_query_in_with_set(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=set(["A Famous Paper", "An Infamous Article"])))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("A Famous Paper" OR "An Infamous Article"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("A Famous Paper" OR "An Infamous Article"))')
def test_build_query_wildcard_filter_types(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__startswith='haystack'))
- self.assertEqual(self.sq.build_query(), u'(why AND title:haystack*)')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:(haystack*))')
def test_clean(self):
self.assertEqual(self.sq.clean('hello world'), 'hello world')
@@ -113,10 +113,10 @@ def test_clean(self):
def test_build_query_with_models(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_model(MockModel)
- self.assertEqual(self.sq.build_query(), 'hello')
+ self.assertEqual(self.sq.build_query(), '(hello)')
self.sq.add_model(AnotherMockModel)
- self.assertEqual(self.sq.build_query(), u'hello')
+ self.assertEqual(self.sq.build_query(), u'(hello)')
def test_set_result_class(self):
# Assert that we're defaulting to ``SearchResult``.
@@ -136,4 +136,4 @@ class IttyBittyResult(object):
def test_in_filter_values_list(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=MockModel.objects.values_list('id', flat=True)))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("1" OR "2" OR "3"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("1" OR "2" OR "3"))')
27 tests/whoosh_tests/tests/whoosh_backend.py
View
@@ -9,6 +9,7 @@
from django.test import TestCase
from haystack import connections, connection_router, reset_search_queries
from haystack import indexes
+from haystack.inputs import AutoQuery
from haystack.models import SearchResult
from haystack.query import SearchQuerySet, SQ
from haystack.utils.loading import UnifiedIndex
@@ -550,7 +551,7 @@ def test_log_query(self):
self.sq.add_filter(SQ(name='bar'))
len(self.sq.get_results())
self.assertEqual(len(connections['default'].queries), 1)
- self.assertEqual(connections['default'].queries[0]['query_string'], 'name:bar')
+ self.assertEqual(connections['default'].queries[0]['query_string'], 'name:(bar)')
# And again, for good measure.
self.sq = connections['default'].get_query()
@@ -558,8 +559,8 @@ def test_log_query(self):
self.sq.add_filter(SQ(text='foo'))
len(self.sq.get_results())
self.assertEqual(len(connections['default'].queries), 2)
- self.assertEqual(connections['default'].queries[0]['query_string'], 'name:bar')
- self.assertEqual(connections['default'].queries[1]['query_string'], u'(name:baz AND text:foo)')
+ self.assertEqual(connections['default'].queries[0]['query_string'], 'name:(bar)')
+ self.assertEqual(connections['default'].queries[1]['query_string'], u'(name:(baz) AND text:(foo))')
# Restore.
settings.DEBUG = old_debug
@@ -614,35 +615,35 @@ def test_various_searchquerysets(self):
self.sb.update(self.wmmi, self.sample_objs)
sqs = self.sqs.filter(content='Index')
- self.assertEqual(sqs.query.build_query(), u'Index')
+ self.assertEqual(sqs.query.build_query(), u'(Index)')
self.assertEqual(len(sqs), 3)
sqs = self.sqs.auto_query('Indexed!')
- self.assertEqual(sqs.query.build_query(), u"'Indexed!'")
+ self.assertEqual(sqs.query.build_query(), u"('Indexed!')")
self.assertEqual(len(sqs), 3)
sqs = self.sqs.auto_query('Indexed!').filter(pub_date__lte=date(2009, 8, 31))
- self.assertEqual(sqs.query.build_query(), u"('Indexed!' AND pub_date:[to 20090831000000])")
+ self.assertEqual(sqs.query.build_query(), u"(('Indexed!') AND pub_date:([to 20090831000000]))")
self.assertEqual(len(sqs), 3)
sqs = self.sqs.auto_query('Indexed!').filter(pub_date__lte=date(2009, 2, 23))
- self.assertEqual(sqs.query.build_query(), u"('Indexed!' AND pub_date:[to 20090223000000])")
+ self.assertEqual(sqs.query.build_query(), u"(('Indexed!') AND pub_date:([to 20090223000000]))")
self.assertEqual(len(sqs), 2)
sqs = self.sqs.auto_query('Indexed!').filter(pub_date__lte=date(2009, 2, 25)).filter(django_id__in=[1, 2]).exclude(name='daniel1')
- self.assertEqual(sqs.query.build_query(), u"('Indexed!' AND pub_date:[to 20090225000000] AND django_id:(\"1\" OR \"2\") AND NOT (name:daniel1))")
+ self.assertEqual(sqs.query.build_query(), u'((\'Indexed!\') AND pub_date:([to 20090225000000]) AND django_id:("1" OR "2") AND NOT (name:(daniel1)))')
self.assertEqual(len(sqs), 1)
sqs = self.sqs.auto_query('re-inker')
- self.assertEqual(sqs.query.build_query(), u"'re-inker'")
+ self.assertEqual(sqs.query.build_query(), u"('re-inker')")
self.assertEqual(len(sqs), 0)
sqs = self.sqs.auto_query('0.7 wire')
- self.assertEqual(sqs.query.build_query(), u"'0.7' wire")
+ self.assertEqual(sqs.query.build_query(), u"('0.7' wire)")
self.assertEqual(len(sqs), 0)
sqs = self.sqs.auto_query("daler-rowney pearlescent 'bell bronze'")
- self.assertEqual(sqs.query.build_query(), u"'daler-rowney' pearlescent 'bell bronze'")
+ self.assertEqual(sqs.query.build_query(), u"('daler-rowney' pearlescent 'bell bronze')")
self.assertEqual(len(sqs), 0)
sqs = self.sqs.models(MockModel)
@@ -754,6 +755,10 @@ def test_count(self):
self.assertEqual(results._cache_is_full(), False)
self.assertEqual(len(connections['default'].queries), 1)
+ def test_query_generation(self):
+ sqs = self.sqs.filter(SQ(content=AutoQuery("hello world")) | SQ(title=AutoQuery("hello world")))
+ self.assertEqual(sqs.query.build_query(), u"((hello world) OR title:(hello world))")
+
def test_result_class(self):
self.sb.update(self.wmmi, self.sample_objs)
36 tests/whoosh_tests/tests/whoosh_query.py
View
@@ -33,42 +33,42 @@ def test_build_query_all(self):
def test_build_query_single_word(self):
self.sq.add_filter(SQ(content='hello'))
- self.assertEqual(self.sq.build_query(), 'hello')
+ self.assertEqual(self.sq.build_query(), '(hello)')
def test_build_query_multiple_words_and(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_filter(SQ(content='world'))
- self.assertEqual(self.sq.build_query(), u'(hello AND world)')
+ self.assertEqual(self.sq.build_query(), u'((hello) AND (world))')
def test_build_query_multiple_words_not(self):
self.sq.add_filter(~SQ(content='hello'))
self.sq.add_filter(~SQ(content='world'))
- self.assertEqual(self.sq.build_query(), u'(NOT (hello) AND NOT (world))')
+ self.assertEqual(self.sq.build_query(), u'(NOT ((hello)) AND NOT ((world)))')
def test_build_query_multiple_words_or(self):
self.sq.add_filter(SQ(content='hello') | SQ(content='world'))
- self.assertEqual(self.sq.build_query(), u'(hello OR world)')
+ self.assertEqual(self.sq.build_query(), u'((hello) OR (world))')
def test_build_query_multiple_words_mixed(self):
self.sq.add_filter(SQ(content='why') | SQ(content='hello'))
self.sq.add_filter(~SQ(content='world'))
- self.assertEqual(self.sq.build_query(), u'((why OR hello) AND NOT (world))')
+ self.assertEqual(self.sq.build_query(), u'(((why) OR (hello)) AND NOT ((world)))')
def test_build_query_phrase(self):
self.sq.add_filter(SQ(content='hello world'))
self.assertEqual(self.sq.build_query(), u'(hello AND world)')
self.sq.add_filter(SQ(content__exact='hello world'))
- self.assertEqual(self.sq.build_query(), u'((hello AND world) AND "hello world")')
+ self.assertEqual(self.sq.build_query(), u'((hello AND world) AND ("hello world"))')
def test_build_query_boost(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_boost('world', 5)
- self.assertEqual(self.sq.build_query(), "hello world^5")
+ self.assertEqual(self.sq.build_query(), "(hello) world^5")
def test_correct_exact(self):
self.sq.add_filter(SQ(content=Exact('hello world')))
- self.assertEqual(self.sq.build_query(), '"hello world"')
+ self.assertEqual(self.sq.build_query(), '("hello world")')
def test_build_query_multiple_filter_types(self):
self.sq.add_filter(SQ(content='why'))
@@ -78,27 +78,27 @@ def test_build_query_multiple_filter_types(self):
self.sq.add_filter(SQ(title__gte='B'))
self.sq.add_filter(SQ(id__in=[1, 2, 3]))
self.sq.add_filter(SQ(rating__range=[3, 5]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:[to 20090210015900] AND author:{daniel to} AND created:{to 20090212121300} AND title:[B to] AND id:("1" OR "2" OR "3") AND rating:[3 to 5])')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:([to 20090210015900]) AND author:({daniel to}) AND created:({to 20090212121300}) AND title:([B to]) AND id:("1" OR "2" OR "3") AND rating:([3 to 5]))')
def test_build_query_in_filter_multiple_words(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=["A Famous Paper", "An Infamous Article"]))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("A Famous Paper" OR "An Infamous Article"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("A Famous Paper" OR "An Infamous Article"))')
def test_build_query_in_filter_datetime(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(pub_date__in=[datetime.datetime(2009, 7, 6, 1, 56, 21)]))
- self.assertEqual(self.sq.build_query(), u'(why AND pub_date:("20090706015621"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND pub_date:("20090706015621"))')
def test_build_query_in_with_set(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=set(["A Famous Paper", "An Infamous Article"])))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("A Famous Paper" OR "An Infamous Article"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("A Famous Paper" OR "An Infamous Article"))')
def test_build_query_wildcard_filter_types(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__startswith='haystack'))
- self.assertEqual(self.sq.build_query(), u'(why AND title:haystack*)')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:(haystack*))')
def test_clean(self):
self.assertEqual(self.sq.clean('hello world'), 'hello world')
@@ -109,18 +109,18 @@ def test_clean(self):
def test_build_query_with_models(self):
self.sq.add_filter(SQ(content='hello'))
self.sq.add_model(MockModel)
- self.assertEqual(self.sq.build_query(), 'hello')
+ self.assertEqual(self.sq.build_query(), '(hello)')
self.sq.add_model(AnotherMockModel)
- self.assertEqual(self.sq.build_query(), u'hello')
+ self.assertEqual(self.sq.build_query(), u'(hello)')
def test_build_query_with_datetime(self):
self.sq.add_filter(SQ(pub_date=datetime.datetime(2009, 5, 9, 16, 20)))
- self.assertEqual(self.sq.build_query(), u'pub_date:20090509162000')
+ self.assertEqual(self.sq.build_query(), u'pub_date:(20090509162000)')
def test_build_query_with_sequence_and_filter_not_in(self):
self.sq.add_filter(SQ(id=[1, 2, 3]))
- self.assertEqual(self.sq.build_query(), u'id:1,2,3')
+ self.assertEqual(self.sq.build_query(), u'id:(1,2,3)')
def test_set_result_class(self):
# Assert that we're defaulting to ``SearchResult``.
@@ -140,4 +140,4 @@ class IttyBittyResult(object):
def test_in_filter_values_list(self):
self.sq.add_filter(SQ(content='why'))
self.sq.add_filter(SQ(title__in=MockModel.objects.values_list('id', flat=True)))
- self.assertEqual(self.sq.build_query(), u'(why AND title:("1" OR "2" OR "3"))')
+ self.assertEqual(self.sq.build_query(), u'((why) AND title:("1" OR "2" OR "3"))')
Please sign in to comment.
Something went wrong with that request. Please try again.