From e30f44262264c291e2e223c4c01ba8473f499fc3 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 21 Aug 2007 16:15:55 +0000 Subject: [PATCH] Adding more thread locking code. This is an incremental check-in. (CVS 4262) FossilOrigin-Name: 7428732b1fa04b83eda0a3539834693ef351313e --- manifest | 16 ++--- manifest.uuid | 2 +- src/main.c | 153 +++++++++++++++++++++++++----------------------- src/sqlite.h.in | 99 ++++++++++++++----------------- src/vdbeapi.c | 61 +++++++++++++++++++ 5 files changed, 195 insertions(+), 136 deletions(-) diff --git a/manifest b/manifest index 123eaf6b83..2d12762f24 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Readded\sthe\ssqlite3_open_v2()\sinterface.\s\sNo\stest\scases\syet.\nAdditional\sprogress\stoward\sadding\smutexes\sto\sall\sinterfaces.\s(CVS\s4261) -D 2007-08-21T15:13:19 +C Adding\smore\sthread\slocking\scode.\s\sThis\sis\san\sincremental\scheck-in.\s(CVS\s4262) +D 2007-08-21T16:15:56 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -97,7 +97,7 @@ F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c F src/legacy.c a83519a8fbb488c3155fca577b010d590ec479e9 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 F src/loadext.c 780748f3f55a3b5af6ed0adfd58035f728cde4ca -F src/main.c 5f6ab3380477a7f134f7c664e3fdcdbf12a3d9dc +F src/main.c 1f6f46975182c589c4942c708c9821db7c5d5772 F src/malloc.c c2f5da620d8e030c6974a0ddcaeb7b408c9bdb3d F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/mem1.c 30bf8be3846f92fdf88c490c5e5378512383bcbe @@ -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 62a2cb5d0ce867e206a0b5465dedd5dfd941cc37 +F src/sqlite.h.in c691ae04f7c064d853710a1eff4707549a54e1f8 F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b F src/sqliteInt.h c9ba3861d1e8835caeb0c89fca7cddd12779e1ac F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa @@ -159,7 +159,7 @@ F src/vacuum.c 318ccae7c4e3ddf241aeaee4d2611bfe1949a373 F src/vdbe.c f1a9a29da48ccfa49042df478abb478520589f37 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 F src/vdbeInt.h 8e360d326328e7a66100f468697edf9cfb4567dc -F src/vdbeapi.c 16268e7a2614051c9c7f93679d9102b03206c129 +F src/vdbeapi.c b4a1f4d56906a43f40c2bc47d7b142db3759c14e F src/vdbeaux.c 14b48bfc6334682e5e5858a0835f8b00d8751953 F src/vdbeblob.c ac223e6d3acaa3321ce09c11c47bf0d05b37372f 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 3fb97a63ef70662abdba18ce8b480e6b0badcfb1 -R ebd0701e4b840e7f444fe74a84efea35 +P 3787563e90d7210d349ee36484c3f008c955552e +R 059b95f5c37a602e37abf433f570fd9a U drh -Z 4a9c7281bbaf4cab164c43383497e97b +Z da09ba003aea60219dd1a004da17c3aa diff --git a/manifest.uuid b/manifest.uuid index 082b6ce149..d6a9e84d4a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3787563e90d7210d349ee36484c3f008c955552e \ No newline at end of file +7428732b1fa04b83eda0a3539834693ef351313e \ No newline at end of file diff --git a/src/main.c b/src/main.c index 0cdda648e1..b0aa877d5c 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.391 2007/08/21 15:13:19 drh Exp $ +** $Id: main.c,v 1.392 2007/08/21 16:15:56 drh Exp $ */ #include "sqliteInt.h" #include @@ -231,6 +231,7 @@ int sqlite3_close(sqlite3 *db){ void sqlite3RollbackAll(sqlite3 *db){ int i; int inTrans = 0; + assert( sqlite3_mutex_held(db->mutex) ); for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ @@ -366,9 +367,11 @@ int sqlite3_busy_handler( if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } + sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; db->busyHandler.nBusy = 0; + sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -385,6 +388,7 @@ void sqlite3_progress_handler( void *pArg ){ if( !sqlite3SafetyCheck(db) ){ + sqlite3_mutex_enter(db->mutex); if( nOps>0 ){ db->xProgress = xProgress; db->nProgressOps = nOps; @@ -394,6 +398,7 @@ void sqlite3_progress_handler( db->nProgressOps = 0; db->pProgressArg = 0; } + sqlite3_mutex_leave(db->mutex); } } #endif @@ -445,6 +450,7 @@ int sqlite3CreateFunc( FuncDef *p; int nName; + assert( sqlite3_mutex_held(db->mutex) ); if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } @@ -472,10 +478,13 @@ int sqlite3CreateFunc( int rc; rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, pUserData, xFunc, xStep, xFinal); - if( rc!=SQLITE_OK ) return rc; - rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, - pUserData, xFunc, xStep, xFinal); - if( rc!=SQLITE_OK ) return rc; + if( rc==SQLITE_OK ){ + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, + pUserData, xFunc, xStep, xFinal); + } + if( rc!=SQLITE_OK ){ + return rc; + } enc = SQLITE_UTF16BE; } #else @@ -525,10 +534,12 @@ int sqlite3_create_function( void (*xFinal)(sqlite3_context*) ){ int rc; + sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); - - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } #ifndef SQLITE_OMIT_UTF16 @@ -544,13 +555,14 @@ int sqlite3_create_function16( ){ int rc; char *zFunc8; + sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); - zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1); rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); sqlite3_free(zFunc8); - - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } #endif @@ -573,11 +585,15 @@ int sqlite3_overload_function( int nArg ){ int nName = strlen(zName); + int rc; + sqlite3_mutex_enter(db->mutex); if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, 0, sqlite3InvalidFunction, 0, 0); } - return sqlite3ApiExit(db, SQLITE_OK); + rc = sqlite3ApiExit(db, SQLITE_OK); + sqlite3_mutex_leave(db->mutex); + return rc; } #ifndef SQLITE_OMIT_TRACE @@ -590,9 +606,12 @@ int sqlite3_overload_function( ** SQL statement. */ void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ - void *pOld = db->pTraceArg; + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pTraceArg; db->xTrace = xTrace; db->pTraceArg = pArg; + sqlite3_mutex_leave(db->mutex); return pOld; } /* @@ -608,9 +627,12 @@ void *sqlite3_profile( void (*xProfile)(void*,const char*,sqlite_uint64), void *pArg ){ - void *pOld = db->pProfileArg; + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pProfileArg; db->xProfile = xProfile; db->pProfileArg = pArg; + sqlite3_mutex_leave(db->mutex); return pOld; } #endif /* SQLITE_OMIT_TRACE */ @@ -626,9 +648,12 @@ void *sqlite3_commit_hook( int (*xCallback)(void*), /* Function to invoke on each commit */ void *pArg /* Argument to the function */ ){ - void *pOld = db->pCommitArg; + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pCommitArg; db->xCommitCallback = xCallback; db->pCommitArg = pArg; + sqlite3_mutex_leave(db->mutex); return pOld; } @@ -641,9 +666,12 @@ void *sqlite3_update_hook( void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), void *pArg /* Argument to the function */ ){ - void *pRet = db->pUpdateArg; + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pUpdateArg; db->xUpdateCallback = xCallback; db->pUpdateArg = pArg; + sqlite3_mutex_leave(db->mutex); return pRet; } @@ -656,9 +684,12 @@ void *sqlite3_rollback_hook( void (*xCallback)(void*), /* Callback function */ void *pArg /* Argument to the function */ ){ - void *pRet = db->pRollbackArg; + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pRollbackArg; db->xRollbackCallback = xCallback; db->pRollbackArg = pArg; + sqlite3_mutex_leave(db->mutex); return pRet; } @@ -697,6 +728,7 @@ int sqlite3BtreeFactory( int btree_flags = 0; int rc; + assert( sqlite3_mutex_held(db->mutex) ); assert( ppBtree != 0); if( omitJournal ){ btree_flags |= BTREE_OMIT_JOURNAL; @@ -738,6 +770,7 @@ const char *sqlite3_errmsg(sqlite3 *db){ if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } + sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); @@ -746,6 +779,7 @@ const char *sqlite3_errmsg(sqlite3 *db){ if( z==0 ){ z = sqlite3ErrStr(db->errCode); } + sqlite3_mutex_leave(db->mutex); return z; } @@ -775,13 +809,14 @@ const void *sqlite3_errmsg16(sqlite3 *db){ }; const void *z; - assert( !db->mallocFailed ); if( !db ){ return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); } + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); z = sqlite3_value_text16(db->pErr); if( z==0 ){ sqlite3ValueSetStr(db, db->pErr, -1, sqlite3ErrStr(db->errCode), @@ -789,6 +824,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ z = sqlite3_value_text16(db->pErr); } sqlite3ApiExit(0, 0); + sqlite3_mutex_leave(db->mutex); return z; } #endif /* SQLITE_OMIT_UTF16 */ @@ -825,6 +861,7 @@ static int createCollation( if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } + assert( sqlite3_mutex_held(db->mutex) ); /* If SQLITE_UTF16 is specified as the encoding type, transform this ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the @@ -1098,45 +1135,6 @@ int sqlite3_open16( } #endif /* SQLITE_OMIT_UTF16 */ -/* -** 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{ - rc = sqlite3VdbeFinalize((Vdbe*)pStmt); - } - 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{ - rc = sqlite3VdbeReset((Vdbe*)pStmt); - sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); - assert( (rc & (sqlite3_db_handle(pStmt)->errMask))==rc ); - } - return rc; -} - /* ** Register a new collation sequence with the database handle db. */ @@ -1148,9 +1146,12 @@ int sqlite3_create_collation( int(*xCompare)(void*,int,const void*,int,const void*) ){ int rc; + sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); rc = createCollation(db, zName, enc, pCtx, xCompare, 0); - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } /* @@ -1165,9 +1166,12 @@ int sqlite3_create_collation_v2( void(*xDel)(void*) ){ int rc; + sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); rc = createCollation(db, zName, enc, pCtx, xCompare, xDel); - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } #ifndef SQLITE_OMIT_UTF16 @@ -1183,13 +1187,16 @@ int sqlite3_create_collation16( ){ int rc = SQLITE_OK; char *zName8; + sqlite3_mutex_enter(db->mutex); assert( !db->mallocFailed ); zName8 = sqlite3Utf16to8(db, zName, -1); if( zName8 ){ rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); sqlite3_free(zName8); } - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } #endif /* SQLITE_OMIT_UTF16 */ @@ -1205,9 +1212,11 @@ int sqlite3_collation_needed( if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } + sqlite3_mutex_enter(db->mutex); db->xCollNeeded = xCollNeeded; db->xCollNeeded16 = 0; db->pCollNeededArg = pCollNeededArg; + sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } @@ -1224,9 +1233,11 @@ int sqlite3_collation_needed16( if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } + sqlite3_mutex_enter(db->mutex); db->xCollNeeded = 0; db->xCollNeeded16 = xCollNeeded16; db->pCollNeededArg = pCollNeededArg; + sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } #endif /* SQLITE_OMIT_UTF16 */ @@ -1306,6 +1317,7 @@ int sqlite3_table_column_metadata( if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } + sqlite3_mutex_enter(db->mutex); rc = sqlite3Init(db, &zErrMsg); if( SQLITE_OK!=rc ){ goto error_out; @@ -1383,39 +1395,34 @@ error_out: } sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); sqlite3_free(zErrMsg); - return sqlite3ApiExit(db, rc); -} -#endif - -/* -** Set all the parameters in the compiled SQL statement to NULL. -*/ -int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ - int i; - int rc = SQLITE_OK; - for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ - rc = sqlite3_bind_null(pStmt, i); - } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); return rc; } +#endif /* ** Sleep for a little while. Return the amount of time slept. */ int sqlite3_sleep(int ms){ sqlite3_vfs *pVfs; + int rc; pVfs = sqlite3_vfs_find(0); /* This function works in milliseconds, but the underlying OsSleep() ** API uses microseconds. Hence the 1000's. */ - return (sqlite3OsSleep(pVfs, 1000*ms)/1000); + rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); + sqlite3_vfs_release(pVfs); + return rc; } /* ** Enable or disable the extended result codes. */ int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ + sqlite3_mutex_enter(db->mutex); db->errMask = onoff ? 0xffffffff : 0xff; + sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 55f9204220..abecd1d190 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.232 2007/08/21 15:13:19 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.233 2007/08/21 16:15:56 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -169,6 +169,12 @@ typedef sqlite_uint64 sqlite3_uint64; ** [sqlite3_prepare16_v2()] must be destroyed using [sqlite3_finalize()] ** before this routine is called. Otherwise, SQLITE_BUSY is returned and the ** database connection remains open. +** +** Passing this routine a database connection that has already been +** closed results in undefined behavior. If other interfaces that +** reference the same database connection are pending (either in the +** same thread or in different threads) when this routine is called, +** then the behavior is undefined and is almost certainly undesirable. */ int sqlite3_close(sqlite3 *); @@ -695,6 +701,10 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff); ** is running. But once the trigger terminates, the value returned ** by this routine reverts to the last value inserted before the ** trigger fired. +** +** If another thread does a new insert on the same database connection +** while this routine is running and thus changes the last insert rowid, +** then the return value of this routine is undefined. */ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); @@ -728,6 +738,10 @@ sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); ** zero regardless of the number of elements that were originally in the ** table. To get an accurate count of the number of rows deleted, use ** "DELETE FROM table WHERE 1" instead. +** +** If another thread makes changes on the same database connection +** while this routine is running then the return value of this routine +** is undefined. */ int sqlite3_changes(sqlite3*); @@ -750,6 +764,10 @@ int sqlite3_changes(sqlite3*); ** zero regardless of the number of elements that were originally in the ** table. To get an accurate count of the number of rows deleted, use ** "DELETE FROM table WHERE 1" instead. +** +** If another thread makes changes on the same database connection +** while this routine is running then the return value of this routine +** is undefined. */ int sqlite3_total_changes(sqlite3*); @@ -1344,7 +1362,7 @@ int sqlite3_open16( sqlite3 **ppDb /* OUT: SQLite db handle */ ); int sqlite3_open_v2( - const void *filename, /* Database filename (UTF-16) */ + const void *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ int flags, /* Flags */ const char *zVfs /* Name of VFS module to use */ @@ -2150,7 +2168,7 @@ int sqlite3_aggregate_count(sqlite3_context*); int sqlite3_expired(sqlite3_stmt*); int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); int sqlite3_global_recover(void); - +void sqlite3_thread_cleanup(void); /* ** CAPI3REF: Obtaining SQL Function Parameter Values @@ -2503,6 +2521,10 @@ SQLITE_EXTERN char *sqlite3_temp_directory; ** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on ** by default. Autocommit is disabled by a BEGIN statement and reenabled ** by the next COMMIT or ROLLBACK. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. */ int sqlite3_get_autocommit(sqlite3*); @@ -2581,28 +2603,14 @@ void *sqlite3_update_hook( ** Sharing is enabled if the argument is true and disabled if the argument ** is false. ** -** Cache sharing is enabled and disabled on a thread-by-thread basis. -** Each call to this routine enables or disables cache sharing only for -** connections created in the same thread in which this routine is called. -** There is no mechanism for sharing cache between database connections -** running in different threads. +** Beginning in SQLite version 3.5.0, cache sharing is enabled and disabled +** for an entire process. In prior versions of SQLite, sharing was +** enabled or disabled for each thread separately. ** -** Sharing must be disabled prior to shutting down a thread or else -** the thread will leak memory. Call this routine with an argument of -** 0 to turn off sharing. Or use the sqlite3_thread_cleanup() API. -** -** This routine must not be called when any database connections -** are active in the current thread. Enabling or disabling shared -** cache while there are active database connections will result -** in memory corruption. -** -** When the shared cache is enabled, the -** following routines must always be called from the same thread: -** [sqlite3_open()], [sqlite3_prepare_v2()], [sqlite3_step()], -** [sqlite3_reset()], [sqlite3_finalize()], and [sqlite3_close()]. -** This is due to the fact that the shared cache makes use of -** thread-specific storage so that it will be available for sharing -** with other connections. +** The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue use the sharing mode that was +** in effect at the time they were opened. ** ** Virtual tables cannot be used with a shared cache. When shared ** cache is enabled, the sqlite3_create_module() API used to register @@ -2631,21 +2639,18 @@ int sqlite3_release_memory(int); /* ** CAPI3REF: Impose A Limit On Heap Size ** -** Place a "soft" limit on the amount of heap memory that may be allocated by -** SQLite within the current thread. If an internal allocation is requested -** that would exceed the specified limit, [sqlite3_release_memory()] is invoked -** one or more times to free up some space before the allocation is made. +** Place a "soft" limit on the amount of heap memory that may be allocated +** by SQLite. If an internal allocation is requested +** that would exceed the specified limit, [sqlite3_release_memory()] is +** invoked one or more times to free up some space before the allocation +** is made. ** -** The limit is called "soft", because if [sqlite3_release_memory()] cannot free -** sufficient memory to prevent the limit from being exceeded, the memory is -** allocated anyway and the current operation proceeds. -** -** Prior to shutting down a thread sqlite3_soft_heap_limit() must be set to -** zero (the default) or else the thread will leak memory. Alternatively, use -** the [sqlite3_thread_cleanup()] API. +** The limit is called "soft", because if [sqlite3_release_memory()] cannot +** free sufficient memory to prevent the limit from being exceeded, +** the memory is allocated anyway and the current operation proceeds. ** ** A negative or zero value for N means that there is no soft heap limit and -** [sqlite3_release_memory()] will only be called when memory is exhaused. +** [sqlite3_release_memory()] will only be called when memory is exhausted. ** The default value for the soft heap limit is zero. ** ** SQLite makes a best effort to honor the soft heap limit. But if it @@ -2653,27 +2658,13 @@ int sqlite3_release_memory(int); ** continue without error or notification. This is why the limit is ** called a "soft" limit. It is advisory only. ** -** This function is only available if the library was compiled with the -** SQLITE_ENABLE_MEMORY_MANAGEMENT option set. -** memory-management has been enabled. +** Prior to SQLite version 3.5.0, this routine only constrained the memory +** allocated by a single thread - the same thread in which this routine +** runs. Beginning with SQLite version 3.5.0, the soft heap limit is +** applied cumulatively to all threads. */ void sqlite3_soft_heap_limit(int); -/* -** CAPI3REF: Clean Up Thread Local Storage -** -** This routine makes sure that all thread-local storage has been -** deallocated for the current thread. -** -** This routine is not technically necessary. All thread-local storage -** will be automatically deallocated once memory-management and -** shared-cache are disabled and the soft heap limit has been set -** to zero. This routine is provided as a convenience for users who -** want to make absolutely sure they have not forgotten something -** prior to killing off a thread. -*/ -void sqlite3_thread_cleanup(void); - /* ** CAPI3REF: Extract Metadata About A Column Of A Table ** diff --git a/src/vdbeapi.c b/src/vdbeapi.c index ffe89b24c8..253b477801 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -29,6 +29,67 @@ int sqlite3_expired(sqlite3_stmt *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; + sqlite3_mutex_enter(v->db->mutex); + rc = sqlite3VdbeFinalize(v); + sqlite3_mutex_leave(v->db->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); + 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 *v = (Vdbe*)pStmt; + sqlite3_mutex_enter(v->db->mutex); + for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ + rc = sqlite3_bind_null(pStmt, i); + } + sqlite3_mutex_leave(v->db->mutex); + return rc; +} + + /**************************** sqlite3_value_ ******************************* ** The following routines extract information from a Mem or sqlite3_value ** structure.