【问题标题】:{fmt} Using compile-time format strings with SQL{fmt} 在 SQL 中使用编译时格式字符串
【发布时间】: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-&gt;executeQuery("SELECT * FROM user WHERE id = ?", 123, &amp;results);。其中results 是一个字典数组。一切都在一个声明中。
  • 您使用的是什么 SQL 库?它是否有像 sqlite3 这样的准备好的语句?

标签: c++ fmt


【解决方案1】:

{fmt} 8.x 中,您应该将格式字符串作为fmt::format_string 传递,这样可以对支持C++20 的编译器进行编译时检查consteval

#include <fmt/core.h>

void run_query(fmt::string_view format, fmt::format_args args) {
  // ...
}

template <typename... T>
void query(fmt::format_string<T...> fmt, T&&... args) {
  run_query(fmt, fmt::make_format_args(args...));
}

int main() {
  query("SELECT * FROM user WHERE id = '{}'", 123);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多