** 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 <ctype.h>
void sqlite3RollbackAll(sqlite3 *db){
int i;
int inTrans = 0;
+ assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
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;
}
void *pArg
){
if( !sqlite3SafetyCheck(db) ){
+ sqlite3_mutex_enter(db->mutex);
if( nOps>0 ){
db->xProgress = xProgress;
db->nProgressOps = nOps;
db->nProgressOps = 0;
db->pProgressArg = 0;
}
+ sqlite3_mutex_leave(db->mutex);
}
}
#endif
FuncDef *p;
int nName;
+ assert( sqlite3_mutex_held(db->mutex) );
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
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
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
){
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
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
** 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;
}
/*
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 */
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;
}
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;
}
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;
}
int btree_flags = 0;
int rc;
+ assert( sqlite3_mutex_held(db->mutex) );
assert( ppBtree != 0);
if( omitJournal ){
btree_flags |= BTREE_OMIT_JOURNAL;
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);
if( z==0 ){
z = sqlite3ErrStr(db->errCode);
}
+ sqlite3_mutex_leave(db->mutex);
return z;
}
};
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),
z = sqlite3_value_text16(db->pErr);
}
sqlite3ApiExit(0, 0);
+ sqlite3_mutex_leave(db->mutex);
return z;
}
#endif /* SQLITE_OMIT_UTF16 */
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
}
#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.
*/
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;
}
/*
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
){
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 */
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;
}
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 */
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
+ sqlite3_mutex_enter(db->mutex);
rc = sqlite3Init(db, &zErrMsg);
if( SQLITE_OK!=rc ){
goto 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;
}
** 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_
** [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 *);
** 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*);
** 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*);
** 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*);
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 */
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
** 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*);
** 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.
-**
-** 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.
+** 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.
+**
+** 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
/*
** 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.
-**
-** 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.
+** 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.
**
-** 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
** 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
**