Commit 3b9b48b9 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

fulltext: escape some characters in Mroonga boolean search queries.

parent 10e171cb
...@@ -51,6 +51,11 @@ class TestI18NSearch(ERP5TypeTestCase): ...@@ -51,6 +51,11 @@ class TestI18NSearch(ERP5TypeTestCase):
last_name='実篤', last_name='実篤',
description='Slow white fox jumps over the diligent dog.', description='Slow white fox jumps over the diligent dog.',
) )
person3 = person_module.newContent(
portal_type='Person',
first_name='( - + )',
last_name='',
)
self.tic() self.tic()
# check if 'é' == 'e' collation works # check if 'é' == 'e' collation works
...@@ -77,6 +82,12 @@ class TestI18NSearch(ERP5TypeTestCase): ...@@ -77,6 +82,12 @@ class TestI18NSearch(ERP5TypeTestCase):
self.assertEqual(len(result), 1) self.assertEqual(len(result), 1)
self.assertEqual(result[0].getPath(), person1.getPath()) self.assertEqual(result[0].getPath(), person1.getPath())
# check search with a special character
for query in ('(', ')', ):
result = person_module.searchFolder(title=query)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].getPath(), person3.getPath())
# check fulltext search for automatically generated related keys. # check fulltext search for automatically generated related keys.
self.assertTrue('MATCH' in self.portal.portal_catalog(destination_title='Faure', src__=1)) self.assertTrue('MATCH' in self.portal.portal_catalog(destination_title='Faure', src__=1))
......
...@@ -139,6 +139,11 @@ class MroongaComparisonOperator(MatchComparisonOperator): ...@@ -139,6 +139,11 @@ class MroongaComparisonOperator(MatchComparisonOperator):
MatchComparisonOperator.__init__(self, operator, ' IN BOOLEAN MODE') MatchComparisonOperator.__init__(self, operator, ' IN BOOLEAN MODE')
self.force_boolean = force_boolean self.force_boolean = force_boolean
def _escape(self, query_string):
# TODO : We need to escape more invalid boolean operator usage
# like '+' or '-' without any letter.
return re.compile(r'([()])').sub(r'\\\g<1>', query_string)
def renderValue(self, value_list): def renderValue(self, value_list):
""" """
Special Query renderer for MroongaFullText queries: Special Query renderer for MroongaFullText queries:
...@@ -153,7 +158,7 @@ class MroongaComparisonOperator(MatchComparisonOperator): ...@@ -153,7 +158,7 @@ class MroongaComparisonOperator(MatchComparisonOperator):
if self.force_boolean: if self.force_boolean:
fulltext_query = '*D+ %s' % value_list fulltext_query = '*D+ %s' % value_list
return self._renderValue(fulltext_query) return self._renderValue(self._escape(fulltext_query))
else: else:
match_query_list = [] match_query_list = []
match_boolean_query_list = [] match_boolean_query_list = []
...@@ -170,7 +175,7 @@ class MroongaComparisonOperator(MatchComparisonOperator): ...@@ -170,7 +175,7 @@ class MroongaComparisonOperator(MatchComparisonOperator):
if match_query_list: if match_query_list:
fulltext_query += ' *S"%s"' % ' '.join(match_query_list) fulltext_query += ' *S"%s"' % ' '.join(match_query_list)
if match_boolean_query_list: if match_boolean_query_list:
fulltext_query += ' %s' % ' '.join(match_boolean_query_list) fulltext_query += ' %s' % self._escape(' '.join(match_boolean_query_list))
return self._renderValue(fulltext_query) return self._renderValue(fulltext_query)
verifyClass(IOperator, MroongaComparisonOperator) verifyClass(IOperator, MroongaComparisonOperator)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment