是否需要在对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;
}
请注意,如果对步骤的调用失败,则不会进行重置。 Google的文档或搜索结果中没有任何内容表明必须在失败时调用sqlite3_reset()
。实际上,documentation指出失败后调用sqlite3_reset()
也会失败:
如果对准备好的语句S的sqlite3_step(S)的最新调用指示错误,则sqlite3_reset(S)返回适当的错误代码。
读到这篇文章使我认为,如果步骤失败,也许我不应该调用reset函数。
任何人都可以澄清吗?请注意,在我的情况下,sqlite3_step()
由于SQLITE_BUSY
而失败。我正在使用WAL日记模式。一旦对准备好的语句执行步骤失败,那么当我调用sqlite3_step()
时,该准备好的语句将永远处于繁忙状态。在返回sqlite3_bind_*()
之后调用sqlite3_bind_int64() failed (21): bad parameter or other API misuse
(日志格式是我自己的,但是错误代码是21),这让我认为在失败的情况下应该调用reset ,因为所有错误似乎都表明数据库正忙,原因是由于缺少复位而使准备好的语句滞留在事务处理中间。
答案 0 :(得分:4)
请注意,如果对步骤的调用失败,则不会进行重置。什么都没有 Google上的文档或搜索结果表明
sqlite3_reset()
必须在失败时被调用。
不,不是具体,但是the docs for sqlite3_reset()
确实会说
调用sqlite3_reset()函数来重置准备好的语句 对象恢复到初始状态,准备重新执行。
您添加
实际上,文档 指出失败后调用
sqlite3_reset()
也会失败:如果对准备好的语句S的sqlite3_step(S)的最新调用指示错误,则sqlite3_reset(S)返回一个错误。 相应的错误代码。
不,您误解了这一点。 “返回适当的错误代码”和“将失败”之间有重要区别。在此摘录自the docs for sqlite3_step()
的上下文中,应该更清楚:
在旧版界面中,sqlite3_step()API始终返回一个 通用错误代码SQLITE_ERROR,跟随除以下以外的任何错误 SQLITE_BUSY和SQLITE_MISUSE。您必须调用sqlite3_reset()或 sqlite3_finalize()以查找特定的错误代码之一 可以更好地描述错误。
尽管sqlite3_step()
的行为仅适用于旧版接口,而不适用于V2接口,但这解释了为什么sqlite3_reset()
的返回值报告了先前对{{ 1}},而不是靠自己的成功或失败。隐含的是,重置本身不能失败,或者至少不能通过返回代码报告其自身的失败。
读到这篇文章让我觉得也许我不应该给复位打个电话 如果步骤失败,则功能正常。
sqlite3_step()
的文档在这一点上有这样的说法:
对于不低于3.6.23.1的所有SQLite版本,请调用 在sqlite3_step()返回任何内容后,需要sqlite3_reset() 后续的任何调用之前,SQLITE_ROW除外 sqlite3_step()。
注意:因此,sqlite3_step()
报告错误后调用sqlite3_reset()
是没错。文档继续说,
无法使用重新设置准备好的语句 sqlite3_reset()将导致从SQLITE_MISUSE返回 sqlite3_step()。但是在版本3.6.23.1(2010-03-26,sqlite3_step()之后 在这种情况下开始自动调用sqlite3_reset() 而不是返回SQLITE_MISUSE。
这似乎与您举报的行为不一致,但请注意,
[...] SQLITE_OMIT_AUTORESET 编译时选项可用于恢复旧版行为。
因此,最安全的选择是无条件重置该语句,而不是避免在报告错误后将其重置。对于许多SQLite3构建来说,这可能是不必要的,但这不是错误或有害的,而对于某些构建,则是必需的。