描述
在使用sqlite3_prepare_v2或sqlite3_prepare16_v2或其中一个旧功能sqlite3_prepare或sqlite3_prepare16准备好的语句之后,必须调用此函数一次或多次以评估该语句。对于新的应用程序,建议使用新的“v2”界面。
C / C ++语法
int sqlite3_step(sqlite3_stmt*); |
PB语法
FUNCTION sqlite3_step ( _ BYVAL hStmt AS DWORD _ ) AS LONG |
参数
pStmt
[in]语句句柄。
返回值
在旧版界面中,返回值将为SQLITE_BUSY,SQLITE_DONE,SQLITE_ROW,SQLITE_ERROR或SQLITE_MISUSE。使用“v2”界面,也可以返回任何其他结果代码或扩展结果代码。
SQLITE_BUSY意味着数据库引擎无法获取完成其作业所需的数据库锁。如果该语句是COMMIT或发生在显式事务之外,则可以重试该语句。如果该语句不是COMMIT并发生在显式事务中,那么您应该在继续之前回滚该事务。
SQLITE_DONE表示语句已成功执行。不要在此虚拟机上再次调用sqlite3_step(),而无需先调用sqlite3_reset将虚拟机重置为初始状态。
如果正在执行的SQL语句返回任何数据,则每当新行数据准备好由调用者处理时,返回SQLITE_ROW.可以使用列访问功能来访问这些值。再次调用sqlite3_step以检索下一行数据。
SQLITE_ERROR表示发生运行时错误(如约束违规)。不要在虚拟机上再次调用sqlite3_step.通过致电sqlite3_errmsg可以找到更多信息。使用传统接口,可以通过在准备好的语句中调用sqlite3_reset获取更具体的错误代码(例如,SQLITE_INTERRUPT,SQLITE_SCHEMA,SQLITE_CORRUPT等)。在“v2”界面中,sqlite3_step直接返回更具体的错误代码。
SQLITE_MISUSE意味着这个函数被调用不当。也许这是在已经完成的准备好的语句中被调用的,或者是之前已经返回SQLITE_ERROR或SQLITE_DONE的语句。或者可能是同一个数据库连接在同一时刻被两个或多个线程使用的情况。
备注
sqlite3_step功能的行为细节取决于该语句是否使用较新的“v2”接口sqlite3_prepare_v2和sqlite3_prepare16_v2或旧版本接口sqlite3_prepare和sqlite3_prepare16进行准备。对于新的应用程序推荐使用新的“v2”界面,但继续支持传统接口。
对于所有版本的SQLite,直到并包括3.6.23.1,在sqlite3_reset之后sqlite3_step返回除SQLITE_ROW之外的任何东西,在任何后续调用sqlite3_step之前,都需要调用sqlite3_reset.如果未使用sqlite3_reset重置准备好的语句,则会导致SQLite_MISUSE从sqlite3_step返回。但在版本3.6.23.1之后,sqlite3_step在这种情况下自动调用sqlite3_reset而不是返回SQLITE_MISUSE。这不被认为是兼容性破坏,因为任何收到SQLITE_MISUSE错误的应用程序都被定义破坏。SQLITE_OMIT_AUTORESET编译时选项可用于还原旧版行为。
Goofy界面警报:在旧版接口中,除了SQLITE_BUSY和SQLITE_MISUSE之外,sqlite3_stepAPI总是返回一个通用错误代码SQLITE_ERROR。您必须致电sqlite3_reset或sqlite3_finalize才能找到更好地描述错误的特定错误代码之一。我们承认这是一个愚蠢的设计。问题已经通过“v2”界面修复。如果您使用sqlite3_prepare_v2或sqlite3_prepare16_v2而不是传统的sqlite3_prepare和sqlite3_prepare16接口准备所有SQL语句,那么sqlite3_step将直接返回更具体的错误代码。建议使用“v2”界面。
C ++实现代码
/*
** Rerun the compilation of a statement after a schema change.
**
** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
** if the statement cannot be recompiled because another connection has
** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error
** occurs, return SQLITE_SCHEMA.
*/
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
int rc;
sqlite3_stmt *pNew;
const char *zSql;
sqlite3 *db;
assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) );
zSql = sqlite3_sql((sqlite3_stmt *)p);
assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */
db = sqlite3VdbeDb(p);
assert( sqlite3_mutex_held(db->mutex) );
rc = sqlite3LockAndPrepare(db, zSql, -1, 0, p, &pNew, 0);
if( rc ){
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
assert( pNew==0 );
return rc;
}else{
assert( pNew!=0 );
}
sqlite3VdbeSwap((Vdbe*)pNew, p);
sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult((Vdbe*)pNew);
sqlite3VdbeFinalize((Vdbe*)pNew);
return SQLITE_OK;
}
/*
** Execute the statement pStmt, either until a row of data is ready, the
** statement is completely executed or an error occurs.
**
** This function implements the bulk of the logic behind the sqlite_step()
** API. The only thing omitted is the automatic recompile if a
** schema change has occurred. That detail is handled by the
** outer sqlite3_step() wrapper procedure.
*/
static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
assert(p);
if( p->magic!=VDBE_MAGIC_RUN ){
/* We used to require that sqlite3_reset() be called before retrying
** sqlite3_step() after any error or after SQLITE_DONE. But beginning
** with version 3.7.0, we changed this so that sqlite3_reset() would
** be called automatically instead of throwing the SQLITE_MISUSE error.
** This "automatic-reset" change is not technically an incompatibility,
** since any application that receives an SQLITE_MISUSE is broken by
** definition.
**
** Nevertheless, some published applications that were originally written
** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
** returns, and those were broken by the automatic-reset change. As a
** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
** legacy behavior of returning SQLITE_MISUSE for cases where the
** previous sqlite3_step() returned something other than a SQLITE_LOCKED
** or SQLITE_BUSY error.
*/
#ifdef SQLITE_OMIT_AUTORESET
if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){
sqlite3_reset((sqlite3_stmt*)p);
}else{
return SQLITE_MISUSE_BKPT;
}
#else
sqlite3_reset((sqlite3_stmt*)p);
#endif
}
/* Check that malloc() has not failed. If it has, return early. */
db = p->db;
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM;
return SQLITE_NOMEM;
}
if( p->pc<=0 && p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
goto end_of_step;
}
if( p->pc<0 ){
/* If there are no other statements currently running, then
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
if( db->activeVdbeCnt==0 ){
db->u1.isInterrupted = 0;
}
assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 );
#ifndef SQLITE_OMIT_TRACE
if( db->xProfile && !db->init.busy ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}
#endif
db->activeVdbeCnt++;
if( p->readOnly==0 ) db->writeVdbeCnt++;
p->pc = 0;
}
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
db->vdbeExecCnt++;
rc = sqlite3VdbeExec(p);
db->vdbeExecCnt--;
}
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
sqlite3_int64 iNow;
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
}
#endif
if( rc==SQLITE_DONE ){
assert( p->rc==SQLITE_OK );
p->rc = doWalCallbacks(db);
if( p->rc!=SQLITE_OK ){
rc = SQLITE_ERROR;
}
}
db->errCode = rc;
if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
p->rc = SQLITE_NOMEM;
}
end_of_step:
/* At this point local variable rc holds the value that should be
** returned if this statement was compiled using the legacy
** sqlite3_prepare() interface. According to the docs, this can only
** be one of the values in the first assert() below. Variable p->rc
** contains the value that would be returned if sqlite3_finalize()
** were called on statement p.
*/
assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|| rc==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
/* If this statement was prepared using sqlite3_prepare_v2(), and an
** error has occured, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
rc = sqlite3VdbeTransferError(p);
}
return (rc&db->errMask);
}
/*
** The maximum number of times that a statement will try to reparse
** itself before giving up and returning SQLITE_SCHEMA.
*/
#ifndef SQLITE_MAX_SCHEMA_RETRY
# define SQLITE_MAX_SCHEMA_RETRY 5
#endif
/*
** This is the top-level implementation of sqlite3_step(). Call
** sqlite3Step() to do most of the work. If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_OK; /* Result from sqlite3Step() */
int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
sqlite3 *db; /* The database connection */
if( vdbeSafetyNotNull(v) ){
return SQLITE_MISUSE_BKPT;
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
assert( v->expired==0 );
}
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
** from the database handle into the statement and sets the statement
** program counter to 0 to ensure that when the statement is
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
v->rc = rc2;
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM;
}
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}