| Index: third_party/sqlite/src/src/vdbeapi.c
|
| diff --git a/third_party/sqlite/src/src/vdbeapi.c b/third_party/sqlite/src/src/vdbeapi.c
|
| index 33c6ba3b287e9a45eb9beaf6d89cda513a029cfd..6eb97f1d1ddb0ce90158d866d0a5dd9cdd3e7610 100644
|
| --- a/third_party/sqlite/src/src/vdbeapi.c
|
| +++ b/third_party/sqlite/src/src/vdbeapi.c
|
| @@ -60,12 +60,19 @@ static int vdbeSafetyNotNull(Vdbe *p){
|
| */
|
| static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
|
| sqlite3_int64 iNow;
|
| + sqlite3_int64 iElapse;
|
| assert( p->startTime>0 );
|
| - assert( db->xProfile!=0 );
|
| + assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
|
| assert( db->init.busy==0 );
|
| assert( p->zSql!=0 );
|
| sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
|
| - db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
|
| + iElapse = (iNow - p->startTime)*1000000;
|
| + if( db->xProfile ){
|
| + db->xProfile(db->pProfileArg, p->zSql, iElapse);
|
| + }
|
| + if( db->mTrace & SQLITE_TRACE_PROFILE ){
|
| + db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
|
| + }
|
| p->startTime = 0;
|
| }
|
| /*
|
| @@ -162,7 +169,7 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
|
| const void *sqlite3_value_blob(sqlite3_value *pVal){
|
| Mem *p = (Mem*)pVal;
|
| if( p->flags & (MEM_Blob|MEM_Str) ){
|
| - if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){
|
| + if( ExpandBlob(p)!=SQLITE_OK ){
|
| assert( p->flags==MEM_Null && p->z==0 );
|
| return 0;
|
| }
|
| @@ -188,7 +195,8 @@ sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
|
| return sqlite3VdbeIntValue((Mem*)pVal);
|
| }
|
| unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
|
| - return ((Mem*)pVal)->eSubtype;
|
| + Mem *pMem = (Mem*)pVal;
|
| + return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
|
| }
|
| const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
|
| return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
|
| @@ -369,8 +377,10 @@ void sqlite3_result_null(sqlite3_context *pCtx){
|
| sqlite3VdbeMemSetNull(pCtx->pOut);
|
| }
|
| void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
|
| - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| - pCtx->pOut->eSubtype = eSubtype & 0xff;
|
| + Mem *pOut = pCtx->pOut;
|
| + assert( sqlite3_mutex_held(pOut->db->mutex) );
|
| + pOut->eSubtype = eSubtype & 0xff;
|
| + pOut->flags |= MEM_Subtype;
|
| }
|
| void sqlite3_result_text(
|
| sqlite3_context *pCtx,
|
| @@ -468,9 +478,9 @@ void sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
| void sqlite3_result_error_nomem(sqlite3_context *pCtx){
|
| assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
| sqlite3VdbeMemSetNull(pCtx->pOut);
|
| - pCtx->isError = SQLITE_NOMEM;
|
| + pCtx->isError = SQLITE_NOMEM_BKPT;
|
| pCtx->fErrorOrAux = 1;
|
| - pCtx->pOut->db->mallocFailed = 1;
|
| + sqlite3OomFault(pCtx->pOut->db);
|
| }
|
|
|
| /*
|
| @@ -489,7 +499,7 @@ static int doWalCallbacks(sqlite3 *db){
|
| nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
|
| sqlite3BtreeLeave(pBt);
|
| if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
|
| - rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
|
| + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry);
|
| }
|
| }
|
| }
|
| @@ -544,7 +554,7 @@ static int sqlite3Step(Vdbe *p){
|
| db = p->db;
|
| if( db->mallocFailed ){
|
| p->rc = SQLITE_NOMEM;
|
| - return SQLITE_NOMEM;
|
| + return SQLITE_NOMEM_BKPT;
|
| }
|
|
|
| if( p->pc<=0 && p->expired ){
|
| @@ -566,7 +576,8 @@ static int sqlite3Step(Vdbe *p){
|
| );
|
|
|
| #ifndef SQLITE_OMIT_TRACE
|
| - if( db->xProfile && !db->init.busy && p->zSql ){
|
| + if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
|
| + && !db->init.busy && p->zSql ){
|
| sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
|
| }else{
|
| assert( p->startTime==0 );
|
| @@ -607,7 +618,7 @@ static int sqlite3Step(Vdbe *p){
|
|
|
| db->errCode = rc;
|
| if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
|
| - p->rc = SQLITE_NOMEM;
|
| + p->rc = SQLITE_NOMEM_BKPT;
|
| }
|
| end_of_step:
|
| /* At this point local variable rc holds the value that should be
|
| @@ -674,7 +685,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
| v->rc = rc2;
|
| } else {
|
| v->zErrMsg = 0;
|
| - v->rc = rc = SQLITE_NOMEM;
|
| + v->rc = rc = SQLITE_NOMEM_BKPT;
|
| }
|
| }
|
| rc = sqlite3ApiExit(db, rc);
|
| @@ -779,7 +790,7 @@ static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){
|
| ** same context that was returned on prior calls.
|
| */
|
| void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
|
| - assert( p && p->pFunc && p->pFunc->xStep );
|
| + assert( p && p->pFunc && p->pFunc->xFinalize );
|
| assert( sqlite3_mutex_held(p->pOut->db->mutex) );
|
| testcase( nByte<0 );
|
| if( (p->pMem->flags & MEM_Agg)==0 ){
|
| @@ -870,7 +881,7 @@ failed:
|
| ** context.
|
| */
|
| int sqlite3_aggregate_count(sqlite3_context *p){
|
| - assert( p && p->pMem && p->pFunc && p->pFunc->xStep );
|
| + assert( p && p->pMem && p->pFunc && p->pFunc->xFinalize );
|
| return p->pMem->n;
|
| }
|
| #endif
|
| @@ -941,14 +952,13 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
|
| Mem *pOut;
|
|
|
| pVm = (Vdbe *)pStmt;
|
| - if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
|
| - sqlite3_mutex_enter(pVm->db->mutex);
|
| + if( pVm==0 ) return (Mem*)columnNullValue();
|
| + assert( pVm->db );
|
| + sqlite3_mutex_enter(pVm->db->mutex);
|
| + if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
|
| pOut = &pVm->pResultSet[i];
|
| }else{
|
| - if( pVm && ALWAYS(pVm->db) ){
|
| - sqlite3_mutex_enter(pVm->db->mutex);
|
| - sqlite3Error(pVm->db, SQLITE_RANGE);
|
| - }
|
| + sqlite3Error(pVm->db, SQLITE_RANGE);
|
| pOut = (Mem*)columnNullValue();
|
| }
|
| return pOut;
|
| @@ -981,6 +991,8 @@ static void columnMallocFailure(sqlite3_stmt *pStmt)
|
| */
|
| Vdbe *p = (Vdbe *)pStmt;
|
| if( p ){
|
| + assert( p->db!=0 );
|
| + assert( sqlite3_mutex_held(p->db->mutex) );
|
| p->rc = sqlite3ApiExit(p->db, p->rc);
|
| sqlite3_mutex_leave(p->db->mutex);
|
| }
|
| @@ -1098,7 +1110,7 @@ static const void *columnName(
|
| ** is the case, clear the mallocFailed flag and return NULL.
|
| */
|
| if( db->mallocFailed ){
|
| - db->mallocFailed = 0;
|
| + sqlite3OomClear(db);
|
| ret = 0;
|
| }
|
| sqlite3_mutex_leave(db->mutex);
|
| @@ -1298,6 +1310,9 @@ int sqlite3_bind_blob(
|
| int nData,
|
| void (*xDel)(void*)
|
| ){
|
| +#ifdef SQLITE_ENABLE_API_ARMOR
|
| + if( nData<0 ) return SQLITE_MISUSE_BKPT;
|
| +#endif
|
| return bindText(pStmt, i, zData, nData, xDel, 0);
|
| }
|
| int sqlite3_bind_blob64(
|
| @@ -1455,10 +1470,8 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
|
| */
|
| const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
|
| Vdbe *p = (Vdbe*)pStmt;
|
| - if( p==0 || i<1 || i>p->nzVar ){
|
| - return 0;
|
| - }
|
| - return p->azVar[i-1];
|
| + if( p==0 ) return 0;
|
| + return sqlite3VListNumToName(p->pVList, i);
|
| }
|
|
|
| /*
|
| @@ -1467,19 +1480,8 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
|
| ** return 0.
|
| */
|
| int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
|
| - int i;
|
| - if( p==0 ){
|
| - return 0;
|
| - }
|
| - if( zName ){
|
| - for(i=0; i<p->nzVar; i++){
|
| - const char *z = p->azVar[i];
|
| - if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
|
| - return i+1;
|
| - }
|
| - }
|
| - }
|
| - return 0;
|
| + if( p==0 || zName==0 ) return 0;
|
| + return sqlite3VListNameToNum(p->pVList, zName, nName);
|
| }
|
| int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
|
| return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
|
| @@ -1554,7 +1556,7 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
|
| */
|
| int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
|
| Vdbe *v = (Vdbe*)pStmt;
|
| - return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
|
| + return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
|
| }
|
|
|
| /*
|
| @@ -1598,6 +1600,225 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
| return (int)v;
|
| }
|
|
|
| +/*
|
| +** Return the SQL associated with a prepared statement
|
| +*/
|
| +const char *sqlite3_sql(sqlite3_stmt *pStmt){
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + return p ? p->zSql : 0;
|
| +}
|
| +
|
| +/*
|
| +** Return the SQL associated with a prepared statement with
|
| +** bound parameters expanded. Space to hold the returned string is
|
| +** obtained from sqlite3_malloc(). The caller is responsible for
|
| +** freeing the returned string by passing it to sqlite3_free().
|
| +**
|
| +** The SQLITE_TRACE_SIZE_LIMIT puts an upper bound on the size of
|
| +** expanded bound parameters.
|
| +*/
|
| +char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
|
| +#ifdef SQLITE_OMIT_TRACE
|
| + return 0;
|
| +#else
|
| + char *z = 0;
|
| + const char *zSql = sqlite3_sql(pStmt);
|
| + if( zSql ){
|
| + Vdbe *p = (Vdbe *)pStmt;
|
| + sqlite3_mutex_enter(p->db->mutex);
|
| + z = sqlite3VdbeExpandSql(p, zSql);
|
| + sqlite3_mutex_leave(p->db->mutex);
|
| + }
|
| + return z;
|
| +#endif
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
| +/*
|
| +** Allocate and populate an UnpackedRecord structure based on the serialized
|
| +** record in nKey/pKey. Return a pointer to the new UnpackedRecord structure
|
| +** if successful, or a NULL pointer if an OOM error is encountered.
|
| +*/
|
| +static UnpackedRecord *vdbeUnpackRecord(
|
| + KeyInfo *pKeyInfo,
|
| + int nKey,
|
| + const void *pKey
|
| +){
|
| + UnpackedRecord *pRet; /* Return value */
|
| +
|
| + pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
|
| + if( pRet ){
|
| + memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1));
|
| + sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
|
| + }
|
| + return pRet;
|
| +}
|
| +
|
| +/*
|
| +** This function is called from within a pre-update callback to retrieve
|
| +** a field of the row currently being updated or deleted.
|
| +*/
|
| +int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
| + PreUpdate *p = db->pPreUpdate;
|
| + Mem *pMem;
|
| + int rc = SQLITE_OK;
|
| +
|
| + /* Test that this call is being made from within an SQLITE_DELETE or
|
| + ** SQLITE_UPDATE pre-update callback, and that iIdx is within range. */
|
| + if( !p || p->op==SQLITE_INSERT ){
|
| + rc = SQLITE_MISUSE_BKPT;
|
| + goto preupdate_old_out;
|
| + }
|
| + if( p->pPk ){
|
| + iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
|
| + }
|
| + if( iIdx>=p->pCsr->nField || iIdx<0 ){
|
| + rc = SQLITE_RANGE;
|
| + goto preupdate_old_out;
|
| + }
|
| +
|
| + /* If the old.* record has not yet been loaded into memory, do so now. */
|
| + if( p->pUnpacked==0 ){
|
| + u32 nRec;
|
| + u8 *aRec;
|
| +
|
| + nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
|
| + aRec = sqlite3DbMallocRaw(db, nRec);
|
| + if( !aRec ) goto preupdate_old_out;
|
| + rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
|
| + if( rc==SQLITE_OK ){
|
| + p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
|
| + if( !p->pUnpacked ) rc = SQLITE_NOMEM;
|
| + }
|
| + if( rc!=SQLITE_OK ){
|
| + sqlite3DbFree(db, aRec);
|
| + goto preupdate_old_out;
|
| + }
|
| + p->aRecord = aRec;
|
| + }
|
| +
|
| + pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
|
| + if( iIdx==p->pTab->iPKey ){
|
| + sqlite3VdbeMemSetInt64(pMem, p->iKey1);
|
| + }else if( iIdx>=p->pUnpacked->nField ){
|
| + *ppValue = (sqlite3_value *)columnNullValue();
|
| + }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
|
| + if( pMem->flags & MEM_Int ){
|
| + sqlite3VdbeMemRealify(pMem);
|
| + }
|
| + }
|
| +
|
| + preupdate_old_out:
|
| + sqlite3Error(db, rc);
|
| + return sqlite3ApiExit(db, rc);
|
| +}
|
| +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
| +
|
| +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
| +/*
|
| +** This function is called from within a pre-update callback to retrieve
|
| +** the number of columns in the row being updated, deleted or inserted.
|
| +*/
|
| +int sqlite3_preupdate_count(sqlite3 *db){
|
| + PreUpdate *p = db->pPreUpdate;
|
| + return (p ? p->keyinfo.nField : 0);
|
| +}
|
| +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
| +
|
| +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
| +/*
|
| +** This function is designed to be called from within a pre-update callback
|
| +** only. It returns zero if the change that caused the callback was made
|
| +** immediately by a user SQL statement. Or, if the change was made by a
|
| +** trigger program, it returns the number of trigger programs currently
|
| +** on the stack (1 for a top-level trigger, 2 for a trigger fired by a
|
| +** top-level trigger etc.).
|
| +**
|
| +** For the purposes of the previous paragraph, a foreign key CASCADE, SET NULL
|
| +** or SET DEFAULT action is considered a trigger.
|
| +*/
|
| +int sqlite3_preupdate_depth(sqlite3 *db){
|
| + PreUpdate *p = db->pPreUpdate;
|
| + return (p ? p->v->nFrame : 0);
|
| +}
|
| +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
| +
|
| +#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
| +/*
|
| +** This function is called from within a pre-update callback to retrieve
|
| +** a field of the row currently being updated or inserted.
|
| +*/
|
| +int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
| + PreUpdate *p = db->pPreUpdate;
|
| + int rc = SQLITE_OK;
|
| + Mem *pMem;
|
| +
|
| + if( !p || p->op==SQLITE_DELETE ){
|
| + rc = SQLITE_MISUSE_BKPT;
|
| + goto preupdate_new_out;
|
| + }
|
| + if( p->pPk && p->op!=SQLITE_UPDATE ){
|
| + iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
|
| + }
|
| + if( iIdx>=p->pCsr->nField || iIdx<0 ){
|
| + rc = SQLITE_RANGE;
|
| + goto preupdate_new_out;
|
| + }
|
| +
|
| + if( p->op==SQLITE_INSERT ){
|
| + /* For an INSERT, memory cell p->iNewReg contains the serialized record
|
| + ** that is being inserted. Deserialize it. */
|
| + UnpackedRecord *pUnpack = p->pNewUnpacked;
|
| + if( !pUnpack ){
|
| + Mem *pData = &p->v->aMem[p->iNewReg];
|
| + rc = ExpandBlob(pData);
|
| + if( rc!=SQLITE_OK ) goto preupdate_new_out;
|
| + pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
|
| + if( !pUnpack ){
|
| + rc = SQLITE_NOMEM;
|
| + goto preupdate_new_out;
|
| + }
|
| + p->pNewUnpacked = pUnpack;
|
| + }
|
| + pMem = &pUnpack->aMem[iIdx];
|
| + if( iIdx==p->pTab->iPKey ){
|
| + sqlite3VdbeMemSetInt64(pMem, p->iKey2);
|
| + }else if( iIdx>=pUnpack->nField ){
|
| + pMem = (sqlite3_value *)columnNullValue();
|
| + }
|
| + }else{
|
| + /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
|
| + ** value. Make a copy of the cell contents and return a pointer to it.
|
| + ** It is not safe to return a pointer to the memory cell itself as the
|
| + ** caller may modify the value text encoding.
|
| + */
|
| + assert( p->op==SQLITE_UPDATE );
|
| + if( !p->aNew ){
|
| + p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField);
|
| + if( !p->aNew ){
|
| + rc = SQLITE_NOMEM;
|
| + goto preupdate_new_out;
|
| + }
|
| + }
|
| + assert( iIdx>=0 && iIdx<p->pCsr->nField );
|
| + pMem = &p->aNew[iIdx];
|
| + if( pMem->flags==0 ){
|
| + if( iIdx==p->pTab->iPKey ){
|
| + sqlite3VdbeMemSetInt64(pMem, p->iKey2);
|
| + }else{
|
| + rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
|
| + if( rc!=SQLITE_OK ) goto preupdate_new_out;
|
| + }
|
| + }
|
| + }
|
| + *ppValue = pMem;
|
| +
|
| + preupdate_new_out:
|
| + sqlite3Error(db, rc);
|
| + return sqlite3ApiExit(db, rc);
|
| +}
|
| +#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
| +
|
| #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| /*
|
| ** Return status data for a single loop within query pStmt.
|
|
|