From 32bc3f6e01750d6b730efd372952156d7d62b066 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 21 Aug 2007 20:25:39 +0000 Subject: [PATCH] All mutexing and locking appears to be in place. Now we just have to test it and make it all work. (CVS 4264) FossilOrigin-Name: 0f7941aef976aa4f3be3e0046edd1ae042e5d9a3 --- manifest | 14 ++++----- manifest.uuid | 2 +- src/sqlite.h.in | 43 +++++++++++++++++++++++---- src/vdbeapi.c | 77 +++++++++++++++++++++++++++++++++++-------------- 4 files changed, 101 insertions(+), 35 deletions(-) diff --git a/manifest b/manifest index cc0aa52cb7..fa52920b33 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3_value\sobject\snow\scarries\san\ssqlite3*\spointer\sto\suse\sfor\nrecording\smalloc\sfailures.\s\sThis\seliminates\sthe\sneed\sto\spass\ssqlite3*\npointers\sinto\smany\sinternal\sinterfaces.\s\sAlso\sadded\smore\smutexing.\s(CVS\s4263) -D 2007-08-21T19:33:56 +C All\smutexing\sand\slocking\sappears\sto\sbe\sin\splace.\s\sNow\swe\sjust\shave\sto\ntest\sit\sand\smake\sit\sall\swork.\s(CVS\s4264) +D 2007-08-21T20:25:40 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -124,7 +124,7 @@ F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da F src/select.c 98c367bce3f38c5adfcc97de9ab5c79b0e5dc2b2 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c ac29402b538515fa4697282387be9c1205e6e9eb -F src/sqlite.h.in 95e159919060f9c6e060ff420ce17490f7b6a0f3 +F src/sqlite.h.in b2a7484c024c42f2e639f289beb7c8db36513a2c F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b F src/sqliteInt.h 23eb6a5b1f10d5d3d34c3c7846b7c3b93acf1276 F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa @@ -159,7 +159,7 @@ F src/vacuum.c 318ccae7c4e3ddf241aeaee4d2611bfe1949a373 F src/vdbe.c 9d4d00589c174aad9a616f1615464ddddebba0ec F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 F src/vdbeInt.h 39fb069ce04137545ca0bc790f80ddc64a8c99d9 -F src/vdbeapi.c 09eb4fe5ce6e8e4558ca3fa1e22241f2d3895bf0 +F src/vdbeapi.c e12f99aa859118afbffff67eb32df36d564b5c80 F src/vdbeaux.c b0aeed4ff33352904b392ee6c7408bae5b141b9b F src/vdbeblob.c d12ed95dac0992e1e372d079d76af047cc42f7c7 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 @@ -558,7 +558,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 7428732b1fa04b83eda0a3539834693ef351313e -R 913d5d6bd631d176ac289a9e0cf82ff0 +P 9287276191a582c1cf7cf6b71d8399727d8e534d +R c2481d632c284d895f66ae3d4866a0ab U drh -Z c581f4a42a4b4dc59e9659821c9fdece +Z aa5c15d669e0ef0f762ec1f2d438a5a0 diff --git a/manifest.uuid b/manifest.uuid index d5508f39d3..780479153a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9287276191a582c1cf7cf6b71d8399727d8e534d \ No newline at end of file +0f7941aef976aa4f3be3e0046edd1ae042e5d9a3 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index ba1731864d..a4bd04f53e 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.234 2007/08/21 19:33:56 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.235 2007/08/21 20:25:40 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1745,6 +1745,10 @@ const void *sqlite3_column_name16(sqlite3_stmt*, int N); ** ** These APIs are only available if the library was compiled with the ** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +** +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. */ const char *sqlite3_column_database_name(sqlite3_stmt*,int); const void *sqlite3_column_database_name16(sqlite3_stmt*,int); @@ -1905,17 +1909,27 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); /* ** CAPI3REF: Results Values From A Query ** -** These routines return information about the information -** in a single column of the current result row of a query. In every +** These routines return information about +** a single column of the current result row of a query. In every ** case the first argument is a pointer to the ** [sqlite3_stmt | SQL statement] that is being -** evaluate (the [sqlite3_stmt*] that was returned from +** evaluated (the [sqlite3_stmt*] that was returned from ** [sqlite3_prepare_v2()] or one of its variants) and ** the second argument is the index of the column for which information -** should be returned. The left-most column has an index of 0. +** should be returned. The left-most column of the result set +** has an index of 0. ** ** If the SQL statement is not currently point to a valid row, or if the -** the column index is out of range, the result is undefined. +** the column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. ** ** The sqlite3_column_type() routine returns ** [SQLITE_INTEGER | datatype code] for the initial data type @@ -2019,6 +2033,13 @@ int sqlite3_data_count(sqlite3_stmt *pStmt); ** find the size of the result. Do not mix call to sqlite3_column_text() or ** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not ** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). +** +** The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. The memory space used to hold strings +** and blobs is freed automatically. Do not pass the pointers returned +** [sqlite3_column_blob()], [sqlite_column_text()], etc. into +** [sqlite3_free()]. */ const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); int sqlite3_column_bytes(sqlite3_stmt*, int iCol); @@ -2211,6 +2232,9 @@ void sqlite3_thread_cleanup(void); ** ** These routines must be called from the same thread as ** the SQL function that supplied the sqlite3_value* parameters. +** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] +** interface, then these routines should be called from the same thread +** that ran [sqlite3_column_value()]. */ const void *sqlite3_value_blob(sqlite3_value*); int sqlite3_value_bytes(sqlite3_value*); @@ -3311,6 +3335,13 @@ int sqlite3_mutex_try(sqlite3_mutex*); void sqlite3_mutex_leave(sqlite3_mutex*); int sqlite3_mutex_held(sqlite3_mutex*); int sqlite3_mutex_notheld(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Types +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +*/ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 #define SQLITE_MUTEX_STATIC_MASTER 2 diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 20767fd628..cf8b6dc5ff 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -137,7 +137,6 @@ const void *sqlite3_value_text16le(sqlite3_value *pVal){ 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 @@ -150,28 +149,35 @@ void sqlite3_result_blob( 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( @@ -180,6 +186,7 @@ void sqlite3_result_text( 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 @@ -189,6 +196,7 @@ void sqlite3_result_text16( 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( @@ -197,6 +205,7 @@ void sqlite3_result_text16be( 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( @@ -205,18 +214,22 @@ void sqlite3_result_text16le( 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); } @@ -535,14 +548,21 @@ int sqlite3_data_count(sqlite3_stmt *pStmt){ ** 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 ){ + 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 }; sqlite3Error(pVm->db, SQLITE_RANGE, 0); - return (Mem*)&nullMem; + pOut = (Mem*)&nullMem; } - return &pVm->pTos[(1-vals)+i]; + return pOut; } /* @@ -552,7 +572,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){ ** 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() @@ -572,7 +592,10 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) ** 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_ ******************************* @@ -620,7 +643,9 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ 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){ @@ -630,7 +655,9 @@ const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ } #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 @@ -662,20 +689,28 @@ static const void *columnName( 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>=n || N<0 ){ - return 0; + if( p!=0 ){ + n = sqlite3_column_count(pStmt); + if( N=0 ){ + N += useType*n; + ret = xFunc(&p->aColName[N]); + +#if 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; + } +#endif + } } - 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; }