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. |