Commit 9bcb5a93 authored by Jean-Paul Smets's avatar Jean-Paul Smets

Minor changes in syntax (space, tabs, etc.)

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@19215 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 7fd695dd
......@@ -33,7 +33,7 @@ class ComplexQuery(QueryMixin):
"""
Used in order to concatenate many queries
"""
def __init__(self, *args, **kw):
self.query_list = args
self.operator = kw.pop('operator', 'AND')
......
......@@ -34,10 +34,10 @@ class QueryMixin:
operator = None
format = None
type = None
def __call__(self, **kw):
return self.asSQLExpression(**kw)
def getOperator(self):
return self.operator
......
......@@ -30,29 +30,29 @@ from Products.ZSQLCatalog.Query.SimpleQuery import SimpleQuery as Query
from Products.ZSQLCatalog.Query.ComplexQuery import ComplexQuery
from Products.ZSQLCatalog.SQLCatalog import getSearchKeyInstance
from DateTime import DateTime
from Key import BaseKey
from SearchKey import SearchKey
from pprint import pprint
class DateTimeKey(BaseKey):
class DateTimeKey(SearchKey):
""" DateTimeKey key is an ERP5 portal_catalog search key which is used to render
SQL expression that will try to match values in DateTime MySQL columns.
It supports following special operator ['=', '%', '>' , '>=', '<', '<='] in
addition to main logical operators like ['OR', 'or', 'AND', 'and'].
Note: because all ERP5 datetime values are indexed in MySQL in 'UTC'
the respective passed date will be first converted to 'UTC' before inserted into
respective SQL query!
Examples (GMT+02, Bulgaria/Sofia for 'delivery.start_date'):
* '15/01/2008' --> "delivery.start_date = '2008-01-14 22:00'"
* '>=15/01/2008' --> "delivery.start_date >= '2008-01-14 22:00'"
* '>=15/01/2008 or <=20/01/2008'
--> "delivery.start_date >= '2008-01-14 22:00' or delivery.start_date<='2008-01-19 22:00'"
* '>=15/01/2008 10:00 GMT+02 OR <=20/01/2008 05:12 Universal'
-->
"delivery.start_date >= '2008-01-15 08:00 Universal'
......@@ -60,14 +60,14 @@ class DateTimeKey(BaseKey):
delivery.start_date <= '2008-01-20 05:12 Universal'
"
"""
tokens = ('DATE', 'OR', 'AND', 'NOT', 'EQUAL',
'GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL')
sub_operators = ('GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL', 'NOT', 'EQUAL',)
def t_OR(self, t):
r'(\s+OR\s+|\s+or\s+)'
# operator has leading and trailing ONLY one white space character
......@@ -78,21 +78,21 @@ class DateTimeKey(BaseKey):
r'(\s+AND\s+|\s+and\s+)'
# operator has leading and trailing ONLY one white space character
t.value = 'AND'
return t
return t
def t_NOT(self, t):
r'(\s+NOT\s+|\s+not\s+|!=)'
# operator has leading and trailing ONLY one white space character
t.value = t.value.upper().strip()
return t
return t
t_GREATERTHANEQUAL = r'>='
t_LESSTHANEQUAL = r'<='
t_GREATERTHAN = r'>'
t_LESSTHAN = r'<'
t_EQUAL = r'='
t_EQUAL = r'='
t_DATE = r'\d{1,4}[(/|\.|\-) /.]\d{1,4}[(/|\.|\-) /.]\d{1,4}((\s.)*\d{0,2}:\d{0,2}(:\d{0,2})?)?(\sUniversal|\sGMT\+\d\d)?|\d\d\d\d%?'
def quoteSQLString(self, value, format):
""" Return a quoted string of the value.
Make sure to convert it to UTC first."""
......@@ -101,7 +101,7 @@ class DateTimeKey(BaseKey):
else:
value = "'%s'" %DateTime(value).toZone('UTC').ISO()
return value
def buildQueryForTokenList(self, tokens, key, value, format):
""" Build a ComplexQuery for a token list """
query_list = []
......@@ -125,7 +125,7 @@ class DateTimeKey(BaseKey):
days_offset_map = {'=' : 366, '>' : 366,
'>=' : 366, '<': -366, '<=':-366}
days_offset = days_offset_map[sub_operator]
# convert to UTC in given format
is_valid_date = 1
try:
......@@ -137,8 +137,8 @@ class DateTimeKey(BaseKey):
date_value = DateTime(date_value).toZone('UTC')
except:
is_valid_date = 0
query_kw = None
query_kw = None
if is_valid_date:
if sub_operator == '=':
# transform to range 'key >= date AND date < key'
......@@ -147,7 +147,7 @@ class DateTimeKey(BaseKey):
else:
query_kw = {key: date_value + days_offset,
'range': sub_operator}
query_kw['type'] = 'date'
query_kw['type'] = 'date'
else:
# not a valid date, try to get an year range
is_year = 1
......@@ -160,17 +160,17 @@ class DateTimeKey(BaseKey):
query_kw = {key: (date_value, date_value + 366,),
'type': 'date',
'range': 'minmax'}
# append only if it was possible to generate query
if query_kw is not None:
query_list.append(Query(**query_kw))
query_list.append(Query(**query_kw))
# join query list in one really big ComplexQuery
if len(query_list):
complex_query = ComplexQuery(*query_list,
**{'operator': 'AND'})
return complex_query
return complex_query
## def buildSQLExpressionFromSearchString(self, key, value, format, mode, range_value, stat__):
## """ Tokenize/analyze passed string value and generate SQL query expressions. """
## where_expression = ''
......
......@@ -26,15 +26,15 @@
#
##############################################################################
from Key import BaseKey
from SearchKey import SearchKey
from pprint import pprint
class DefaultKey(BaseKey):
class DefaultKey(SearchKey):
""" DefaultKey key is an ERP5 portal_catalog search key which is used to render
SQL expression that will try to exactly one value.
It supports following special operator ['=', '%', '>' , '>=', '<', '<='] in
addition to main logical operators like ['OR', 'or', 'AND', 'and'].
Examples for title column:
* 'foo or bar' --> "title = 'foo' OR title = 'bar'"
* 'foo or =bar' --> "title = 'foo' OR title = 'bar'"
......@@ -43,17 +43,17 @@ class DefaultKey(BaseKey):
* '"Organisation Module"' --> "title = 'Organisation Module'"
* '="Organisation Module"' --> "title = 'Organisation Module'"
"""
# default type of sub Queries to be generated out fo a search string
default_key_type = 'default'
tokens = ('OR', 'AND', 'NOT', 'WORDSET', 'WORD',
'GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL')
sub_operators = ('GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL', 'NOT')
# Note: Order of placing rules (t_WORD for example) is very important
def t_OR(self, t):
......@@ -69,14 +69,14 @@ class DefaultKey(BaseKey):
# otherwise it's treated as a WORD
t.value = 'AND'
return t
def t_NOT(self, t):
r'(\s+NOT\s+|\s+not\s+|!=)'
# operator must have leading and trailing ONLY one white space character
# otherwise it's treated as a WORD
t.value = '!='
return t
t_GREATERTHANEQUAL = r'>='
t_LESSTHANEQUAL = r'<='
t_GREATERTHAN = r'>'
......@@ -89,8 +89,8 @@ class DefaultKey(BaseKey):
# WORD may contain '%' but not at the beginning or end (otherwise it's KEYWORD)
value = t.value.strip()
t.value = "%s" %value
return t
return t
def t_WORDSET(self, t):
r'"[\x7F-\xFF\w\d\s\/~!@#$%^&*()_+][\x7F-\xFF\w\d\s\/~!@#$%^&*()_+]*"'
#r'"[\x7F-\xFF\w\d\s/%][\x7F-\xFF\w\d\s/%]*"'
......@@ -99,21 +99,21 @@ class DefaultKey(BaseKey):
value = t.value.replace('"', '').strip()
t.value = "%s" %value
return t
def quoteSQLString(self, value, format):
""" Return a quoted string of the value. """
if isinstance(value, (int, long,)):
return str(value)
return "'%s'" %value
## def buildSQLExpressionFromSearchString(self, key, value, format, mode, range_value, stat__):
## """ Tokenize/analyze passed string value and generate SQL query expressions. """
## where_expressions = []
## select_expressions = []
## tokens = self.tokenize(value)
## operators_mapping_list = self.groupByOperator(tokens)
##
##
## # find if any logical operator exists
## tokens_values = []
## logical_operator_found = 0
......@@ -122,7 +122,7 @@ class DefaultKey(BaseKey):
## logical_operator_found = 1
## break
## tokens_values.append(token.value.replace("'", ""))
##
##
## # build expressions
## if not logical_operator_found:
## # no logical operator found so we assume that we search for a combination of words
......
......@@ -26,22 +26,22 @@
#
##############################################################################
from Key import BaseKey
class FloatKey(BaseKey):
from SearchKey import SearchKey
class FloatKey(SearchKey):
""" FloatKey key is an ERP5 portal_catalog search key which is used to render
float like SQL expression.
"""
# default type of sub Queries to be generated out fo a search string
default_key_type = 'float'
tokens = ('OR', 'AND', 'NOT', 'FLOAT',
'GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL')
sub_operators = ('GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL', 'NOT')
# Note: Order of placing rules (t_WORD for example) is very important
def t_OR(self, t):
......@@ -75,12 +75,12 @@ class FloatKey(BaseKey):
# FLOAT is a float number
value = t.value.replace('"', '').strip()
t.value = "%s" %value
return t
return t
def quoteSQLString(self, value, format):
""" Return a quoted string of the value. """
# Make sure there is no space in float values
return "'%s'" %str(value).replace(' ', '')
return "'%s'" %str(value).replace(' ', '')
def quoteSQLKey(self, key, format):
""" Return a quoted string of the value. """
......
......@@ -26,12 +26,12 @@
#
##############################################################################
from Key import BaseKey
from SearchKey import SearchKey
SEARCH_MODE_MAPPING = {'in_boolean_mode': 'IN BOOLEAN MODE',
'with_query_expansion': 'WITH QUERY EXPANSION'}
class FullTextKey(BaseKey):
class FullTextKey(SearchKey):
""" FullTextKey key is an ERP5 portal_catalog search key which is used to render
SQL expression that will try match all possible values using
MySQL's fulltext search support.
......@@ -41,12 +41,12 @@ class FullTextKey(BaseKey):
tokens = ('PLUS', 'MINUS', 'WORD', 'GREATERTHAN', 'LESSTHAN', 'LEFTPARENTHES',
'RIGHTPARENTHES', 'TILDE', 'ASTERISK', 'DOUBLEQUOTE',)
# SQL expressions patterns
relevance = '%s_relevance'
where_match_against = "MATCH %s AGAINST ('%s' %s)"
select_match_against_as = "MATCH %s AGAINST ('%s' %s) AS %s"
t_PLUS = r'(\+)'
t_MINUS = r'(\-)'
t_GREATERTHAN = r'(\>)'
......@@ -56,7 +56,7 @@ class FullTextKey(BaseKey):
t_TILDE = r'(\~)'
t_ASTERISK = r'(\*)'
t_DOUBLEQUOTE = r'(\")'
def t_WORD(self, t):
r'[\x7F-\xFF\w\d\/!@#$%^&_][\x7F-\xFF\w\d\/!@#$%^&_]*'
#r'[\x7F-\xFF\w\d][\x7F-\xFF\w\d]*'
......
##############################################################################
#
# Copyright (c) 2005 Nexedi SARL and Contributors. All Rights Reserved.
# Ivan Tyagov <ivan@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License,] or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from Products.ZSQLCatalog.Query.SimpleQuery import SimpleQuery as Query
from Products.ZSQLCatalog.Query.ComplexQuery import ComplexQuery
from Products.ZSQLCatalog.SQLCatalog import getSearchKeyInstance
import ply.yacc as yacc
import ply.lex as lex
class BaseKey:
""" BaseKey is a base class that implements a parser of
search grammar used in ERP5. It also implements all generic
search key class methods."""
# main logical operators
operators = ('OR', 'AND',)
default_operator = '='
# in ERP5 search grammer white space is extremely important
# so we can not ignore it.
#t_ignore = ' \t'
# no need to rack down line numbers
#def t_newline(self, t):
# r'\n+'
# #t.lexer.lineno += len(t.value)
def t_error(self, t):
#print "Illegal character '%s'" % t.value[0]
t.lexer.skip(1)
def p_error(self, p):
pass
def build(self, **kwargs):
""" This method will initialize respective search key class with
tokens' definitions. """
self.lexer = lex.lex(object = self, **kwargs)
def tokenize(self, data):
""" Return list of tokens according to respective
search key tokens' definitions. """
result = []
self.lexer.input(data)
while 1:
tok = self.lexer.token()
if not tok:
break
result.append(tok)
return result
# Grouping of tokens
def getOperatorForTokenList(self, tokens):
""" Generic implementation that will return respective
operator for a token list. The first found occurence wins."""
token = tokens[0]
token_type = token.type
if token_type in self.sub_operators:
return token.value, tokens[1:]
else:
return self.default_operator, tokens
def groupByLogicalOperator(self, tokens, logical_operator ='OR'):
""" Split tokens list into one or many OR concatanated tokens list
"""
sub_tokens_or_groups = []
tmp_token_list = []
for token in tokens:
if token.type != logical_operator:
tmp_token_list.append(token)
else:
sub_tokens_or_groups.append(tmp_token_list)
tmp_token_list = []
# append remainig last tokens
sub_tokens_or_groups.append(tmp_token_list)
return sub_tokens_or_groups
# SQL quoting (each search key should override them it if needed)
def quoteSQLKey(self, key, format):
""" Return a quoted string of the value. """
return key
def quoteSQLString(self, value, format):
""" Return a quoted string of the value. """
return "'%s'" %value
# SQL generation
def buildSQLExpression(self, key, value,
format = None, mode = None, range_value = None, stat__=0):
""" Generic implementation. Leave details to respective key. """
if range_value is not None:
# if range_value we handle directly (i.e no parsing of search string)
where_expressions, select_expressions = \
self.buildSQLExpressionFromRange(key, value,
format, mode, range_value, stat__)
else:
# search string parsing is needed
where_expressions, select_expressions = \
self.buildSQLExpressionFromSearchString(key, str(value),
format, mode, range_value, stat__)
return where_expressions, select_expressions
def buildSQLExpressionFromSearchString(self, key, value, format, mode, range_value, stat__):
complex_query = self.buildQuery(key, value, format, mode, range_value, stat__)
if complex_query is None:
# Query could not be generated from search string
sql_expression = {'where_expression': '1',
'select_expression_list': []}
else:
sql_expression = complex_query(keyword_search_keys = [],
datetime_search_keys = [],
full_text_search_keys = [])
return sql_expression['where_expression'], sql_expression['select_expression_list']
def buildQuery(self, key, value, format, mode, range_value, stat__):
""" Build Query """
query_list = []
# tokenize searchs string into tokens for Search Key
tokens = self.tokenize(value)
# split tokens list into one or more 'OR' tokens lists
tokens_or_groups = self.groupByLogicalOperator(tokens, 'OR')
# remove empty tokens lists
tokens_or_groups = filter(lambda x: len(x), tokens_or_groups)
# get a ComplexQuery for a sub token list
for tokens_or_group in tokens_or_groups:
query = self.buildQueryForTokenList(tokens_or_group, key, value, format)
if query is not None:
# query could be generated for token list
query_list.append(query)
if len(query_list):
# join query list in one really big ComplexQuery
return ComplexQuery(*query_list,
**{'operator':'OR'})
def buildQueryForTokenList(self, tokens, key, value, format):
""" Build a ComplexQuery for a token list """
query_list = []
logical_groups = self.groupByLogicalOperator(tokens, 'AND')
for group_tokens in logical_groups:
token_values = [x.value for x in group_tokens]
sub_operator, sub_tokens = self.getOperatorForTokenList(group_tokens)
sub_tokens_values = [x.value for x in sub_tokens]
query_kw = {key: ' '.join(sub_tokens_values),
'type': self.default_key_type,
'format': format,
'range': sub_operator}
query_list.append(Query(**query_kw))
# join query list in one really big ComplexQuery
complex_query = ComplexQuery(*query_list,
**{'operator': 'AND'})
return complex_query
def buildSQLExpressionFromRange(self, key, value, format, mode, range_value, stat__):
""" This method will generate SQL expressions
from explicitly passed list of values and
range_value in ('min', 'max', ..)"""
key = self.quoteSQLKey(key, format)
where_expression = ''
select_expressions = []
if isinstance(value, (list, tuple)):
if len(value) > 1:
# value should contain at least two items
query_min = self.quoteSQLString(value[0], format)
query_max = self.quoteSQLString(value[1], format)
else:
# value contains only one item
query_min = query_max = self.quoteSQLString(value[0], format)
else:
query_min = query_max = self.quoteSQLString(value, format)
if range_value == 'min':
where_expression = "%s >= %s" % (key, query_min)
elif range_value == 'max':
where_expression = "%s < %s" % (key, query_max)
elif range_value == 'minmax' :
where_expression = "%s >= %s AND %s < %s" % (key, query_min, key, query_max)
elif range_value == 'minngt' :
where_expression = "%s >= %s AND %s <= %s" % (key, query_min, key, query_max)
elif range_value == 'ngt':
where_expression = "%s <= %s" % (key, query_max)
elif range_value == 'nlt':
where_expression = "%s > %s" % (key, query_max)
elif range_value == 'like':
where_expression = "%s LIKE %s" % (key, query_max)
elif range_value == 'not_like':
where_expression = "%s NOT LIKE %s" % (key, query_max)
elif range_value in ('=', '>', '<', '>=', '<=','!=',):
where_expression = "%s %s %s" % (key, range_value, query_max)
return where_expression, select_expressions
## def groupByOperator(self, tokens, group_by_operators_list = operators):
## """ Generic implementation of splitting tokens into logical
## groups defided by respective list of logical operator
## defined for respective search key. """
## items = []
## last_operator = None
## operators_mapping_list = []
## last_operator = {'operator': None,
## 'tokens': []}
## for token in tokens:
## token_type = token.type
## token_value = token.value
## if token_type in group_by_operators_list:
## # (re) init it
## last_operator = {'operator': token,
## 'tokens': []}
## operators_mapping_list.append(last_operator)
## else:
## # not an operator just a value token
## last_operator['tokens'].append(token)
## if last_operator not in operators_mapping_list:
## operators_mapping_list.append(last_operator)
## return operators_mapping_list
......@@ -29,34 +29,34 @@
from Products.ZSQLCatalog.Query.SimpleQuery import SimpleQuery as Query
from Products.ZSQLCatalog.Query.ComplexQuery import ComplexQuery
from Products.ZSQLCatalog.SQLCatalog import getSearchKeyInstance
from Key import BaseKey
from SearchKey import SearchKey
from pprint import pprint
class KeyWordKey(BaseKey):
class KeyWordKey(SearchKey):
""" KeyWordKey key is an ERP5 portal_catalog search key which is used to render
SQL expression that will try to match all possible values in a greedy manner.
It supports following special operator ['=', '%', '>' , '>=', '<', '<='] in
addition to main logical operators like ['OR', 'or', 'AND', 'and'].
Examples for title column:
* 'foo or bar' --> "title LIKE '%foo%' OR title LIKE '%bar%'"
* 'foo or =bar' --> "title LIKE '%foo%' OR title = 'bar'"
* 'Organisation Module' --> "title LIKE '%Organisation Module%'"
* '"Organisation Module"' --> "title LIKE '%Organisation Module%'"
* '="Organisation Module"' --> "title = 'Organisation Module'"
"""
tokens = ('OR', 'AND', 'NOT',
'KEYWORD', 'WORDSET', 'WORD', 'EXPLICITEQUALLITYWORD',
'GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL')
sub_operators = ('GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL', 'NOT')
# this is the default operator
default_operator = 'like'
default_operator = 'like'
# if token's list starts with left sided operator
# use this map to transfer it to range operator
......@@ -98,8 +98,8 @@ class KeyWordKey(BaseKey):
value = t.value.strip()
# get rid of leading '='
t.value = value[1:]
return t
return t
def t_KEYWORD(self, t):
r'%?[\x7F-\xFF\w\d/~!@#$%^&*()_+][\x7F-\xFF\w\d/~!@#$%^&*()_+]*%?'
# KEYWORD may starts(1) and may ends (2) with '%' but always must either #1 or #2
......
......@@ -26,7 +26,9 @@
#
##############################################################################
class RawKey:
from SearchKey import SearchKey
class RawKey(SearchKey):
""" RawKey key is an ERP5 portal_catalog search key which is used to render
SQL expression that will match exactly what's passed to it using equality ."""
......@@ -34,8 +36,8 @@ class RawKey:
# this key doesn't require parsing
# It's required to implement it as it's used ONLY for ExactMath
pass
def buildSQLExpression(self, key, value,
format=None, mode=None, range_value=None, stat__=None):
where_expression = "%s = '%s'" %(key, value)
return where_expression, []
return where_expression, []
......@@ -31,43 +31,42 @@ from Products.ZSQLCatalog.Query.ComplexQuery import ComplexQuery
from Products.ZSQLCatalog.SQLCatalog import getSearchKeyInstance
from Products.PythonScripts.Utility import allow_class
from Key import BaseKey
from pprint import pprint
from SearchKey import SearchKey
from pprint import pprint
# these keys are used to build query in case for ScriptableKey
# when no key was specified in fornt of value
DEFAULT_SEARCH_KEYS = ('SearchableText', 'reference', 'title',)
class KeyMappingKey(BaseKey):
class KeyMappingKey(SearchKey):
""" Usable lexer class used (internally) by ScriptableKey lexer than can parse following:
VALUE OPERATOR VALUE
Examples:
* "portal_type : Person"
* "creation_date > 2007-01-01"
"""
tokens = ('OPERATOR', 'COLONOPERATOR', 'VALUE',)
t_OPERATOR = r'>=|<=|>|<'
t_VALUE = r'[\x7F-\xFF\w\d\/~!@#$^&*()_+-][\x7F-\xFF\w\d\/~!@#$^&*()_+-]*'
def t_COLONOPERATOR(self, t):
r':'
# ':' is the same as '=' (equality)
t.value = '='
return t
class ScriptableKey(BaseKey):
class ScriptableKey(SearchKey):
""" KeyWordKey key is an ERP5 portal_catalog search key which is used to generate a
ComplexQuery instance out of an arbitrary search string.
Examples:
* "John Doe AND portal_type:Person AND creation_date > 2007-01-01"
would be turned into following ComplexQuery:
* ComplexQuery(Query(portal_type='Person'),
Query(creation_date='2007-01-01', operator='>'),
ComplexQuery(Query(searchable_text='John Doe'),
......@@ -78,18 +77,18 @@ class ScriptableKey(BaseKey):
"""
sub_operators = ('GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL',)
tokens = ('OR', 'AND',
'DATE', 'WORD', 'KEYMAPPING',
'GREATERTHAN', 'GREATERTHANEQUAL',
'LESSTHAN', 'LESSTHANEQUAL', 'EQUAL')
t_GREATERTHANEQUAL = r'>='
t_LESSTHANEQUAL = r'<='
t_GREATERTHAN = r'>'
t_LESSTHAN = r'<'
t_EQUAL = r'='
t_EQUAL = r'='
# Note: Order of placing rules (t_WORD for example) is very important
def t_OR(self, t):
r'(\s+OR\s+|\s+or\s+)'
......@@ -113,14 +112,14 @@ class ScriptableKey(BaseKey):
value = t.value.strip()
t.value = value
return t
def t_WORD(self, t):
r'[\x7F-\xFF\w\d\/~!@#$^&*()_+][\x7F-\xFF\w\d\/~!@#$^&*()_+]*'
# WORD may contain arbitrary letters and numbers without white space
# WORD may contain '%' but not at the beginning or end (otherwise it's KEYWORD)
value = t.value.strip()
t.value = value
return t
return t
def buildQueryForTokenList(self, tokens):
""" Build a ComplexQuery for a token list """
......@@ -164,31 +163,31 @@ class ScriptableKey(BaseKey):
**{'operator':'AND'})
return complex_query
def buildQuery(self, key, value,
format=None, mode=None, range_value=None, stat__=None):
""" Build ComplexQuery from passed search string value.
When grouping expressions we use the following assumptions
that 'OR' operator has higher priority in a sense:
* "John Doe AND portal_type:Person OR creation_date>=2005/12/12"
is considered as:
* (John Doe AND portal_type:Person) OR (creation_date>=2005/12/12)"
"""
query_list = []
tokens = self.tokenize(value)
# split tokens list into one or many OR concatanated expressions
sub_tokens_or_groups = self.groupByLogicalOperator(tokens, 'OR')
# get a ComplexQuery for a sub token list
for tokens_or_group in sub_tokens_or_groups:
query_list.append(self.buildQueryForTokenList(tokens_or_group))
# join query list in one really big ComplexQuery
complex_query = ComplexQuery(*query_list,
**{'operator':'OR'})
return complex_query
allow_class(ScriptableKey)
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