📄 vdbeapi.c
字号:
/*** 2004 May 26**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.******************************************************************************* This file contains code use to implement APIs that are part of the** VDBE.**** $Id: vdbeapi.c,v 1.140 2008/08/21 12:19:44 danielk1977 Exp $*/#include "sqliteInt.h"#include "vdbeInt.h"#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)/*** The following structure contains pointers to the end points of a** doubly-linked list of all compiled SQL statements that may be holding** buffers eligible for release when the sqlite3_release_memory() interface is** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2** mutex.**** Statements are added to the end of this list when sqlite3_reset() is** called. They are removed either when sqlite3_step() or sqlite3_finalize()** is called. When statements are added to this list, the associated ** register array (p->aMem[1..p->nMem]) may contain dynamic buffers that** can be freed using sqlite3VdbeReleaseMemory().**** When statements are added or removed from this list, the mutex** associated with the Vdbe being added or removed (Vdbe.db->mutex) is** already held. The LRU2 mutex is then obtained, blocking if necessary,** the linked-list pointers manipulated and the LRU2 mutex relinquished.*/struct StatementLruList { Vdbe *pFirst; Vdbe *pLast;};static struct StatementLruList sqlite3LruStatements;/*** Check that the list looks to be internally consistent. This is used** as part of an assert() statement as follows:**** assert( stmtLruCheck() );*/#ifndef NDEBUGstatic int stmtLruCheck(){ Vdbe *p; for(p=sqlite3LruStatements.pFirst; p; p=p->pLruNext){ assert(p->pLruNext || p==sqlite3LruStatements.pLast); assert(!p->pLruNext || p->pLruNext->pLruPrev==p); assert(p->pLruPrev || p==sqlite3LruStatements.pFirst); assert(!p->pLruPrev || p->pLruPrev->pLruNext==p); } return 1;}#endif/*** Add vdbe p to the end of the statement lru list. It is assumed that** p is not already part of the list when this is called. The lru list** is protected by the SQLITE_MUTEX_STATIC_LRU mutex.*/static void stmtLruAdd(Vdbe *p){ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); return; } assert( stmtLruCheck() ); if( !sqlite3LruStatements.pFirst ){ assert( !sqlite3LruStatements.pLast ); sqlite3LruStatements.pFirst = p; sqlite3LruStatements.pLast = p; }else{ assert( !sqlite3LruStatements.pLast->pLruNext ); p->pLruPrev = sqlite3LruStatements.pLast; sqlite3LruStatements.pLast->pLruNext = p; sqlite3LruStatements.pLast = p; } assert( stmtLruCheck() ); sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));}/*** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove** statement p from the least-recently-used statement list. If the ** statement is not currently part of the list, this call is a no-op.*/static void stmtLruRemoveNomutex(Vdbe *p){ if( p->pLruPrev || p->pLruNext || p==sqlite3LruStatements.pFirst ){ assert( stmtLruCheck() ); if( p->pLruNext ){ p->pLruNext->pLruPrev = p->pLruPrev; }else{ sqlite3LruStatements.pLast = p->pLruPrev; } if( p->pLruPrev ){ p->pLruPrev->pLruNext = p->pLruNext; }else{ sqlite3LruStatements.pFirst = p->pLruNext; } p->pLruNext = 0; p->pLruPrev = 0; assert( stmtLruCheck() ); }}/*** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove** statement p from the least-recently-used statement list. If the ** statement is not currently part of the list, this call is a no-op.*/static void stmtLruRemove(Vdbe *p){ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); stmtLruRemoveNomutex(p); sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));}/*** Try to release n bytes of memory by freeing buffers associated ** with the memory registers of currently unused vdbes.*/int sqlite3VdbeReleaseMemory(int n){ Vdbe *p; Vdbe *pNext; int nFree = 0; sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){ pNext = p->pLruNext; /* For each statement handle in the lru list, attempt to obtain the ** associated database mutex. If it cannot be obtained, continue ** to the next statement handle. It is not possible to block on ** the database mutex - that could cause deadlock. */ if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){ nFree += sqlite3VdbeReleaseBuffers(p); stmtLruRemoveNomutex(p); sqlite3_mutex_leave(p->db->mutex); } } sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2)); return nFree;}/*** Call sqlite3Reprepare() on the statement. Remove it from the** lru list before doing so, as Reprepare() will free all the** memory register buffers anyway.*/int vdbeReprepare(Vdbe *p){ stmtLruRemove(p); return sqlite3Reprepare(p);}#else /* !SQLITE_ENABLE_MEMORY_MANAGEMENT */ #define stmtLruRemove(x) #define stmtLruAdd(x) #define vdbeReprepare(x) sqlite3Reprepare(x)#endif/*** Return TRUE (non-zero) of the statement supplied as an argument needs** to be recompiled. A statement needs to be recompiled whenever the** execution environment changes in a way that would alter the program** that sqlite3_prepare() generates. For example, if new functions or** collating sequences are registered or if an authorizer function is** added or changed.*/int sqlite3_expired(sqlite3_stmt *pStmt){ Vdbe *p = (Vdbe*)pStmt; 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;#ifndef SQLITE_MUTEX_NOOP sqlite3_mutex *mutex = v->db->mutex;#endif sqlite3_mutex_enter(mutex); stmtLruRemove(v); 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); stmtLruAdd(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 *p = (Vdbe*)pStmt;#ifndef SQLITE_MUTEX_NOOP 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; } sqlite3_mutex_leave(mutex); return rc;}/**************************** sqlite3_value_ ********************************* The following routines extract information from a Mem or sqlite3_value** structure.*/const void *sqlite3_value_blob(sqlite3_value *pVal){ Mem *p = (Mem*)pVal; if( p->flags & (MEM_Blob|MEM_Str) ){ sqlite3VdbeMemExpandBlob(p); p->flags &= ~MEM_Str; p->flags |= MEM_Blob; return p->z; }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 sqlite3VdbeIntValue((Mem*)pVal);}sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal);}const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);}#ifndef SQLITE_OMIT_UTF16const 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 /* SQLITE_OMIT_UTF16 */int sqlite3_value_type(sqlite3_value* pVal){ return pVal->type;}/**************************** sqlite3_result_ ********************************* The following routines are used by user-defined functions to specify** the function result.*/void sqlite3_result_blob( sqlite3_context *pCtx, const void *z, int n, 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 = SQLITE_ERROR; sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);}#ifndef SQLITE_OMIT_UTF16void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = SQLITE_ERROR; sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);}#endifvoid 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( sqlite3_context *pCtx, const char *z, int n, void (*xDel)(void *)){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel);}#ifndef SQLITE_OMIT_UTF16void sqlite3_result_text16( sqlite3_context *pCtx, const void *z, 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( sqlite3_context *pCtx, const void *z, 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( sqlite3_context *pCtx, const void *z, 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);}void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ pCtx->isError = errCode;}/* Force an SQLITE_TOOBIG error. */void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->s.db->mutex) ); pCtx->isError = SQLITE_TOOBIG; sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, SQLITE_UTF8, SQLITE_STATIC);}/* 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 = SQLITE_NOMEM; pCtx->s.db->mallocFailed = 1;}/*** Execute the statement pStmt, either until a row of data is ready, the** statement is completely executed or an error occurs.**** This routine implements the bulk of the logic behind the sqlite_step()** API. The only thing omitted is the automatic recompile if a ** schema change has occurred. That detail is handled by the** outer sqlite3_step() wrapper procedure.*/static int sqlite3Step(Vdbe *p){ sqlite3 *db;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -