Skip to content

Commit 5c261f6

Browse files
Advanced query search syntax for multi byte search
1 parent 9a1d333 commit 5c261f6

File tree

1 file changed

+43
-6
lines changed

1 file changed

+43
-6
lines changed

redash/models/__init__.py

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import datetime
33
import logging
44
import numbers
5+
import re
56
import time
67

78
import pytz
@@ -644,6 +645,47 @@ def outdated_queries(cls):
644645

645646
return list(outdated_queries.values())
646647

648+
@classmethod
649+
def _do_multi_byte_search(cls, all_queries, term, limit=None):
650+
# term examples:
651+
# - word
652+
# - name:word
653+
# - query:word
654+
# - "multiple words"
655+
# - name:"multiple words"
656+
# - word1 word2 word3
657+
# - word1 "multiple word" query:"select foo"
658+
tokens = re.findall(r'(?:([^:\s]+):)?(?:"([^"]+)"|(\S+))', term)
659+
conditions = []
660+
for token in tokens:
661+
key = None
662+
if token[0]:
663+
key = token[0]
664+
665+
if token[1]:
666+
value = token[1]
667+
else:
668+
value = token[2]
669+
670+
pattern = f"%{value}%"
671+
672+
if key == "id" and value.isdigit():
673+
conditions.append(cls.id.equal(int(value)))
674+
elif key == "name":
675+
conditions.append(cls.name.ilike(pattern))
676+
elif key == "query":
677+
conditions.append(cls.query_text.ilike(pattern))
678+
elif key == "description":
679+
conditions.append(cls.description.ilike(pattern))
680+
else:
681+
conditions.append(or_(cls.name.ilike(pattern), cls.description.ilike(pattern)))
682+
683+
return (
684+
all_queries.filter(and_(*conditions))
685+
.order_by(Query.id)
686+
.limit(limit)
687+
)
688+
647689
@classmethod
648690
def search(
649691
cls,
@@ -664,12 +706,7 @@ def search(
664706

665707
if multi_byte_search:
666708
# Since tsvector doesn't work well with CJK languages, use `ilike` too
667-
pattern = "%{}%".format(term)
668-
return (
669-
all_queries.filter(or_(cls.name.ilike(pattern), cls.description.ilike(pattern)))
670-
.order_by(Query.id)
671-
.limit(limit)
672-
)
709+
return cls._do_multi_byte_search(all_queries, term, limit)
673710

674711
# sort the result using the weight as defined in the search vector column
675712
return all_queries.search(term, sort=True).limit(limit)

0 commit comments

Comments
 (0)