如何转义 SQLite FTS 查询的字符串

问题描述 投票:0回答:3

我正在尝试使用不受信任的用户输入执行 SQLite FTS 查询。我不想让用户访问查询语法,也就是说他们将无法执行像

foo OR bar AND cats
这样的匹配查询。如果他们尝试使用该字符串进行查询,我想将其解释为更像
foo \OR bar \AND cats

SQLite 中似乎没有为此内置任何内容,因此我可能最终会构建自己的转义函数,但这似乎很危险且容易出错。有更好的方法来做到这一点吗?

sqlite full-text-search fts4
3个回答
11
投票

FTS MATCH 语法是它自己的小语言。对于 FTS5,逐字字符串文字定义良好

在 FTS 表达式中,可以通过以下两种方式之一指定字符串:

  • 将其括在双引号 (") 中。在字符串中,任何嵌入的双引号字符都可以通过添加第二个双引号字符来转义 SQL 样式。

  • (已编辑特殊情况)

事实证明,正确转义 FTS 查询的字符串非常简单,可以完全可靠地实现:将

"
替换为
""
并将结果括在两端的
"
中。

就我而言,当我将其放入准备好的语句(例如

SELECT stuff FROM fts_table WHERE fts_table MATCH ?
)中时,它会完美地工作。然后我会
.bind(fts_escape(user_input))
其中
fts_escape
是我上面描述的函数。


4
投票

好的,我已经进一步研究了,通过一些强大的魔法,您可以访问 SQLite 的 FTS 使用的实际标记器。 “简单”标记生成器获取您的字符串,将其分隔为不在 [A-Za-z0-0] 中的任何字符,并将其余字符小写。如果执行相同的操作,您将获得一个适合 FTS 的完美“转义”字符串。

您可以编写自己的程序,但也可以访问 SQLite 的内部程序。有关详细信息,请参阅此问题:使用 SQLite FTS4 自动 OR 查询


0
投票

将查询转换为文字字符串

def fts_string(str):
    # escape string for SQLite FTS query
    return '"' + str.replace('"', ' ') + '"'

...但这可能太严格了,因为它强制执行单词的顺序。
例如

"me find"
find me

不匹配
import re
def fts_words(str):
    # escape words for SQLite FTS query
    # https://github.com/hideaki-t/sqlite-fts-python
    pat = re.compile(r'\w+', re.UNICODE)
    return " ".join(map(lambda word: word.lower(), pat.findall(str)))

...这从字符串中提取单词 (

\w+
)
并逃脱了魔法词
AND
OR
NOT
by
word.lower()

>>> fts_words('"me AND" find')
'me and find'

另请参阅

© www.soinside.com 2019 - 2024. All rights reserved.