#include "sqliteInt.h"
#include "vdbeInt.h"
#include "opcodes.h"
#ifndef SQLITE_OMIT_DEPRECATED
int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
#endif
static int vdbeSafety(Vdbe *p){
if( p->db==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
return 1;
}else{
return 0;
}
}
static int vdbeSafetyNotNull(Vdbe *p){
if( p==0 ){
sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
return 1;
}else{
return vdbeSafety(p);
}
}
#ifndef SQLITE_OMIT_TRACE
static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
iElapse = (iNow - p->startTime)*1000000;
#ifndef SQLITE_OMIT_DEPRECATED
if( db->xProfile ){
db->xProfile(db->pProfileArg, p->zSql, iElapse);
}
#endif
if( db->mTrace & SQLITE_TRACE_PROFILE ){
db->trace.xV2(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
}
p->startTime = 0;
}
# define checkProfileCallback(DB,P) \
if( ((P)->startTime)>0 ){ invokeProfileCallback(DB,P); }
#else
# define checkProfileCallback(DB,P)
#endif
int sqlite3_finalize(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
sqlite3_mutex_enter(db->mutex);
checkProfileCallback(db, v);
assert( v->eVdbeState>=VDBE_READY_STATE );
rc = sqlite3VdbeReset(v);
sqlite3VdbeDelete(v);
rc = sqlite3ApiExit(db, rc);
sqlite3LeaveMutexAndCloseZombie(db);
}
return rc;
}
int sqlite3_reset(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3 *db = v->db;
sqlite3_mutex_enter(db->mutex);
checkProfileCallback(db, v);
rc = sqlite3VdbeReset(v);
sqlite3VdbeRewind(v);
assert( (rc & (db->errMask))==rc );
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
}
return rc;
}
int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
for(i=0; i<p->nVar; i++){
sqlite3VdbeMemRelease(&p->aVar[i]);
p->aVar[i].flags = MEM_Null;
}
assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
if( p->expmask ){
p->expired = 1;
}
sqlite3_mutex_leave(mutex);
return rc;
}
const void *sqlite3_value_blob(sqlite3_value *pVal){
Mem *p = (Mem*)pVal;
if( p->flags & (MEM_Blob|MEM_Str) ){
if( ExpandBlob(p)!=SQLITE_OK ){
assert( p->flags==MEM_Null && p->z==0 );
return 0;
}
p->flags |= MEM_Blob;
return p->n ? p->z : 0;
}else{
return sqlite3_value_text(pVal);
}
}
int sqlite3_value_bytes(sqlite3_value *pVal){
return sqlite3ValueBytes(pVal, SQLITE_UTF8);
}
int sqlite3_value_bytes16(sqlite3_value *pVal){
return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE);
}
double sqlite3_value_double(sqlite3_value *pVal){
return sqlite3VdbeRealValue((Mem*)pVal);
}
int sqlite3_value_int(sqlite3_value *pVal){
return (int)sqlite3VdbeIntValue((Mem*)pVal);
}
sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
return sqlite3VdbeIntValue((Mem*)pVal);
}
unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
Mem *pMem = (Mem*)pVal;
return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
}
void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){
Mem *p = (Mem*)pVal;
if( (p->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
(MEM_Null|MEM_Term|MEM_Subtype)
&& zPType!=0
&& p->eSubtype=='p'
&& strcmp(p->u.zPType, zPType)==0
){
return (void*)p->z;
}else{
return 0;
}
}
const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_value_text16(sqlite3_value* pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
}
const void *sqlite3_value_text16be(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16BE);
}
const void *sqlite3_value_text16le(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16LE);
}
#endif
int sqlite3_value_type(sqlite3_value* pVal){
static const u8 aType[] = {
SQLITE_BLOB,
SQLITE_NULL,
SQLITE_TEXT,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_BLOB,
SQLITE_NULL,
SQLITE_TEXT,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_INTEGER,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_BLOB,
SQLITE_NULL,
SQLITE_TEXT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
SQLITE_FLOAT,
SQLITE_NULL,
};
#ifdef SQLITE_DEBUG
{
int eType = SQLITE_BLOB;
if( pVal->flags & MEM_Null ){
eType = SQLITE_NULL;
}else if( pVal->flags & (MEM_Real|MEM_IntReal) ){
eType = SQLITE_FLOAT;
}else if( pVal->flags & MEM_Int ){
eType = SQLITE_INTEGER;
}else if( pVal->flags & MEM_Str ){
eType = SQLITE_TEXT;
}
assert( eType == aType[pVal->flags&MEM_AffMask] );
}
#endif
return aType[pVal->flags&MEM_AffMask];
}
int sqlite3_value_encoding(sqlite3_value *pVal){
return pVal->enc;
}
int sqlite3_value_nochange(sqlite3_value *pVal){
return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
}
int sqlite3_value_frombind(sqlite3_value *pVal){
return (pVal->flags&MEM_FromBind)!=0;
}
sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
sqlite3_value *pNew;
if( pOrig==0 ) return 0;
pNew = sqlite3_malloc( sizeof(*pNew) );
if( pNew==0 ) return 0;
memset(pNew, 0, sizeof(*pNew));
memcpy(pNew, pOrig, MEMCELLSIZE);
pNew->flags &= ~MEM_Dyn;
pNew->db = 0;
if( pNew->flags&(MEM_Str|MEM_Blob) ){
pNew->flags &= ~(MEM_Static|MEM_Dyn);
pNew->flags |= MEM_Ephem;
if( sqlite3VdbeMemMakeWriteable(pNew)!=SQLITE_OK ){
sqlite3ValueFree(pNew);
pNew = 0;
}
}else if( pNew->flags & MEM_Null ){
pNew->flags &= ~(MEM_Term|MEM_Subtype);
}
return pNew;
}
void sqlite3_value_free(sqlite3_value *pOld){
sqlite3ValueFree(pOld);
}
static void setResultStrOrError(
sqlite3_context *pCtx,
const char *z,
int n,
u8 enc,
void (*xDel)(void*)
){
Mem *pOut = pCtx->pOut;
int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
if( rc ){
if( rc==SQLITE_TOOBIG ){
sqlite3_result_error_toobig(pCtx);
}else{
assert( rc==SQLITE_NOMEM );
sqlite3_result_error_nomem(pCtx);
}
return;
}
sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
if( sqlite3VdbeMemTooBig(pOut) ){
sqlite3_result_error_toobig(pCtx);
}
}
static int invokeValueDestructor(
const void *p,
void (*xDel)(void*),
sqlite3_context *pCtx
){
assert( xDel!=SQLITE_DYNAMIC );
if( xDel==0 ){
}else if( xDel==SQLITE_TRANSIENT ){
}else{
xDel((void*)p);
}
sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
void sqlite3_result_blob(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
assert( n>=0 );
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, 0, xDel);
}
void sqlite3_result_blob64(
sqlite3_context *pCtx,
const void *z,
sqlite3_uint64 n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, 0, xDel);
}
}
void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
}
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_ERROR;
sqlite3VdbeMemSetStr(pCtx->pOut, 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->pOut->db->mutex) );
pCtx->isError = SQLITE_ERROR;
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal);
}
void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
}
void sqlite3_result_null(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
}
void sqlite3_result_pointer(
sqlite3_context *pCtx,
void *pPtr,
const char *zPType,
void (*xDestructor)(void*)
){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
sqlite3VdbeMemRelease(pOut);
pOut->flags = MEM_Null;
sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
}
void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
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,
const char *z,
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
}
void sqlite3_result_text64(
sqlite3_context *pCtx,
const char *z,
sqlite3_uint64 n,
void (*xDel)(void *),
unsigned char enc
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( xDel!=SQLITE_DYNAMIC );
if( enc!=SQLITE_UTF8 ){
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
n &= ~(u64)1;
}
if( n>0x7fffffff ){
(void)invokeValueDestructor(z, xDel, pCtx);
}else{
setResultStrOrError(pCtx, z, (int)n, enc, xDel);
}
}
#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_text16(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16NATIVE, xDel);
}
void sqlite3_result_text16be(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16BE, xDel);
}
void sqlite3_result_text16le(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16LE, xDel);
}
#endif
void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemCopy(pOut, pValue);
sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
if( sqlite3VdbeMemTooBig(pOut) ){
sqlite3_result_error_toobig(pCtx);
}
}
void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0);
}
int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pOut->db->mutex) );
if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
return SQLITE_OK;
#else
return sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
#endif
}
void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode ? errCode : -1;
#ifdef SQLITE_DEBUG
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8,
SQLITE_STATIC);
}
}
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
void sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
pCtx->isError = SQLITE_NOMEM_BKPT;
sqlite3OomFault(pCtx->pOut->db);
}
#ifndef SQLITE_UNTESTABLE
void sqlite3ResultIntReal(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
if( pCtx->pOut->flags & MEM_Int ){
pCtx->pOut->flags &= ~MEM_Int;
pCtx->pOut->flags |= MEM_IntReal;
}
}
#endif
static int doWalCallbacks(sqlite3 *db){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_WAL
int i;
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
int nEntry;
sqlite3BtreeEnter(pBt);
nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){
rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry);
}
}
}
#endif
return rc;
}
static int sqlite3Step(Vdbe *p){
sqlite3 *db;
int rc;
assert(p);
db = p->db;
if( p->eVdbeState!=VDBE_RUN_STATE ){
restart_step:
if( p->eVdbeState==VDBE_READY_STATE ){
if( p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
rc = sqlite3VdbeTransferError(p);
}
goto end_of_step;
}
if( db->nVdbeActive==0 ){
AtomicStore(&db->u1.isInterrupted, 0);
}
assert( db->nVdbeWrite>0 || db->autoCommit==0
|| (db->nDeferredCons==0 && db->nDeferredImmCons==0)
);
#ifndef SQLITE_OMIT_TRACE
if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
&& !db->init.busy && p->zSql ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}else{
assert( p->startTime==0 );
}
#endif
db->nVdbeActive++;
if( p->readOnly==0 ) db->nVdbeWrite++;
if( p->bIsReader ) db->nVdbeRead++;
p->pc = 0;
p->eVdbeState = VDBE_RUN_STATE;
}else
if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){
#ifdef SQLITE_OMIT_AUTORESET
if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
sqlite3_reset((sqlite3_stmt*)p);
}else{
return SQLITE_MISUSE_BKPT;
}
#else
sqlite3_reset((sqlite3_stmt*)p);
#endif
assert( p->eVdbeState==VDBE_READY_STATE );
goto restart_step;
}
}
#ifdef SQLITE_DEBUG
p->rcApp = SQLITE_OK;
#endif
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
}else
#endif
{
db->nVdbeExec++;
rc = sqlite3VdbeExec(p);
db->nVdbeExec--;
}
if( rc==SQLITE_ROW ){
assert( p->rc==SQLITE_OK );
assert( db->mallocFailed==0 );
db->errCode = SQLITE_ROW;
return SQLITE_ROW;
}else{
#ifndef SQLITE_OMIT_TRACE
checkProfileCallback(db, p);
#endif
p->pResultRow = 0;
if( rc==SQLITE_DONE && db->autoCommit ){
assert( p->rc==SQLITE_OK );
p->rc = doWalCallbacks(db);
if( p->rc!=SQLITE_OK ){
rc = SQLITE_ERROR;
}
}else if( rc!=SQLITE_DONE && (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
rc = sqlite3VdbeTransferError(p);
}
}
db->errCode = rc;
if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
p->rc = SQLITE_NOMEM_BKPT;
if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ) rc = p->rc;
}
end_of_step:
assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
|| rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
return (rc&db->errMask);
}
int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_OK;
Vdbe *v = (Vdbe*)pStmt;
int cnt = 0;
sqlite3 *db;
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 ){
int savedPc = v->pc;
rc = sqlite3Reprepare(v);
if( rc!=SQLITE_OK ){
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
v->rc = rc = sqlite3ApiExit(db, rc);
} else {
v->zErrMsg = 0;
v->rc = rc = SQLITE_NOMEM_BKPT;
}
break;
}
sqlite3_reset(pStmt);
if( savedPc>=0 ){
v->minWriteFileFormat = 254;
}
assert( v->expired==0 );
}
sqlite3_mutex_leave(db->mutex);
return rc;
}
void *sqlite3_user_data(sqlite3_context *p){
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
assert( p && p->pOut );
return p->pOut->db;
}
int sqlite3_vtab_nochange(sqlite3_context *p){
assert( p );
return sqlite3_value_nochange(p->pOut);
}
void sqlite3VdbeValueListFree(void *pToDelete){
sqlite3_free(pToDelete);
}
static int valueFromValueList(
sqlite3_value *pVal,
sqlite3_value **ppOut,
int bNext
){
int rc;
ValueList *pRhs;
*ppOut = 0;
if( pVal==0 ) return SQLITE_MISUSE;
if( (pVal->flags & MEM_Dyn)==0 || pVal->xDel!=sqlite3VdbeValueListFree ){
return SQLITE_ERROR;
}else{
assert( (pVal->flags&(MEM_TypeMask|MEM_Term|MEM_Subtype)) ==
(MEM_Null|MEM_Term|MEM_Subtype) );
assert( pVal->eSubtype=='p' );
assert( pVal->u.zPType!=0 && strcmp(pVal->u.zPType,"ValueList")==0 );
pRhs = (ValueList*)pVal->z;
}
if( bNext ){
rc = sqlite3BtreeNext(pRhs->pCsr, 0);
}else{
int dummy = 0;
rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy);
assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) );
if( sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE;
}
if( rc==SQLITE_OK ){
u32 sz;
Mem sMem;
memset(&sMem, 0, sizeof(sMem));
sz = sqlite3BtreePayloadSize(pRhs->pCsr);
rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
if( rc==SQLITE_OK ){
u8 *zBuf = (u8*)sMem.z;
u32 iSerial;
sqlite3_value *pOut = pRhs->pOut;
int iOff = 1 + getVarint32(&zBuf[1], iSerial);
sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut);
pOut->enc = ENC(pOut->db);
if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){
rc = SQLITE_NOMEM;
}else{
*ppOut = pOut;
}
}
sqlite3VdbeMemRelease(&sMem);
}
return rc;
}
int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){
return valueFromValueList(pVal, ppOut, 0);
}
int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){
return valueFromValueList(pVal, ppOut, 1);
}
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
int rc;
#ifndef SQLITE_ENABLE_STAT4
sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
assert( p->pVdbe!=0 );
#else
sqlite3_int64 iTime = 0;
sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
#endif
if( *piTime==0 ){
rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
if( rc ) *piTime = 0;
}
return *piTime;
}
static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){
Mem *pMem = p->pMem;
assert( (pMem->flags & MEM_Agg)==0 );
if( nByte<=0 ){
sqlite3VdbeMemSetNull(pMem);
pMem->z = 0;
}else{
sqlite3VdbeMemClearAndResize(pMem, nByte);
pMem->flags = MEM_Agg;
pMem->u.pDef = p->pFunc;
if( pMem->z ){
memset(pMem->z, 0, nByte);
}
}
return (void*)pMem->z;
}
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
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 ){
return createAggContext(p, nByte);
}else{
return (void*)p->pMem->z;
}
}
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
#if SQLITE_ENABLE_STAT4
if( pCtx->pVdbe==0 ) return 0;
#else
assert( pCtx->pVdbe!=0 );
#endif
for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
return pAuxData->pAux;
}
}
return 0;
}
void sqlite3_set_auxdata(
sqlite3_context *pCtx,
int iArg,
void *pAux,
void (*xDelete)(void*)
){
AuxData *pAuxData;
Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
#ifdef SQLITE_ENABLE_STAT4
if( pVdbe==0 ) goto failed;
#else
assert( pVdbe!=0 );
#endif
for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNextAux){
if( pAuxData->iAuxArg==iArg && (pAuxData->iAuxOp==pCtx->iOp || iArg<0) ){
break;
}
}
if( pAuxData==0 ){
pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
if( !pAuxData ) goto failed;
pAuxData->iAuxOp = pCtx->iOp;
pAuxData->iAuxArg = iArg;
pAuxData->pNextAux = pVdbe->pAuxData;
pVdbe->pAuxData = pAuxData;
if( pCtx->isError==0 ) pCtx->isError = -1;
}else if( pAuxData->xDeleteAux ){
pAuxData->xDeleteAux(pAuxData->pAux);
}
pAuxData->pAux = pAux;
pAuxData->xDeleteAux = xDelete;
return;
failed:
if( xDelete ){
xDelete(pAux);
}
}
#ifndef SQLITE_OMIT_DEPRECATED
int sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pMem && p->pFunc && p->pFunc->xFinalize );
return p->pMem->n;
}
#endif
int sqlite3_column_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
return pVm ? pVm->nResColumn : 0;
}
int sqlite3_data_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
if( pVm==0 || pVm->pResultRow==0 ) return 0;
return pVm->nResColumn;
}
static const Mem *columnNullValue(void){
static const Mem nullMem
#if defined(SQLITE_DEBUG) && defined(__GNUC__)
__attribute__((aligned(8)))
#endif
= {
{0},
(char*)0,
(int)0,
(u16)MEM_Null,
(u8)0,
(u8)0,
(sqlite3*)0,
(int)0,
(u32)0,
(char*)0,
(void(*)(void*))0,
#ifdef SQLITE_DEBUG
(Mem*)0,
0,
#endif
};
return &nullMem;
}
static Mem *columnMem(sqlite3_stmt *pStmt, int i){
Vdbe *pVm;
Mem *pOut;
pVm = (Vdbe *)pStmt;
if( pVm==0 ) return (Mem*)columnNullValue();
assert( pVm->db );
sqlite3_mutex_enter(pVm->db->mutex);
if( pVm->pResultRow!=0 && i<pVm->nResColumn && i>=0 ){
pOut = &pVm->pResultRow[i];
}else{
sqlite3Error(pVm->db, SQLITE_RANGE);
pOut = (Mem*)columnNullValue();
}
return pOut;
}
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);
}
}
const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
const void *val;
val = sqlite3_value_blob( columnMem(pStmt,i) );
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){
Mem *pOut = columnMem(pStmt, i);
if( pOut->flags&MEM_Static ){
pOut->flags &= ~MEM_Static;
pOut->flags |= MEM_Ephem;
}
columnMallocFailure(pStmt);
return (sqlite3_value *)pOut;
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
#endif
int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
int iType = sqlite3_value_type( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return iType;
}
static const void *columnName(
sqlite3_stmt *pStmt,
int N,
int useUtf16,
int useType
){
const void *ret;
Vdbe *p;
int n;
sqlite3 *db;
#ifdef SQLITE_ENABLE_API_ARMOR
if( pStmt==0 ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
ret = 0;
p = (Vdbe *)pStmt;
db = p->db;
assert( db!=0 );
n = sqlite3_column_count(pStmt);
if( N<n && N>=0 ){
u8 prior_mallocFailed = db->mallocFailed;
N += useType*n;
sqlite3_mutex_enter(db->mutex);
#ifndef SQLITE_OMIT_UTF16
if( useUtf16 ){
ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]);
}else
#endif
{
ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]);
}
assert( db->mallocFailed==0 || db->mallocFailed==1 );
if( db->mallocFailed > prior_mallocFailed ){
sqlite3OomClear(db);
ret = 0;
}
sqlite3_mutex_leave(db->mutex);
}
return ret;
}
const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 0, COLNAME_NAME);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 1, COLNAME_NAME);
}
#endif
#if defined(SQLITE_OMIT_DECLTYPE) && defined(SQLITE_ENABLE_COLUMN_METADATA)
# error "Must not define both SQLITE_OMIT_DECLTYPE \
and SQLITE_ENABLE_COLUMN_METADATA"
#endif
#ifndef SQLITE_OMIT_DECLTYPE
const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 0, COLNAME_DECLTYPE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 1, COLNAME_DECLTYPE);
}
#endif
#endif
#ifdef SQLITE_ENABLE_COLUMN_METADATA
const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 0, COLNAME_DATABASE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 1, COLNAME_DATABASE);
}
#endif
const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 0, COLNAME_TABLE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 1, COLNAME_TABLE);
}
#endif
const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 0, COLNAME_COLUMN);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
return columnName(pStmt, N, 1, COLNAME_COLUMN);
}
#endif
#endif
static int vdbeUnbind(Vdbe *p, unsigned int i){
Mem *pVar;
if( vdbeSafetyNotNull(p) ){
return SQLITE_MISUSE_BKPT;
}
sqlite3_mutex_enter(p->db->mutex);
if( p->eVdbeState!=VDBE_READY_STATE ){
sqlite3Error(p->db, SQLITE_MISUSE);
sqlite3_mutex_leave(p->db->mutex);
sqlite3_log(SQLITE_MISUSE,
"bind on a busy prepared statement: [%s]", p->zSql);
return SQLITE_MISUSE_BKPT;
}
if( i>=(unsigned int)p->nVar ){
sqlite3Error(p->db, SQLITE_RANGE);
sqlite3_mutex_leave(p->db->mutex);
return SQLITE_RANGE;
}
pVar = &p->aVar[i];
sqlite3VdbeMemRelease(pVar);
pVar->flags = MEM_Null;
p->db->errCode = SQLITE_OK;
assert( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || p->expmask==0 );
if( p->expmask!=0 && (p->expmask & (i>=31 ? 0x80000000 : (u32)1<<i))!=0 ){
p->expired = 1;
}
return SQLITE_OK;
}
static int bindText(
sqlite3_stmt *pStmt,
int i,
const void *zData,
i64 nData,
void (*xDel)(void*),
u8 encoding
){
Vdbe *p = (Vdbe *)pStmt;
Mem *pVar;
int rc;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
if( 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));
}
if( rc ){
sqlite3Error(p->db, rc);
rc = sqlite3ApiExit(p->db, rc);
}
}
sqlite3_mutex_leave(p->db->mutex);
}else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
xDel((void*)zData);
}
return rc;
}
int sqlite3_bind_blob(
sqlite3_stmt *pStmt,
int i,
const void *zData,
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(
sqlite3_stmt *pStmt,
int i,
const void *zData,
sqlite3_uint64 nData,
void (*xDel)(void*)
){
assert( xDel!=SQLITE_DYNAMIC );
return bindText(pStmt, i, zData, nData, xDel, 0);
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
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){
return sqlite3_bind_int64(p, i, (i64)iValue);
}
int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
}
int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
int rc;
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
}
int sqlite3_bind_pointer(
sqlite3_stmt *pStmt,
int i,
void *pPtr,
const char *zPTtype,
void (*xDestructor)(void*)
){
int rc;
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
sqlite3_mutex_leave(p->db->mutex);
}else if( xDestructor ){
xDestructor(pPtr);
}
return rc;
}
int sqlite3_bind_text(
sqlite3_stmt *pStmt,
int i,
const char *zData,
int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
int sqlite3_bind_text64(
sqlite3_stmt *pStmt,
int i,
const char *zData,
sqlite3_uint64 nData,
void (*xDel)(void*),
unsigned char enc
){
assert( xDel!=SQLITE_DYNAMIC );
if( enc!=SQLITE_UTF8 ){
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
nData &= ~(u16)1;
}
return bindText(pStmt, i, zData, nData, xDel, enc);
}
#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
sqlite3_stmt *pStmt,
int i,
const void *zData,
int n,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, n & ~(u64)1, xDel, SQLITE_UTF16NATIVE);
}
#endif
int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
switch( sqlite3_value_type((sqlite3_value*)pValue) ){
case SQLITE_INTEGER: {
rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
break;
}
case SQLITE_FLOAT: {
assert( pValue->flags & (MEM_Real|MEM_IntReal) );
rc = sqlite3_bind_double(pStmt, i,
(pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i
);
break;
}
case SQLITE_BLOB: {
if( pValue->flags & MEM_Zero ){
rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
}else{
rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
}
break;
}
case SQLITE_TEXT: {
rc = bindText(pStmt,i, pValue->z, pValue->n, SQLITE_TRANSIENT,
pValue->enc);
break;
}
default: {
rc = sqlite3_bind_null(pStmt, i);
break;
}
}
return rc;
}
int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
rc = sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#endif
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
}
int sqlite3_bind_zeroblob64(sqlite3_stmt *pStmt, int i, sqlite3_uint64 n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
sqlite3_mutex_enter(p->db->mutex);
if( n>(u64)p->db->aLimit[SQLITE_LIMIT_LENGTH] ){
rc = SQLITE_TOOBIG;
}else{
assert( (n & 0x7FFFFFFF)==n );
rc = sqlite3_bind_zeroblob(pStmt, i, n);
}
rc = sqlite3ApiExit(p->db, rc);
sqlite3_mutex_leave(p->db->mutex);
return rc;
}
int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p ? p->nVar : 0;
}
const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
if( p==0 ) return 0;
return sqlite3VListNumToName(p->pVList, i);
}
int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
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));
}
int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
int i;
assert( pTo->db==pFrom->db );
assert( pTo->nVar==pFrom->nVar );
sqlite3_mutex_enter(pTo->db->mutex);
for(i=0; i<pFrom->nVar; i++){
sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
}
sqlite3_mutex_leave(pTo->db->mutex);
return SQLITE_OK;
}
#ifndef SQLITE_OMIT_DEPRECATED
int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
assert( (pTo->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pTo->expmask==0 );
if( pTo->expmask ){
pTo->expired = 1;
}
assert( (pFrom->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 || pFrom->expmask==0 );
if( pFrom->expmask ){
pFrom->expired = 1;
}
return sqlite3TransferBindings(pFromStmt, pToStmt);
}
#endif
sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->db : 0;
}
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}
int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->explain : 0;
}
int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
return v!=0 && v->eVdbeState==VDBE_RUN_STATE;
}
sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
sqlite3_stmt *pNext;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(pDb) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
sqlite3_mutex_enter(pDb->mutex);
if( pStmt==0 ){
pNext = (sqlite3_stmt*)pDb->pVdbe;
}else{
pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pVNext;
}
sqlite3_mutex_leave(pDb->mutex);
return pNext;
}
int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
Vdbe *pVdbe = (Vdbe*)pStmt;
u32 v;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !pStmt
|| (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter)))
){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
if( op==SQLITE_STMTSTATUS_MEMUSED ){
sqlite3 *db = pVdbe->db;
sqlite3_mutex_enter(db->mutex);
v = 0;
db->pnBytesFreed = (int*)&v;
assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
db->lookaside.pEnd = db->lookaside.pStart;
sqlite3VdbeDelete(pVdbe);
db->pnBytesFreed = 0;
db->lookaside.pEnd = db->lookaside.pTrueEnd;
sqlite3_mutex_leave(db->mutex);
}else{
v = pVdbe->aCounter[op];
if( resetFlag ) pVdbe->aCounter[op] = 0;
}
return (int)v;
}
const char *sqlite3_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
return p ? p->zSql : 0;
}
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_NORMALIZE
const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
if( p==0 ) return 0;
if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){
sqlite3_mutex_enter(p->db->mutex);
p->zNormSql = sqlite3Normalize(p, p->zSql);
sqlite3_mutex_leave(p->db->mutex);
}
return p->zNormSql;
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
static UnpackedRecord *vdbeUnpackRecord(
KeyInfo *pKeyInfo,
int nKey,
const void *pKey
){
UnpackedRecord *pRet;
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
}
return pRet;
}
int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
PreUpdate *p = db->pPreUpdate;
Mem *pMem;
int rc = SQLITE_OK;
if( !p || p->op==SQLITE_INSERT ){
rc = SQLITE_MISUSE_BKPT;
goto preupdate_old_out;
}
if( p->pPk ){
iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
}
if( p->pUnpacked==0 ){
u32 nRec;
u8 *aRec;
assert( p->pCsr->eCurType==CURTYPE_BTREE );
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|MEM_IntReal) ){
testcase( pMem->flags & MEM_Int );
testcase( pMem->flags & MEM_IntReal );
sqlite3VdbeMemRealify(pMem);
}
}
preupdate_old_out:
sqlite3Error(db, rc);
return sqlite3ApiExit(db, rc);
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
int sqlite3_preupdate_count(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
return (p ? p->keyinfo.nKeyField : 0);
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
int sqlite3_preupdate_depth(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
return (p ? p->v->nFrame : 0);
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
int sqlite3_preupdate_blobwrite(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
return (p ? p->iBlobWrite : -1);
}
#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
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 = sqlite3TableColumnToIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
}
if( p->op==SQLITE_INSERT ){
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{
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
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int sqlite3_stmt_scanstatus_v2(
sqlite3_stmt *pStmt,
int iScan,
int iScanStatusOp,
int flags,
void *pOut
){
Vdbe *p = (Vdbe*)pStmt;
VdbeOp *aOp = p->aOp;
int nOp = p->nOp;
ScanStatus *pScan = 0;
int idx;
if( p->pFrame ){
VdbeFrame *pFrame;
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
aOp = pFrame->aOp;
nOp = pFrame->nOp;
}
if( iScan<0 ){
int ii;
if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){
i64 res = 0;
for(ii=0; ii<nOp; ii++){
res += aOp[ii].nCycle;
}
*(i64*)pOut = res;
return 0;
}
return 1;
}
if( flags & SQLITE_SCANSTAT_COMPLEX ){
idx = iScan;
pScan = &p->aScan[idx];
}else{
for(idx=0; idx<p->nScan; idx++){
pScan = &p->aScan[idx];
if( pScan->zName ){
iScan--;
if( iScan<0 ) break;
}
}
}
if( idx>=p->nScan ) return 1;
switch( iScanStatusOp ){
case SQLITE_SCANSTAT_NLOOP: {
if( pScan->addrLoop>0 ){
*(sqlite3_int64*)pOut = aOp[pScan->addrLoop].nExec;
}else{
*(sqlite3_int64*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_NVISIT: {
if( pScan->addrVisit>0 ){
*(sqlite3_int64*)pOut = aOp[pScan->addrVisit].nExec;
}else{
*(sqlite3_int64*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_EST: {
double r = 1.0;
LogEst x = pScan->nEst;
while( x<100 ){
x += 10;
r *= 0.5;
}
*(double*)pOut = r*sqlite3LogEstToInt(x);
break;
}
case SQLITE_SCANSTAT_NAME: {
*(const char**)pOut = pScan->zName;
break;
}
case SQLITE_SCANSTAT_EXPLAIN: {
if( pScan->addrExplain ){
*(const char**)pOut = aOp[ pScan->addrExplain ].p4.z;
}else{
*(const char**)pOut = 0;
}
break;
}
case SQLITE_SCANSTAT_SELECTID: {
if( pScan->addrExplain ){
*(int*)pOut = aOp[ pScan->addrExplain ].p1;
}else{
*(int*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_PARENTID: {
if( pScan->addrExplain ){
*(int*)pOut = aOp[ pScan->addrExplain ].p2;
}else{
*(int*)pOut = -1;
}
break;
}
case SQLITE_SCANSTAT_NCYCLE: {
i64 res = 0;
if( pScan->aAddrRange[0]==0 ){
res = -1;
}else{
int ii;
for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){
int iIns = pScan->aAddrRange[ii];
int iEnd = pScan->aAddrRange[ii+1];
if( iIns==0 ) break;
if( iIns>0 ){
while( iIns<=iEnd ){
res += aOp[iIns].nCycle;
iIns++;
}
}else{
int iOp;
for(iOp=0; iOp<nOp; iOp++){
Op *pOp = &aOp[iOp];
if( pOp->p1!=iEnd ) continue;
if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){
continue;
}
res += aOp[iOp].nCycle;
}
}
}
}
*(i64*)pOut = res;
break;
}
default: {
return 1;
}
}
return 0;
}
int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt,
int iScan,
int iScanStatusOp,
void *pOut
){
return sqlite3_stmt_scanstatus_v2(pStmt, iScan, iScanStatusOp, 0, pOut);
}
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
int ii;
for(ii=0; ii<p->nOp; ii++){
Op *pOp = &p->aOp[ii];
pOp->nExec = 0;
pOp->nCycle = 0;
}
}
#endif