sqlite3_reset()
调用失败后是否需要调用准备好的语句sqlite3_step()
?我正在使用 sqlite3 版本 3.23.1。我准备好的语句的生命周期如下:
sqlite3_prepare_v2()
并保留准备好的语句的句柄在应用程序的生命周期内可用。sqlite3_bind_*()
函数,然后执行sqlite3_step()
该语句,直到得到SQLITE_ROW
除返回之外的其他内容。这是我调用后发生的代码部分sqlite3_step()
。请注意,变量resultCode
保存最后一次调用的返回值sqlite3_step()
。
if (resultCode == SQLITE_DONE || resultCode == SQLITE_ROW)
{
if (sqlite3_reset(m_statement) != SQLITE_OK)
{
LogDbFailure(*m_db, "sqlite3_reset()");
}
}
else
{
LogDbFailure(*m_db, "sqlite3_step()");
success = false;
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果对步骤的调用失败,我不会进行重置。Google 上的文档或搜索结果中没有任何内容表明sqlite3_reset()
必须在失败时调用。事实上,文档指出,sqlite3_reset()
失败后调用也会失败:
如果最近对准备好的语句 S 的 sqlite3_step(S) 调用指示错误,则 sqlite3_reset(S) 返回适当的错误代码。
读到这篇文章让我觉得如果步骤失败,也许我不应该调用重置函数。
谁能澄清一下吗?请注意,就我而言,sqlite3_step()
失败是因为SQLITE_BUSY
. 我正在使用 WAL 日志模式。一旦准备好的语句上的步骤失败,当我调用 时,该准备好的语句将永远处于繁忙状态sqlite3_step()
。sqlite3_bind_*()
return 之后的调用sqlite3_bind_int64() failed (21): bad parameter or other API misuse
(日志格式是我自己的,但 21 是错误代码),这让我认为在失败情况下应该调用重置,因为所有错误似乎都表明数据库正忙,因为准备好的语句卡住了由于缺乏重置而处于交易中期。
请注意,如果对步骤的调用失败,我不会进行重置。Google 上的文档或搜索结果中没有任何内容表明
sqlite3_reset()
必须在失败时调用。
嗯,不,不是具体的,但是文档确实sqlite3_reset()
说
调用 sqlite3_reset() 函数将准备好的语句对象重置回其初始状态,准备重新执行。
你补充说,
事实上,文档指出,
sqlite3_reset()
失败后调用也会失败:如果最近对准备好的语句 S 的 sqlite3_step(S) 调用指示错误,则 sqlite3_reset(S) 返回适当的错误代码。
不,你误解了这一点。“返回适当的错误代码”和“将失败”之间有一个重要的区别。在以下文档sqlite3_step()
摘录的上下文中考虑时,这一点应该会更清楚:
在旧版接口中,sqlite3_step() API 始终在 SQLITE_BUSY 和 SQLITE_MISUSE 之外的任何错误之后返回通用错误代码 SQLITE_ERROR。您必须调用 sqlite3_reset() 或 sqlite3_finalize() 才能找到更好地描述错误的特定错误代码之一。
尽管 的行为sqlite3_step()
仅适用于旧接口,而不是 V2 接口,但它解释了为什么 的返回值sqlite3_reset()
报告先前调用(如果有)的结果sqlite3_step()
,而不是其自身的成功或失败。隐含的是重置本身不能失败,或者至少不能通过其返回代码报告其自身的失败。
读到这篇文章让我觉得如果步骤失败,也许我不应该调用重置函数。
文档对此sqlite3_step()
有这样的说法:
对于 SQLite 3.6.23.1 及之前的所有版本,在 sqlite3_step() 返回除 SQLITE_ROW 以外的任何内容之后,在后续调用 sqlite3_step() 之前,需要调用 sqlite3_reset()。
注意:因此报告错误后调用并没有错。文档继续说,sqlite3_reset()
sqlite3_step()
未能使用 sqlite3_reset() 重置准备好的语句将导致 sqlite3_step() 返回 SQLITE_MISUSE。但在版本3.6.23.1(2010-03-26)之后,sqlite3_step()开始在这种情况下自动调用sqlite3_reset()而不是返回SQLITE_MISUSE。
这似乎与您报告的行为不一致,但请注意,
[...] SQLITE_OMIT_AUTORESET 编译时选项可用于恢复遗留行为。
因此,最安全的选择是无条件重置语句,而不是在报告错误后避免重置它。对于许多 SQLite3 构建来说这可能是不必要的,但这并不是错误或有害的,而且对于某些构建来说这是必要的。