diff -r 7033022af10d -r 27307df4d711 extensions/sqlite/sqlite-source/vdbeapi.c --- a/extensions/sqlite/sqlite-source/vdbeapi.c Sun Oct 28 05:06:12 2007 +0000 +++ b/extensions/sqlite/sqlite-source/vdbeapi.c Sun Oct 28 05:48:06 2007 +0000 @@ -15,7 +15,6 @@ */ #include "sqliteInt.h" #include "vdbeInt.h" -#include "os.h" /* ** Return TRUE (non-zero) of the statement supplied as an argument needs @@ -30,6 +29,68 @@ return p==0 || p->expired; } +/* +** The following routine destroys a virtual machine that is created by +** the sqlite3_compile() routine. The integer returned is an SQLITE_ +** success/failure code that describes the result of executing the virtual +** machine. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + Vdbe *v = (Vdbe*)pStmt; + sqlite3_mutex *mutex = v->db->mutex; + sqlite3_mutex_enter(mutex); + rc = sqlite3VdbeFinalize(v); + sqlite3_mutex_leave(mutex); + } + return rc; +} + +/* +** Terminate the current execution of an SQL statement and reset it +** back to its starting state so that it can be reused. A success code from +** the prior execution is returned. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_reset(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + Vdbe *v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); + rc = sqlite3VdbeReset(v); + sqlite3VdbeMakeReady(v, -1, 0, 0, 0); + assert( (rc & (v->db->errMask))==rc ); + sqlite3_mutex_leave(v->db->mutex); + } + return rc; +} + +/* +** Set all the parameters in the compiled SQL statement to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + Vdbe *v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); + for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ + rc = sqlite3_bind_null(pStmt, i); + } + sqlite3_mutex_leave(v->db->mutex); + return rc; +} + + /**************************** sqlite3_value_ ******************************* ** The following routines extract information from a Mem or sqlite3_value ** structure. @@ -77,7 +138,6 @@ int sqlite3_value_type(sqlite3_value* pVal){ return pVal->type; } -/* sqlite3_value_numeric_type() defined in vdbe.c */ /**************************** sqlite3_result_ ******************************* ** The following routines are used by user-defined functions to specify @@ -90,28 +150,35 @@ void (*xDel)(void *) ){ assert( n>=0 ); + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel); } void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetDouble(&pCtx->s, rVal); } void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = 1; sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = 1; sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif void sqlite3_result_int(sqlite3_context *pCtx, int iVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal); } void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetInt64(&pCtx->s, iVal); } void sqlite3_result_null(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetNull(&pCtx->s); } void sqlite3_result_text( @@ -120,6 +187,7 @@ int n, void (*xDel)(void *) ){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel); } #ifndef SQLITE_OMIT_UTF16 @@ -129,6 +197,7 @@ int n, void (*xDel)(void *) ){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel); } void sqlite3_result_text16be( @@ -137,6 +206,7 @@ int n, void (*xDel)(void *) ){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel); } void sqlite3_result_text16le( @@ -145,21 +215,32 @@ int n, void (*xDel)(void *) ){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel); } #endif /* SQLITE_OMIT_UTF16 */ void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemCopy(&pCtx->s, pValue); } void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetZeroBlob(&pCtx->s, n); } /* Force an SQLITE_TOOBIG error. */ void sqlite3_result_error_toobig(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetZeroBlob(&pCtx->s, SQLITE_MAX_LENGTH+1); } +/* An SQLITE_NOMEM error. */ +void sqlite3_result_error_nomem(sqlite3_context *pCtx){ + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + sqlite3VdbeMemSetNull(&pCtx->s); + pCtx->isError = 1; + pCtx->s.db->mallocFailed = 1; +} /* ** Execute the statement pStmt, either until a row of data is ready, the @@ -175,7 +256,8 @@ int rc; /* Assert that malloc() has not failed */ - assert( !sqlite3MallocFailed() ); + db = p->db; + assert( !db->mallocFailed ); if( p==0 || p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; @@ -190,7 +272,6 @@ rc = SQLITE_ERROR; goto end_of_step; } - db = p->db; if( sqlite3SafetyOn(db) ){ p->rc = SQLITE_MISUSE; return SQLITE_MISUSE; @@ -221,7 +302,7 @@ } if( db->xProfile && !db->init.busy ){ double rNow; - sqlite3OsCurrentTime(&rNow); + sqlite3OsCurrentTime(db->pVfs, &rNow); p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0; } #endif @@ -258,7 +339,7 @@ double rNow; u64 elapseTime; - sqlite3OsCurrentTime(&rNow); + sqlite3OsCurrentTime(db->pVfs, &rNow); elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime; assert( p->nOp>0 ); assert( p->aOp[p->nOp-1].opcode==OP_Noop ); @@ -291,19 +372,27 @@ */ #ifdef SQLITE_OMIT_PARSER int sqlite3_step(sqlite3_stmt *pStmt){ - return sqlite3Step((Vdbe*)pStmt); + int rc; + Vdbe *v; + v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); + rc = sqlite3Step(v); + sqlite3_mutex_leave(v->db->mutex); + return rc; } #else int sqlite3_step(sqlite3_stmt *pStmt){ int cnt = 0; int rc; Vdbe *v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < 5 && sqlite3Reprepare(v) ){ sqlite3_reset(pStmt); v->expired = 0; } + sqlite3_mutex_leave(v->db->mutex); return rc; } #endif @@ -332,10 +421,10 @@ ){ const char *zName = context->pFunc->zName; char *zErr; - zErr = sqlite3MPrintf( + zErr = sqlite3MPrintf(0, "unable to use function %s in the requested context", zName); sqlite3_result_error(context, zErr, -1); - sqliteFree(zErr); + sqlite3_free(zErr); } /* @@ -344,21 +433,23 @@ ** same context that was returned on prior calls. */ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ - Mem *pMem = p->pMem; + 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 = sqlite3FreeX; + pMem->xDel = sqlite3_free; pMem->u.pDef = p->pFunc; if( nByte<=NBFS ){ pMem->z = pMem->zShort; memset(pMem->z, 0, nByte); }else{ - pMem->z = sqliteMalloc( nByte ); + pMem->z = sqlite3DbMallocZero(p->s.db, nByte); } } } @@ -370,7 +461,10 @@ ** the user-function defined by pCtx. */ void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){ - VdbeFunc *pVdbeFunc = pCtx->pVdbeFunc; + VdbeFunc *pVdbeFunc; + + assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); + pVdbeFunc = pCtx->pVdbeFunc; if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){ return 0; } @@ -390,16 +484,19 @@ ){ struct AuxData *pAuxData; VdbeFunc *pVdbeFunc; - if( iArg<0 ) return; + 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 = sqliteRealloc(pVdbeFunc, nMalloc); - if( !pVdbeFunc ) return; + pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc); + if( !pVdbeFunc ){ + goto failed; + } pCtx->pVdbeFunc = pVdbeFunc; - memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0, - sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux)); + memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux)); pVdbeFunc->nAux = iArg+1; pVdbeFunc->pFunc = pCtx->pFunc; } @@ -410,6 +507,12 @@ } pAuxData->pAux = pAux; pAuxData->xDelete = xDelete; + return; + +failed: + if( xDelete ){ + xDelete(pAux); + } } /* @@ -452,14 +555,24 @@ ** of NULL. */ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ - Vdbe *pVm = (Vdbe *)pStmt; - int vals = sqlite3_data_count(pStmt); - if( pVm==0 || pVm->resOnStack==0 || i>=pVm->nResColumn || i<0 ){ - static const Mem nullMem = {{0}, 0.0, "", 0, MEM_Null, SQLITE_NULL }; - sqlite3Error(pVm->db, SQLITE_RANGE, 0); - return (Mem*)&nullMem; + Vdbe *pVm; + int vals; + Mem *pOut; + + pVm = (Vdbe *)pStmt; + if( pVm && pVm->resOnStack && inResColumn && 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 &pVm->pTos[(1-vals)+i]; + return pOut; } /* @@ -469,7 +582,7 @@ ** malloc() has failed, the threads mallocFailed flag is cleared and the result ** code of statement pStmt set to SQLITE_NOMEM. ** -** Specificly, this is called from within: +** Specifically, this is called from within: ** ** sqlite3_column_int() ** sqlite3_column_int64() @@ -489,7 +602,10 @@ ** and _finalize() will return NOMEM. */ Vdbe *p = (Vdbe *)pStmt; - p->rc = sqlite3ApiExit(0, p->rc); + if( p ){ + p->rc = sqlite3ApiExit(p->db, p->rc); + sqlite3_mutex_leave(p->db->mutex); + } } /**************************** sqlite3_column_ ******************************* @@ -537,7 +653,9 @@ return val; } sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){ - return columnMem(pStmt, i); + sqlite3_value *pOut = columnMem(pStmt, i); + columnMallocFailure(pStmt); + return pOut; } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ @@ -547,7 +665,9 @@ } #endif /* SQLITE_OMIT_UTF16 */ int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ - return sqlite3_value_type( columnMem(pStmt,i) ); + int iType = sqlite3_value_type( columnMem(pStmt,i) ); + columnMallocFailure(pStmt); + return iType; } /* The following function is experimental and subject to change or @@ -579,20 +699,28 @@ const void *(*xFunc)(Mem*), int useType ){ - const void *ret; + const void *ret = 0; Vdbe *p = (Vdbe *)pStmt; - int n = sqlite3_column_count(pStmt); + int n; + + + if( p!=0 ){ + n = sqlite3_column_count(pStmt); + if( N=0 ){ + N += useType*n; + sqlite3_mutex_enter(p->db->mutex); + ret = xFunc(&p->aColName[N]); - if( p==0 || N>=n || N<0 ){ - return 0; + /* A malloc may have failed inside of the xFunc() call. If this + ** is the case, clear the mallocFailed flag and return NULL. + */ + if( p->db && p->db->mallocFailed ){ + p->db->mallocFailed = 0; + ret = 0; + } + sqlite3_mutex_leave(p->db->mutex); + } } - N += useType*n; - ret = xFunc(&p->aColName[N]); - - /* A malloc may have failed inside of the xFunc() call. If this is the case, - ** clear the mallocFailed flag and return NULL. - */ - sqlite3ApiExit(0, 0); return ret; } @@ -711,29 +839,33 @@ ** Bind a text or BLOB value. */ static int bindText( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, - void (*xDel)(void*), - int encoding + sqlite3_stmt *pStmt, /* The statement to bind against */ + int i, /* Index of the parameter to bind */ + const void *zData, /* Pointer to the data to be bound */ + int nData, /* Number of bytes of data to be bound */ + void (*xDel)(void*), /* Destructor for the data */ + int encoding /* Encoding for the data */ ){ Vdbe *p = (Vdbe *)pStmt; Mem *pVar; int rc; - rc = vdbeUnbind(p, i); - if( rc || zData==0 ){ - return rc; + if( p==0 ){ + return SQLITE_MISUSE; } - pVar = &p->aVar[i-1]; - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK && zData!=0 ){ + pVar = &p->aVar[i-1]; + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); + if( rc==SQLITE_OK && encoding!=0 ){ + rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + } + sqlite3Error(p->db, rc, 0); + rc = sqlite3ApiExit(p->db, rc); } - - sqlite3Error(((Vdbe *)pStmt)->db, rc, 0); - return sqlite3ApiExit(((Vdbe *)pStmt)->db, rc); + sqlite3_mutex_leave(p->db->mutex); + return rc; } @@ -752,10 +884,12 @@ int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); } + sqlite3_mutex_leave(p->db->mutex); return rc; } int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ @@ -764,14 +898,21 @@ int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); } + sqlite3_mutex_leave(p->db->mutex); return rc; } -int sqlite3_bind_null(sqlite3_stmt* p, int i){ - return vdbeUnbind((Vdbe *)p, i); +int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + sqlite3_mutex_leave(p->db->mutex); + return rc; } int sqlite3_bind_text( sqlite3_stmt *pStmt, @@ -796,19 +937,23 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - sqlite3VdbeMemCopy(&p->aVar[i-1], pValue); + rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue); } + sqlite3_mutex_leave(p->db->mutex); return rc; } int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); } + sqlite3_mutex_leave(p->db->mutex); return rc; } @@ -828,15 +973,19 @@ */ static void createVarMap(Vdbe *p){ if( !p->okVar ){ - int j; - Op *pOp; - for(j=0, pOp=p->aOp; jnOp; j++, pOp++){ - if( pOp->opcode==OP_Variable ){ - assert( pOp->p1>0 && pOp->p1<=p->nVar ); - p->azVar[pOp->p1-1] = pOp->p3; + sqlite3_mutex_enter(p->db->mutex); + if( !p->okVar ){ + int j; + Op *pOp; + for(j=0, pOp=p->aOp; jnOp; j++, pOp++){ + if( pOp->opcode==OP_Variable ){ + assert( pOp->p1>0 && pOp->p1<=p->nVar ); + p->azVar[pOp->p1-1] = pOp->p3; + } } + p->okVar = 1; } - p->okVar = 1; + sqlite3_mutex_leave(p->db->mutex); } } @@ -888,17 +1037,20 @@ Vdbe *pTo = (Vdbe*)pToStmt; int i, rc = SQLITE_OK; if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT) - || (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT) ){ + || (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT) + || pTo->db!=pFrom->db ){ return SQLITE_MISUSE; } if( pFrom->nVar!=pTo->nVar ){ return SQLITE_ERROR; } + sqlite3_mutex_enter(pTo->db->mutex); for(i=0; rc==SQLITE_OK && inVar; i++){ sqlite3MallocDisallow(); rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]); sqlite3MallocAllow(); } + sqlite3_mutex_leave(pTo->db->mutex); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); return rc; }