最后一个参数将覆盖 SQLite 绑定中的先前参数
Last argument overrides previous arguments in SQLite binding
我知道这可能是一个非常愚蠢的错误,但是我已经坐了几个小时盯着几行代码,浏览文档,我仍然不知道为什么会发生这种情况:
我正在为 C++11 中的 SQLite C API 编写一个方便的包装类。建立与数据库的连接后,函数sql
准备语句,必要时将参数绑定到该语句,然后执行该语句。准备和执行工作正常,绑定一个参数工作正常,但如果我想绑定多个参数,所有值将始终设置为列表中的最后一个参数。
sql
函数如下所示:
template <typename... Args>
bool sql(const std::string &query, const Args &... args)
{
sql_statement call;
if(sqlite3_prepare_v2(database_, query.data(), -1, &call.statement, nullptr)
!= SQLITE_OK)
{
return false;
}
if(!bind(call.statement, 1, args...)) {
return false;
}
return sqlite3_step(call.statement) == SQLITE_DONE;
}
sql_statement
是 sqlite3_stmt
的包装结构,当语句超出范围时,它只会释放语句。 database_
是工作数据库的句柄。不过我不确定,这个函数是否与问题有任何关系。作为麻烦制造者,我宁愿想到的是sql
函数中调用的bind
函数。在这里:
template <typename T, typename... Args>
bool bind(sqlite3_stmt *statement, int current, const T &first, const Args &... args)
{
std::stringstream ss;
ss << first;
if(sqlite3_bind_text(statement, current,
ss.str().data(), ss.str().length(), SQLITE_STATIC) != SQLITE_OK)
{
return false;
}
return bind(statement, current+1, args...);
}
bool bind(sqlite3_stmt *, int) { return true; }
请注意,没有错误,该函数返回 true。我已经用各种输入对其进行了调试;请考虑以下示例:
if(!db.sql("INSERT INTO test (name, age) VALUES (?, ?);", "nijansen", 23)) {
std::cerr << db.error() << std::endl;
return 1;
}
当我调试 bind
的函数调用时,递归按预期工作,因此它会将值传递给函数[1] nijansen
并[2] 23
。SQLite C API 的文档说"最左边的 SQL 参数的索引为 1",所以这应该不是问题。不过,在数据库中,查询的结果是:id: 1, name: 23, age: 23
。我真的很感激能再看看这个问题。
除非为第五个参数传递SQLITE_TRANSIENT
,否则sqlite3_bind_text
不会复制您传入的字符串,并且您的字符串应该一直存在到语句执行为止。在您的情况下,字符串在调用sqlite3_bind_text
后立即被销毁,您只是在这里目睹了未定义行为的一种可能表现。
如果希望sqlite3_bind_text
自行管理数据的生存期,请将SQLITE_STATIC
更改为 SQLITE_TRANSIENT
。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 查询SQLite数据库中的日期
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 带内存和隔离功能的SQLite
- 如何使用Luacneneneba API正确读取字符串和表参数
- Qt SQLite没有查询或参数计数不匹配
- 参数计数不匹配 SQLite 和 Qt 错误
- SQLite 函数调用都具有无效的参数
- 最后一个参数将覆盖 SQLite 绑定中的先前参数