-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
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
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
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
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
-3fb97a63ef70662abdba18ce8b480e6b0badcfb1
\ No newline at end of file
+3787563e90d7210d349ee36484c3f008c955552e
\ No newline at end of file
}
/*
-** 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 };
/*
int rc = SQLITE_OK;
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutex);
- for(i=0; i<nAutoExtension; i++){
- if( aAutoExtension[i]==xInit ) break;
+ for(i=0; i<autoext.nExt; i++){
+ if( autoext.aExt[i]==xInit ) break;
}
- if( i==nAutoExtension ){
- int nByte = (++nAutoExtension)*sizeof(aAutoExtension[0]);
- aAutoExtension = sqlite3_realloc(aAutoExtension, nByte);
- if( aAutoExtension==0 ){
- nAutoExtension = 0;
+ if( i==autoext.nExt ){
+ int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
+ void **aNew;
+ aNew = sqlite3_realloc(autoext.aExt, nByte);
+ if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
- aAutoExtension[nAutoExtension-1] = xInit;
+ autoext.aExt = aNew;
+ autoext.aExt[autoext.nExt] = xInit;
+ autoext.nExt++;
}
}
sqlite3_mutex_leave(mutex);
void sqlite3_reset_auto_extension(void){
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutex);
- sqlite3_free(aAutoExtension);
- aAutoExtension = 0;
- nAutoExtension = 0;
+ sqlite3_free(autoext.aExt);
+ autoext.aExt = 0;
+ autoext.nExt = 0;
sqlite3_mutex_leave(mutex);
}
int rc = SQLITE_OK;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
- if( nAutoExtension==0 ){
+ if( autoext.nExt==0 ){
/* Common case: early out without every having to acquire a mutex */
return SQLITE_OK;
}
char *zErrmsg = 0;
sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutex);
- if( 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) ){
** 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 <ctype.h>
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
+ sqlite3_mutex_enter(db->mutex);
#ifdef SQLITE_SSE
{
*/
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;
}
*/
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;
/* 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;
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
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 ){
** 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_
** 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*);
** 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);
**
** 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
** 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;
}
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){
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,
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;
}
*/
static void createVarMap(Vdbe *p){
if( !p->okVar ){
- int j;
- Op *pOp;
- for(j=0, pOp=p->aOp; j<p->nOp; 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; j<p->nOp; 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);
}
}
**
** 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"
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 */
};
/*
char zErr[128];
zErr[0] = 0;
+ sqlite3_mutex_enter(db->mutex);
do {
Parse sParse;
Table *pTab;
rc = sqlite3SafetyOn(db);
if( rc!=SQLITE_OK ){
+ sqlite3_mutex_leave(db->mutex);
return rc;
}
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 ){
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;
}
/*
*/
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,
){
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;
}
/*
/*
** 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;