📄 vdbeapi.c
字号:
/* This is for legacy sqlite3_prepare() builds and when the code ** is SQLITE_ROW or SQLITE_DONE */ return rc; }}/*** 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.*/#ifdef SQLITE_OMIT_PARSERint sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_MISUSE; if( pStmt ){ Vdbe *v; v = (Vdbe*)pStmt; sqlite3_mutex_enter(v->db->mutex); rc = sqlite3Step(v); sqlite3_mutex_leave(v->db->mutex); } return rc;}#elseint sqlite3_step(sqlite3_stmt *pStmt){ int rc = SQLITE_MISUSE; if( pStmt ){ int cnt = 0; Vdbe *v = (Vdbe*)pStmt; sqlite3 *db = v->db; sqlite3_mutex_enter(db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < 5 && sqlite3Reprepare(v) ){ sqlite3_reset(pStmt); v->expired = 0; } if( rc==SQLITE_SCHEMA && v->zSql && 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); sqlite3_free(v->zErrMsg); if( !db->mallocFailed ){ v->zErrMsg = sqlite3DbStrDup(db, zErr); } else { v->zErrMsg = 0; v->rc = SQLITE_NOMEM; } } rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); } return rc;}#endif/*** Extract the user data from a sqlite3_context structure and return a** pointer to it.*/void *sqlite3_user_data(sqlite3_context *p){ assert( p && p->pFunc ); return p->pFunc->pUserData;}/*** The following is the implementation of an SQL function that always** fails with an error message stating that the function is used in the** wrong context. The sqlite3_overload_function() API might construct** SQL function that use this routine so that the functions will exist** for name resolution but are actually overloaded by the xFindFunction** method of virtual tables.*/void sqlite3InvalidFunction( sqlite3_context *context, /* The function calling context */ int argc, /* Number of arguments to the function */ sqlite3_value **argv /* Value of each argument */){ const char *zName = context->pFunc->zName; char *zErr; zErr = sqlite3MPrintf(0, "unable to use function %s in the requested context", zName); sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr);}/*** Allocate or return the aggregate context for a user function. A new** context is allocated on the first call. Subsequent calls return the** same context that was returned on prior calls.*/void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ Mem *pMem; assert( p && p->pFunc && p->pFunc->xStep ); assert( sqlite3_mutex_held(p->s.db->mutex) ); pMem = p->pMem; if( (pMem->flags & MEM_Agg)==0 ){ if( nByte==0 ){ assert( pMem->flags==MEM_Null ); pMem->z = 0; }else{ pMem->flags = MEM_Agg; pMem->xDel = sqlite3_free; pMem->u.pDef = p->pFunc; pMem->z = sqlite3DbMallocZero(p->s.db, nByte); } } return (void*)pMem->z;}/*** Return the auxilary data pointer, if any, for the iArg'th argument to** the user-function defined by pCtx.*/void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ VdbeFunc *pVdbeFunc; assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pVdbeFunc = pCtx->pVdbeFunc; if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){ return 0; } return pVdbeFunc->apAux[iArg].pAux;}/*** Set the auxilary data pointer and delete function, for the iArg'th** argument to the user-function defined by pCtx. Any previous value is** deleted by calling the delete function specified when it was set.*/void sqlite3_set_auxdata( sqlite3_context *pCtx, int iArg, void *pAux, void (*xDelete)(void*)){ struct AuxData *pAuxData; VdbeFunc *pVdbeFunc; if( iArg<0 ) goto failed; assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pVdbeFunc = pCtx->pVdbeFunc; if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){ int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0); int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg; pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc); if( !pVdbeFunc ){ goto failed; } pCtx->pVdbeFunc = pVdbeFunc; memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux)); pVdbeFunc->nAux = iArg+1; pVdbeFunc->pFunc = pCtx->pFunc; } pAuxData = &pVdbeFunc->apAux[iArg]; if( pAuxData->pAux && pAuxData->xDelete ){ pAuxData->xDelete(pAuxData->pAux); } pAuxData->pAux = pAux; pAuxData->xDelete = xDelete; return;failed: if( xDelete ){ xDelete(pAux); }}/*** Return the number of times the Step function of a aggregate has been ** called.**** This function is deprecated. Do not use it for new code. It is** provide only to avoid breaking legacy code. New aggregate function** implementations should keep their own counts within their aggregate** context.*/int sqlite3_aggregate_count(sqlite3_context *p){ assert( p && p->pFunc && p->pFunc->xStep ); return p->pMem->n;}/*** Return the number of columns in the result set for the statement pStmt.*/int sqlite3_column_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; return pVm ? pVm->nResColumn : 0;}/*** Return the number of values available from the current row of the** currently executing statement pStmt.*/int sqlite3_data_count(sqlite3_stmt *pStmt){ Vdbe *pVm = (Vdbe *)pStmt; if( pVm==0 || !pVm->resOnStack ) return 0; return pVm->nResColumn;}/*** Check to see if column iCol of the given statement is valid. If** it is, return a pointer to the Mem for the value of that column.** If iCol is not valid, return a pointer to a Mem which has a value** of NULL.*/static Mem *columnMem(sqlite3_stmt *pStmt, int i){ Vdbe *pVm; int vals; Mem *pOut; pVm = (Vdbe *)pStmt; if( pVm && pVm->resOnStack && i<pVm->nResColumn && i>=0 ){ sqlite3_mutex_enter(pVm->db->mutex); vals = sqlite3_data_count(pStmt); pOut = &pVm->pTos[(1-vals)+i]; }else{ static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL }; if( pVm->db ){ sqlite3_mutex_enter(pVm->db->mutex); sqlite3Error(pVm->db, SQLITE_RANGE, 0); } pOut = (Mem*)&nullMem; } return pOut;}/*** This function is called after invoking an sqlite3_value_XXX function on a ** column value (i.e. a value returned by evaluating an SQL expression in the** select list of a SELECT statement) that may cause a malloc() failure. If ** malloc() has failed, the threads mallocFailed flag is cleared and the result** code of statement pStmt set to SQLITE_NOMEM.**** Specifically, this is called from within:**** sqlite3_column_int()** sqlite3_column_int64()** sqlite3_column_text()** sqlite3_column_text16()** sqlite3_column_real()** sqlite3_column_bytes()** sqlite3_column_bytes16()**** But not for sqlite3_column_blob(), which never calls malloc().*/static void columnMallocFailure(sqlite3_stmt *pStmt){ /* If malloc() failed during an encoding conversion within an ** sqlite3_column_XXX API, then set the return code of the statement to ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR ** and _finalize() will return NOMEM. */ Vdbe *p = (Vdbe *)pStmt; if( p ){ p->rc = sqlite3ApiExit(p->db, p->rc); sqlite3_mutex_leave(p->db->mutex); }}/**************************** sqlite3_column_ ********************************* The following routines are used to access elements of the current row** in the result set.*/const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){ const void *val; val = sqlite3_value_blob( columnMem(pStmt,i) ); /* Even though there is no encoding conversion, value_blob() might ** need to call malloc() to expand the result of a zeroblob() ** expression. */ columnMallocFailure(pStmt); return val;}int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_bytes16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ double val = sqlite3_value_double( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ int val = sqlite3_value_int( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ sqlite3_value *pOut = columnMem(pStmt, i); columnMallocFailure(pStmt); return pOut;}#ifndef SQLITE_OMIT_UTF16const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ const void *val = sqlite3_value_text16( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return val;}#endif /* SQLITE_OMIT_UTF16 */int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ int iType = sqlite3_value_type( columnMem(pStmt,i) ); columnMallocFailure(pStmt); return iType;}/* The following function is experimental and subject to change or** removal *//*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){** return sqlite3_value_numeric_type( columnMem(pStmt,i) );**}*//*** Convert the N-th element of pStmt->pColName[] into a string using** xFunc() then return that string. If N is out of range, return 0.**** There are up to 5 names for each column. useType determines which** name is returned. Here are the names:**** 0 The column name as it should be displayed for output** 1 The datatype name for the column** 2 The name of the database that the column derives from** 3 The name of the table that the column derives from** 4 The name of the table column that the result column derives from**** If the result is not a simple column reference (if it is an expression** or a constant) then useTypes 2, 3, and 4 return NULL.*/static const void *columnName( sqlite3_stmt *pStmt, int N, const void *(*xFunc)(Mem*), int useType){ const void *ret = 0; Vdbe *p = (Vdbe *)pStmt; int n;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -