diff --git a/manifest b/manifest index 7848ebdfb4..123eaf6b83 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Delay\sopening\stemporary\spager\sfiles\suntil\sthey\sare\sfirst\swritten.\s(CVS\s4260) -D 2007-08-21T14:27:02 +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 F Makefile.in 0c0e53720f658c7a551046442dd7afba0b72bfbe F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -96,8 +96,8 @@ F src/hash.h 3ad3da76bfb954978d227bf495568b0e6da2c19e F src/insert.c 633322aef1799f6604fa805e12488bc628570b0c F src/legacy.c a83519a8fbb488c3155fca577b010d590ec479e9 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35 -F src/loadext.c 8563d7ef0d7fe424378ef7b945d56c28ba78fe24 -F src/main.c 3f8917757c7f6a937e300b613b9cfd1bbe703c70 +F src/loadext.c 780748f3f55a3b5af6ed0adfd58035f728cde4ca +F src/main.c 5f6ab3380477a7f134f7c664e3fdcdbf12a3d9dc 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 09d8d2780c2c25dedbcfdfcafc39e8b213fc8432 +F src/sqlite.h.in 62a2cb5d0ce867e206a0b5465dedd5dfd941cc37 F src/sqlite3ext.h 647a6b8a8f76ff6c9611e4a071531d8e63ff2d6b F src/sqliteInt.h c9ba3861d1e8835caeb0c89fca7cddd12779e1ac F src/sqliteLimit.h f14609c27636ebc217c9603ade26dbdd7d0f6afa @@ -159,9 +159,9 @@ F src/vacuum.c 318ccae7c4e3ddf241aeaee4d2611bfe1949a373 F src/vdbe.c f1a9a29da48ccfa49042df478abb478520589f37 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3 F src/vdbeInt.h 8e360d326328e7a66100f468697edf9cfb4567dc -F src/vdbeapi.c ffd28fa0f731467a1e63155abc74cd149e57d671 +F src/vdbeapi.c 16268e7a2614051c9c7f93679d9102b03206c129 F src/vdbeaux.c 14b48bfc6334682e5e5858a0835f8b00d8751953 -F src/vdbeblob.c cf9ee3c7d9977cbd896f8b118da4fb4268637f4f +F src/vdbeblob.c ac223e6d3acaa3321ce09c11c47bf0d05b37372f F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 2843e6f91e8f19cfd72cfc7b24a03f1647db3c28 F src/vtab.c ee29237ecc9b310dc43c0c2ac5caa6c6a20787be @@ -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 6225cd461cdd2132eeb480aa4deb8986b7f63c15 -R 75c714761e5d5dec4034adbc16c873e3 -U danielk1977 -Z ca42567df49c41054078dbc0243fa598 +P 3fb97a63ef70662abdba18ce8b480e6b0badcfb1 +R ebd0701e4b840e7f444fe74a84efea35 +U drh +Z 4a9c7281bbaf4cab164c43383497e97b diff --git a/manifest.uuid b/manifest.uuid index f405a8ffe5..082b6ce149 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3fb97a63ef70662abdba18ce8b480e6b0badcfb1 \ No newline at end of file +3787563e90d7210d349ee36484c3f008c955552e \ No newline at end of file diff --git a/src/loadext.c b/src/loadext.c index 5e854e9334..b5dc4f5fd1 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -356,13 +356,16 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ } /* -** A list of automatically loaded extensions. +** The following object holds the list of automatically loaded +** extensions. ** -** This list is shared across threads, so be sure to hold the -** mutex while accessing or changing it. +** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER +** mutex must be held while accessing this list. */ -static int nAutoExtension = 0; -static void **aAutoExtension = 0; +static struct { + int nExt; /* Number of entries in aExt[] */ + void **aExt; /* Pointers to the extension init functions */ +} autoext = { 0, 0 }; /* @@ -374,17 +377,19 @@ int sqlite3_auto_extension(void *xInit){ int rc = SQLITE_OK; sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(mutex); - for(i=0; i=nAutoExtension ){ + if( i>=autoext.nExt ){ xInit = 0; go = 0; }else{ xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) - aAutoExtension[i]; + autoext.aExt[i]; } sqlite3_mutex_leave(mutex); if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){ diff --git a/src/main.c b/src/main.c index 719ecb634b..0cdda648e1 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.390 2007/08/21 10:44:16 drh Exp $ +** $Id: main.c,v 1.391 2007/08/21 15:13:19 drh Exp $ */ #include "sqliteInt.h" #include @@ -118,6 +118,7 @@ int sqlite3_close(sqlite3 *db){ if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } + sqlite3_mutex_enter(db->mutex); #ifdef SQLITE_SSE { @@ -218,6 +219,8 @@ int sqlite3_close(sqlite3 *db){ */ sqlite3_free(db->aDb[1].pSchema); sqlite3_vfs_release(db->pVfs); + sqlite3_mutex_leave(db->mutex); + sqlite3_mutex_free(db->mutex); sqlite3_free(db); return SQLITE_OK; } @@ -890,7 +893,9 @@ static int createCollation( */ static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ - sqlite3 **ppDb /* OUT: Returned database handle */ + sqlite3 **ppDb, /* OUT: Returned database handle */ + unsigned flags, /* Operational flags */ + const char *zVfs /* Name of the VFS to use */ ){ sqlite3 *db; int rc; @@ -899,7 +904,12 @@ static int openDatabase( /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; - db->pVfs = sqlite3_vfs_find(0); + db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); + if( db->mutex==0 ){ + db->mallocFailed = 1; + goto opendb_out; + } + db->pVfs = sqlite3_vfs_find(zVfs); db->errMask = 0xff; db->priorNewRowid = 0; db->magic = SQLITE_MAGIC_BUSY; @@ -1041,7 +1051,16 @@ int sqlite3_open( const char *zFilename, sqlite3 **ppDb ){ - return openDatabase(zFilename, ppDb); + return openDatabase(zFilename, ppDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); +} +int sqlite3_open_v2( + 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 */ +){ + return openDatabase(filename, ppDb, flags, zVfs); } #ifndef SQLITE_OMIT_UTF16 @@ -1063,7 +1082,8 @@ int sqlite3_open16( sqlite3ValueSetStr(0, pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); zFilename8 = sqlite3ValueText(0, pVal, SQLITE_UTF8); if( zFilename8 ){ - rc = openDatabase(zFilename8, ppDb); + rc = openDatabase(zFilename8, ppDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); if( rc==SQLITE_OK && *ppDb ){ rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); if( rc!=SQLITE_OK ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d70e0444e6..55f9204220 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.231 2007/08/20 22:48:43 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.232 2007/08/21 15:13:19 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1619,6 +1619,10 @@ int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); ** are used (where NNN is an integer) then there might be gaps in the ** numbering and the value returned by this interface is the index of the ** host parameter with the largest index value. +** +** The prepared statement must not not be [sqlite3_finalize | finalized] +** prior to this routine returnning. Otherwise the results are undefined +** and probably undesirable. */ int sqlite3_bind_parameter_count(sqlite3_stmt*); @@ -2222,7 +2226,7 @@ int sqlite3_value_numeric_type(sqlite3_value*); ** function. ** ** This routine must be called from the same thread in which -** the aggregate SQL function was originally invoked. +** the aggregate SQL function is running. */ void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); @@ -2788,7 +2792,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff); ** ** Register an extension entry point that is automatically invoked ** whenever a new database connection is opened using -** [sqlite3_open()] or [sqlite3_open16()]. +** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. ** ** This API can be invoked at program startup in order to register ** one or more statically linked extensions that will be available diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 1226956080..ffe89b24c8 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -719,29 +719,34 @@ static int vdbeUnbind(Vdbe *p, int i){ ** Bind a text or BLOB value. */ static int bindText( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, - void (*xDel)(void*), - int encoding + sqlite3_stmt *pStmt, /* The statement to bind against */ + int i, /* Index of the parameter to bind */ + const void *zData, /* Pointer to the data to be bound */ + int nData, /* Number of bytes of data to be bound */ + void (*xDel)(void*), /* Destructor for the data */ + int encoding /* Encoding for the data */ ){ Vdbe *p = (Vdbe *)pStmt; Mem *pVar; int rc; + if( p==0 ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } pVar = &p->aVar[i-1]; - rc = sqlite3VdbeMemSetStr(0, pVar, zData, nData, encoding, xDel); + rc = sqlite3VdbeMemSetStr(p->db, pVar, zData, nData, encoding, xDel); if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(p->db, pVar, ENC(p->db)); } - sqlite3Error(p->db, rc, 0); - return sqlite3ApiExit(p->db, rc); + rc = sqlite3ApiExit(p->db, rc); + sqlite3_mutex_leave(p->db->mutex); + return rc; } @@ -760,10 +765,12 @@ int sqlite3_bind_blob( int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); 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){ @@ -772,14 +779,21 @@ int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); } + sqlite3_mutex_leave(p->db->mutex); return rc; } -int sqlite3_bind_null(sqlite3_stmt* p, int i){ - return vdbeUnbind((Vdbe *)p, i); +int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + sqlite3_mutex_enter(p->db->mutex); + rc = vdbeUnbind(p, i); + sqlite3_mutex_leave(p->db->mutex); + return rc; } int sqlite3_bind_text( sqlite3_stmt *pStmt, @@ -804,19 +818,23 @@ int sqlite3_bind_text16( int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ rc = sqlite3VdbeMemCopy(0, &p->aVar[i-1], pValue); } + sqlite3_mutex_leave(p->db->mutex); return rc; } int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){ int rc; Vdbe *p = (Vdbe *)pStmt; + sqlite3_mutex_enter(p->db->mutex); rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n); } + sqlite3_mutex_leave(p->db->mutex); return rc; } @@ -836,15 +854,19 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ */ static void createVarMap(Vdbe *p){ if( !p->okVar ){ - int j; - Op *pOp; - for(j=0, pOp=p->aOp; jnOp; j++, pOp++){ - if( pOp->opcode==OP_Variable ){ - assert( pOp->p1>0 && pOp->p1<=p->nVar ); - p->azVar[pOp->p1-1] = pOp->p3; + sqlite3_mutex_enter(p->db->mutex); + if( !p->okVar ){ + int j; + Op *pOp; + for(j=0, pOp=p->aOp; jnOp; j++, pOp++){ + if( pOp->opcode==OP_Variable ){ + assert( pOp->p1>0 && pOp->p1<=p->nVar ); + p->azVar[pOp->p1-1] = pOp->p3; + } } + p->okVar = 1; } - p->okVar = 1; + sqlite3_mutex_leave(p->db->mutex); } } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 8fdf063803..216803123a 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -12,7 +12,7 @@ ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.12 2007/08/16 04:30:41 drh Exp $ +** $Id: vdbeblob.c,v 1.13 2007/08/21 15:13:19 drh Exp $ */ #include "sqliteInt.h" @@ -30,6 +30,7 @@ struct Incrblob { int iOffset; /* Byte offset of blob in cursor data */ BtCursor *pCsr; /* Cursor pointing at blob row */ sqlite3_stmt *pStmt; /* Statement holding cursor open */ + sqlite3 *db; /* The associated database */ }; /* @@ -87,6 +88,7 @@ int sqlite3_blob_open( char zErr[128]; zErr[0] = 0; + sqlite3_mutex_enter(db->mutex); do { Parse sParse; Table *pTab; @@ -96,6 +98,7 @@ int sqlite3_blob_open( rc = sqlite3SafetyOn(db); if( rc!=SQLITE_OK ){ + sqlite3_mutex_leave(db->mutex); return rc; } @@ -219,6 +222,7 @@ int sqlite3_blob_open( pBlob->pStmt = (sqlite3_stmt *)v; pBlob->iOffset = v->apCsr[0]->aOffset[iCol]; pBlob->nByte = sqlite3VdbeSerialTypeLen(type); + pBlob->db = db; *ppBlob = (sqlite3_blob *)pBlob; rc = SQLITE_OK; }else if( rc==SQLITE_OK ){ @@ -232,7 +236,9 @@ blob_open_out: sqlite3_finalize((sqlite3_stmt *)v); } sqlite3Error(db, rc, (rc==SQLITE_OK?0:zErr)); - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } /* @@ -241,12 +247,20 @@ blob_open_out: */ int sqlite3_blob_close(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob; - sqlite3_stmt *pStmt = p->pStmt; + sqlite3_stmt *pStmt; + sqlite3_mutex *mutex = p->db->mutex; + int rc; + + sqlite3_mutex_enter(mutex); + rc = sqlite3_finalize(p->pStmt); + sqlite3_mutex_leave(mutex); sqlite3_free(p); - return sqlite3_finalize(pStmt); + return rc; } - +/* +** Perform a read or write operation on a blob +*/ static int blobReadWrite( sqlite3_blob *pBlob, void *z, @@ -256,33 +270,38 @@ static int blobReadWrite( ){ int rc; Incrblob *p = (Incrblob *)pBlob; - Vdbe *v = (Vdbe *)(p->pStmt); - sqlite3 *db; - - /* If there is no statement handle, then the blob-handle has - ** already been invalidated. Return SQLITE_ABORT in this case. - */ - if( !v ) return SQLITE_ABORT; + Vdbe *v; + sqlite3 *db = p->db; /* Request is out of range. Return a transient error. */ if( (iOffset+n)>p->nByte ){ return SQLITE_ERROR; } + sqlite3_mutex_enter(db->mutex); - /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is - ** returned, clean-up the statement handle. + /* If there is no statement handle, then the blob-handle has + ** already been invalidated. Return SQLITE_ABORT in this case. */ - db = v->db; - rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); - if( rc==SQLITE_ABORT ){ - sqlite3VdbeFinalize(v); - p->pStmt = 0; + v = (Vdbe*)p->pStmt; + if( v==0 ){ + rc = SQLITE_ABORT; }else{ - db->errCode = rc; - v->rc = rc; + /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is + ** returned, clean-up the statement handle. + */ + assert( db == v->db ); + rc = xCall(p->pCsr, iOffset+p->iOffset, n, z); + if( rc==SQLITE_ABORT ){ + sqlite3VdbeFinalize(v); + p->pStmt = 0; + }else{ + db->errCode = rc; + v->rc = rc; + } } - - return sqlite3ApiExit(db, rc); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; } /* @@ -301,6 +320,9 @@ int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){ /* ** Query a blob handle for the size of the data. +** +** The Incrblob.nByte field is fixed for the lifetime of the Incrblob +** so no mutex is required for access. */ int sqlite3_blob_bytes(sqlite3_blob *pBlob){ Incrblob *p = (Incrblob *)pBlob;