【发布时间】:2021-12-02 03:37:31
【问题描述】:
我想做的是使用 fmtlib 制作一个 SQL 查询构建器,理想的语法是:
void run_query(fmt::string_view format, fmt::format_args args) {
...
}
template <typename S, typename... Args>
void query(const S& format, Args&&... args) {
run_query(format, fmt::make_args_checked<Args...>(format, args...));
}
std::string query = query("SELECT * FROM user WHERE id = '{}'", 123);
显然这将允许 SQL 注入,因此我想将每个参数传递给 SQL 转义函数。我找到了一个previous question,看起来我可以工作,但图书馆已经改变,这个例子不再有效。我还查看了一些旧文档,其中有一个名为 ArgVisitor 的东西,我也认为它可能有效,但它也已被删除。
我知道在 SQL 查询构建中格式化字符串的想法是有争议的,但我想保留类型安全性、易用性和编译时格式字符串检查。
【问题讨论】:
-
FWIW,SQL 参数清理的要点是将找到的每个单引号加倍。
-
为什么不直接使用prepared statements而不用担心转义?
-
我不同意这是 ideal 语法。并且准备好的语句比格式化的语句更安全、更快(至少在 SQLite3 上)。使用我的 SQLite3 包装器,它非常复杂并且基于我们的内部框架,您的示例将如下所示:
database->executeQuery("SELECT * FROM user WHERE id = ?", 123, &results);。其中results是一个字典数组。一切都在一个声明中。 -
您使用的是什么 SQL 库?它是否有像 sqlite3 这样的准备好的语句?