Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Tomáš Peterka
erp5
Commits
d7cc8581
Commit
d7cc8581
authored
Oct 28, 2014
by
Kazuhiko Shiozaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
full text: move special query generation logic from SearchKey to ComparisonOperator.
parent
6d4c6e39
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
68 additions
and
76 deletions
+68
-76
product/ZSQLCatalog/Operator/ComparisonOperator.py
product/ZSQLCatalog/Operator/ComparisonOperator.py
+65
-3
product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py
product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py
+1
-1
product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py
product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py
+2
-72
No files found.
product/ZSQLCatalog/Operator/ComparisonOperator.py
View file @
d7cc8581
...
...
@@ -33,6 +33,7 @@ from Products.ZSQLCatalog.SQLExpression import SQLExpression
from
Products.ZSQLCatalog.interfaces.operator
import
IOperator
from
zope.interface.verify
import
verifyClass
from
Products.ZSQLCatalog.SQLCatalog
import
list_type_list
import
re
class
ComparisonOperatorBase
(
OperatorBase
):
def
asSQLExpression
(
self
,
column
,
value_list
,
only_group_columns
):
...
...
@@ -98,16 +99,19 @@ verifyClass(IOperator, MultivaluedComparisonOperator)
class
MatchComparisonOperator
(
MonovaluedComparisonOperator
):
def
__init__
(
self
,
operator
,
mode
=
''
):
MonovaluedComparisonOperator
.
__init__
(
self
,
operator
,
''
)
self
.
where_expression_format_string
=
'MATCH (%%(column)s) AGAINST (%%(value_list)s%s)'
%
(
mode
,
)
self
.
mode
=
mode
self
.
where_expression_format_string
=
'MATCH (%(column)s) AGAINST (%(value_list)s%(mode)s)'
def
asSQLExpression
(
self
,
column
,
value_list
,
only_group_columns
):
"""
This operator can emit a select expression, so it overrides
asSQLExpression inseatd of just defining a render method.
"""
value_list
=
self
.
renderValue
(
value_list
)
match_string
=
self
.
where_expression_format_string
%
{
'column'
:
column
,
'value_list'
:
self
.
renderValue
(
value_list
),
'value_list'
:
value_list
,
'mode'
:
self
.
mode
,
}
select_dict
=
{}
if
not
only_group_columns
:
...
...
@@ -127,6 +131,63 @@ class MatchComparisonOperator(MonovaluedComparisonOperator):
verifyClass
(
IOperator
,
MatchComparisonOperator
)
class
MroongaComparisonOperator
(
MatchComparisonOperator
):
fulltext_boolean_splitter
=
re
.
compile
(
r'(\
s|
\(.+?\
)|
".+?")'
)
fulltext_boolean_detector
=
re
.
compile
(
r'(^[+-]|^.+\
*$|^[
"(].+[")]$)'
)
def
renderValue
(
self
,
value_list
):
"""
Special Query renderer for MroongaFullText queries:
* by default 'AND' search by using '*D+' pragma.
* similarity search for non-boolean queries by using '*S"..."' operator.
"""
if
isinstance
(
value_list
,
list_type_list
):
try
:
value_list
,
=
value_list
except
ValueError
:
raise
ValueError
,
'%r: value_list must not contain more than one item. Got %r'
%
(
self
,
value_list
)
if
self
.
mode
==
' IN BOOLEAN MODE'
:
fulltext_query
=
'*D+ %s'
%
value_list
return
self
.
_renderValue
(
fulltext_query
)
else
:
match_query_list
=
[]
match_boolean_query_list
=
[]
for
token
in
self
.
fulltext_boolean_splitter
.
split
(
value_list
):
token
=
token
.
strip
()
if
not
token
:
continue
elif
self
.
fulltext_boolean_detector
.
match
(
token
):
match_boolean_query_list
.
append
(
token
)
else
:
match_query_list
.
append
(
token
)
fulltext_query
=
'*D+'
if
match_query_list
:
fulltext_query
+=
' *S"%s"'
%
' '
.
join
(
x
.
replace
(
'"'
,
'
\
\
"'
)
for
x
in
match_query_list
)
if
match_boolean_query_list
:
fulltext_query
+=
' %s'
%
' '
.
join
(
match_boolean_query_list
)
self
.
mode
=
' IN BOOLEAN MODE'
return
self
.
_renderValue
(
fulltext_query
)
verifyClass
(
IOperator
,
MroongaComparisonOperator
)
class
MroongaBooleanComparisonOperator
(
MroongaComparisonOperator
):
def
renderValue
(
self
,
value_list
):
"""
value_list must either be a non-list or a single-value list.
"""
if
isinstance
(
value_list
,
list_type_list
):
try
:
value_list
,
=
value_list
except
ValueError
:
raise
ValueError
,
'%r: value_list must not contain more than one item. Got %r'
%
(
self
,
value_list
)
fulltext_query
=
'*D+ %s'
%
value_list
print
self
.
_renderValue
(
fulltext_query
)
return
self
.
_renderValue
(
fulltext_query
)
verifyClass
(
IOperator
,
MatchComparisonOperator
)
class
SphinxSEComparisonOperator
(
MonovaluedComparisonOperator
):
def
__init__
(
self
,
operator
,
mode
=
''
):
MonovaluedComparisonOperator
.
__init__
(
self
,
operator
,
''
)
...
...
@@ -173,9 +234,10 @@ operator_dict = {
'match'
:
MatchComparisonOperator
(
'match'
),
'match_boolean'
:
MatchComparisonOperator
(
'match_boolean'
,
mode
=
' IN BOOLEAN MODE'
),
'match_expansion'
:
MatchComparisonOperator
(
'match_expansion'
,
mode
=
' WITH QUERY EXPANSION'
),
'mroonga'
:
MroongaComparisonOperator
(
'mroonga'
),
'mroonga_boolean'
:
MroongaComparisonOperator
(
'mroonga_boolean'
,
mode
=
' IN BOOLEAN MODE'
),
'sphinxse'
:
SphinxSEComparisonOperator
(
'sphinxse'
),
'in'
:
MultivaluedComparisonOperator
(
'in'
),
'is'
:
MonovaluedComparisonOperator
(
'is'
),
'is not'
:
MonovaluedComparisonOperator
(
'is not'
,
'!='
),
}
product/ZSQLCatalog/SearchKey/MroongaBooleanFullTextKey.py
View file @
d7cc8581
...
...
@@ -35,6 +35,6 @@ class MroongaBooleanFullTextKey(MroongaFullTextKey):
This SearchKey generates SQL fulltext comparisons for Mroonga whose
default comparison operator is match_boolean.
"""
default_comparison_operator
=
'm
atch
_boolean'
default_comparison_operator
=
'm
roonga
_boolean'
verifyClass
(
ISearchKey
,
MroongaBooleanFullTextKey
)
product/ZSQLCatalog/SearchKey/MroongaFullTextKey.py
View file @
d7cc8581
...
...
@@ -27,80 +27,10 @@
##############################################################################
from
DefaultKey
import
DefaultKey
from
FullTextKey
import
FullTextKey
from
Products.ZSQLCatalog.Query.SimpleQuery
import
SimpleQuery
from
Products.ZSQLCatalog.interfaces.search_key
import
ISearchKey
from
SearchKey
import
SearchKey
from
zope.interface.verify
import
verifyClass
import
re
class
MroongaFullTextKey
(
FullTextKey
):
"""
This SearchKey generates SQL fulltext comparisons for Mroonga.
"""
default_comparison_operator
=
'match'
fulltext_boolean_splitter
=
re
.
compile
(
r'(\
s|
\(.+?\
)|
".+?")'
)
fulltext_boolean_detector
=
re
.
compile
(
r'(^[+-]|^.+\
*$|^[
"(].+[")]$)'
)
def
_processSearchValue
(
self
,
search_value
,
logical_operator
,
comparison_operator
):
"""
Special SearchValue processor for MroongaFullText queries:
if a searched token from 'match' operator group contains an
operator recognised in boolean mode, make the operator for
that value be 'match_boolean'.
"""
operator_value_dict
,
logical_operator
,
parsed
=
\
SearchKey
.
_processSearchValue
(
self
,
search_value
,
logical_operator
,
comparison_operator
)
new_value_list
=
[]
append
=
new_value_list
.
append
for
value
in
operator_value_dict
.
pop
(
'match'
,
[]):
if
isinstance
(
value
,
basestring
):
# special case for empty string.
if
value
==
''
:
operator_value_dict
.
setdefault
(
'='
,
[]).
append
(
value
)
continue
for
token
in
self
.
fulltext_boolean_splitter
.
split
(
value
):
token
=
token
.
strip
()
if
not
token
:
continue
elif
self
.
fulltext_boolean_detector
.
match
(
token
):
operator_value_dict
.
setdefault
(
'match_boolean'
,
[]).
append
(
token
)
else
:
append
(
token
)
else
:
append
(
value
)
operator_value_dict
[
'match'
]
=
new_value_list
return
operator_value_dict
,
logical_operator
,
parsed
def
_buildQuery
(
self
,
operator_value_dict
,
logical_operator
,
parsed
,
group
):
"""
Special Query builder for MroongaFullText queries:
* by default 'AND' search by using '*D+' pragma.
* similarity search for non-boolean queries by using '*S"..."' operator.
"""
column
=
self
.
getColumn
()
query_list
=
[]
append
=
query_list
.
append
match_query
=
operator_value_dict
.
pop
(
'match'
,
[])
match_boolean_query
=
operator_value_dict
.
pop
(
'match_boolean'
,
[])
fulltext_query
=
'*D+'
if
match_query
:
fulltext_query
+=
' *S"%s"'
%
' '
.
join
(
x
.
replace
(
'"'
,
'
\
\
"'
)
for
x
in
match_query
)
if
match_boolean_query
:
if
len
(
match_boolean_query
)
>
1
and
logical_operator
==
'or'
:
fulltext_query
+=
' %s'
%
' OR '
.
join
(
'(%s)'
%
x
for
x
in
match_boolean_query
)
else
:
fulltext_query
+=
' %s'
%
' '
.
join
(
match_boolean_query
)
if
match_query
or
match_boolean_query
:
append
(
SimpleQuery
(
search_key
=
self
,
comparison_operator
=
'match_boolean'
,
group
=
group
,
**
{
column
:
fulltext_query
}))
# other comparison operators are handled by DefaultKey.
if
operator_value_dict
:
query_list
+=
DefaultKey
.
_buildQuery
(
self
,
operator_value_dict
,
logical_operator
,
parsed
,
group
)
return
query_list
class
MroongaFullTextKey
(
DefaultKey
):
default_comparison_operator
=
'mroonga'
verifyClass
(
ISearchKey
,
MroongaFullTextKey
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment