diff options
author | drh <drh@noemail.net> | 2000-06-02 01:17:37 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2000-06-02 01:17:37 +0000 |
commit | 58b9576b7ab3e6d06836f2a1cd8b2bdcfe9758bb (patch) | |
tree | 3a2924d36d72c801f074c8516f38722d8a5074ad /src | |
parent | 5494880a71a6086ee561b8365bf0d8a2a8cfff10 (diff) | |
download | sqlite-58b9576b7ab3e6d06836f2a1cd8b2bdcfe9758bb.tar.gz sqlite-58b9576b7ab3e6d06836f2a1cd8b2bdcfe9758bb.zip |
:-) (CVS 34)
FossilOrigin-Name: 52338f4ab5990fefc61f615cd65c3a724b365199
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 16 | ||||
-rw-r--r-- | src/dbbe.c | 120 | ||||
-rw-r--r-- | src/dbbe.h | 6 | ||||
-rw-r--r-- | src/delete.c | 5 | ||||
-rw-r--r-- | src/insert.c | 6 | ||||
-rw-r--r-- | src/main.c | 84 | ||||
-rw-r--r-- | src/sqlite.h | 22 | ||||
-rw-r--r-- | src/sqliteInt.h | 10 | ||||
-rw-r--r-- | src/tclsqlite.c | 4 | ||||
-rw-r--r-- | src/update.c | 5 | ||||
-rw-r--r-- | src/vdbe.c | 107 |
11 files changed, 240 insertions, 145 deletions
diff --git a/src/build.c b/src/build.c index 380ce94a0..d5e98435c 100644 --- a/src/build.c +++ b/src/build.c @@ -24,7 +24,7 @@ ** This file contains C code routines that are called by the parser ** when syntax rules are reduced. ** -** $Id: build.c,v 1.11 2000/05/31 15:34:52 drh Exp $ +** $Id: build.c,v 1.12 2000/06/02 01:17:37 drh Exp $ */ #include "sqliteInt.h" @@ -287,7 +287,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd){ */ if( !pParse->initFlag ){ static VdbeOp addTable[] = { - { OP_Open, 0, 0, MASTER_NAME }, + { OP_Open, 0, 1, MASTER_NAME }, { OP_New, 0, 0, 0}, { OP_String, 0, 0, "table" }, { OP_String, 0, 0, 0}, /* 3 */ @@ -353,7 +353,7 @@ void sqliteDropTable(Parse *pParse, Token *pName){ } if( v ){ static VdbeOp dropTable[] = { - { OP_Open, 0, 0, MASTER_NAME }, + { OP_Open, 0, 1, MASTER_NAME }, { OP_ListOpen, 0, 0, 0}, { OP_String, 0, 0, 0}, /* 2 */ { OP_Next, 0, ADDR(10), 0}, /* 3 */ @@ -529,7 +529,7 @@ void sqliteCreateIndex( */ if( pParse->initFlag==0 ){ static VdbeOp addTable[] = { - { OP_Open, 0, 0, MASTER_NAME}, + { OP_Open, 0, 1, MASTER_NAME}, { OP_New, 0, 0, 0}, { OP_String, 0, 0, "index"}, { OP_String, 0, 0, 0}, /* 3 */ @@ -557,7 +557,7 @@ void sqliteCreateIndex( sqliteVdbeChangeP3(v, base+5, pStart->z, n); } sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0); - sqliteVdbeAddOp(v, OP_Open, 1, 0, pIndex->zName, 0); + sqliteVdbeAddOp(v, OP_Open, 1, 1, pIndex->zName, 0); lbl1 = sqliteVdbeMakeLabel(v); lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1); @@ -608,7 +608,7 @@ void sqliteDropIndex(Parse *pParse, Token *pName){ v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe); if( v ){ static VdbeOp dropIndex[] = { - { OP_Open, 0, 0, MASTER_NAME}, + { OP_Open, 0, 1, MASTER_NAME}, { OP_ListOpen, 0, 0, 0}, { OP_String, 0, 0, 0}, /* 2 */ { OP_Next, 0, ADDR(9), 0}, /* 3 */ @@ -781,9 +781,9 @@ void sqliteCopy( addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0); sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n); sqliteVdbeDequoteP3(v, addr); - sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0); + sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ - sqliteVdbeAddOp(v, OP_Open, i, 0, pIdx->zName, 0); + sqliteVdbeAddOp(v, OP_Open, i, 1, pIdx->zName, 0); } end = sqliteVdbeMakeLabel(v); addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end, 0, 0); diff --git a/src/dbbe.c b/src/dbbe.c index 6d8ed4222..321a5de2e 100644 --- a/src/dbbe.c +++ b/src/dbbe.c @@ -30,7 +30,7 @@ ** relatively simple to convert to a different database such ** as NDBM, SDBM, or BerkeleyDB. ** -** $Id: dbbe.c,v 1.6 2000/05/31 22:58:39 drh Exp $ +** $Id: dbbe.c,v 1.7 2000/06/02 01:17:37 drh Exp $ */ #include "sqliteInt.h" #include <gdbm.h> @@ -48,6 +48,7 @@ struct BeFile { GDBM_FILE dbf; /* The file itself */ int nRef; /* Number of references */ int delOnClose; /* Delete when closing */ + int writeable; /* Opened for writing */ BeFile *pNext, *pPrev; /* Next and previous on list of open files */ }; @@ -128,21 +129,40 @@ static int rc4byte(struct rc4 *p){ */ Dbbe *sqliteDbbeOpen( const char *zName, /* The name of the database */ - int write, /* True if we will be writing to the database */ - int create, /* True to create database if it doesn't exist */ + int writeFlag, /* True if we will be writing to the database */ + int createFlag, /* True to create database if it doesn't exist */ char **pzErrMsg /* Write error messages (if any) here */ ){ Dbbe *pNew; struct stat statbuf; + char *zMaster; + if( !writeFlag ) createFlag = 0; if( stat(zName, &statbuf)!=0 ){ - sqliteSetString(pzErrMsg, "can't find file \"", zName, "\"", 0); - return 0; + if( createFlag ) mkdir(zName, 0750); + if( stat(zName, &statbuf)!=0 ){ + sqliteSetString(pzErrMsg, "can't find or make directory \"", + zName, "\"", 0); + return 0; + } } if( !S_ISDIR(statbuf.st_mode) ){ sqliteSetString(pzErrMsg, "not a directory: \"", zName, "\"", 0); return 0; } + if( access(zName, writeFlag ? (X_OK|W_OK|R_OK) : (X_OK|R_OK)) ){ + sqliteSetString(pzErrMsg, "access permission denied", 0); + return 0; + } + zMaster = 0; + sqliteSetString(&zMaster, zName, "/" MASTER_NAME, 0); + if( stat(zMaster, &statbuf)==0 + && access(zMaster, writeFlag ? (W_OK|R_OK) : R_OK)!=0 ){ + sqliteSetString(pzErrMsg, "access permission denied for ", zMaster, 0); + sqliteFree(zMaster); + return 0; + } + sqliteFree(zMaster); pNew = sqliteMalloc(sizeof(Dbbe) + strlen(zName) + 1); if( pNew==0 ){ sqliteSetString(pzErrMsg, "out of memory", 0); @@ -150,7 +170,7 @@ Dbbe *sqliteDbbeOpen( } pNew->zDir = (char*)&pNew[1]; strcpy(pNew->zDir, zName); - pNew->write = write; + pNew->write = writeFlag; pNew->pOpen = 0; time(&statbuf.st_ctime); rc4init(&pNew->rc4, (char*)&statbuf, sizeof(statbuf)); @@ -212,17 +232,22 @@ static void randomName(struct rc4 *pRc4, char *zBuf, char *zPrefix){ /* ** Open a new table cursor */ -DbbeTable *sqliteDbbeOpenTable( +int sqliteDbbeOpenTable( Dbbe *pBe, /* The database the table belongs to */ const char *zTable, /* The name of the table */ - int writeable /* True to open for writing */ + int writeable, /* True to open for writing */ + DbbeTable **ppTable /* Write the resulting table pointer here */ ){ char *zFile; /* Name of the table file */ DbbeTable *pTable; /* The new table cursor */ BeFile *pFile; /* The underlying data file for this table */ + int rc = SQLITE_OK; /* Return value */ + int rw_mask; /* Permissions mask for opening a table */ + int mode; /* Mode for opening a table */ + *ppTable = 0; pTable = sqliteMalloc( sizeof(*pTable) ); - if( pTable==0 ) return 0; + if( pTable==0 ) return SQLITE_NOMEM; if( zTable ){ zFile = sqliteFileOfTable(pBe, zTable); for(pFile=pBe->pOpen; pFile; pFile=pFile->pNext){ @@ -233,21 +258,20 @@ DbbeTable *sqliteDbbeOpenTable( zFile = 0; } if( pFile==0 ){ + if( writeable ){ + rw_mask = GDBM_WRCREAT | GDBM_FAST; + mode = 0640; + }else{ + rw_mask = GDBM_READER; + mode = 0640; + } pFile = sqliteMalloc( sizeof(*pFile) ); if( pFile==0 ){ sqliteFree(zFile); - return 0; + return SQLITE_NOMEM; } - pFile->zName = zFile; - pFile->nRef = 1; - pFile->pPrev = 0; - if( pBe->pOpen ){ - pBe->pOpen->pPrev = pFile; - } - pFile->pNext = pBe->pOpen; - pBe->pOpen = pFile; if( pFile->zName ){ - pFile->dbf = gdbm_open(pFile->zName, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0); + pFile->dbf = gdbm_open(pFile->zName, 0, rw_mask, mode, 0); }else{ int limit; struct rc4 *pRc4; @@ -259,20 +283,35 @@ DbbeTable *sqliteDbbeOpenTable( randomName(&pBe->rc4, zRandom, "_temp_table_"); sqliteFree(zFile); zFile = sqliteFileOfTable(pBe, zRandom); - pFile->dbf = gdbm_open(zFile, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0); + pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0); }while( pFile->dbf==0 && limit-- >= 0); - pFile->zName = zFile; pFile->delOnClose = 1; } + pFile->writeable = writeable; + pFile->zName = zFile; + pFile->nRef = 1; + pFile->pPrev = 0; + if( pBe->pOpen ){ + pBe->pOpen->pPrev = pFile; + } + pFile->pNext = pBe->pOpen; + pBe->pOpen = pFile; + if( pFile->dbf==0 ){ + rc = SQLITE_BUSY; + } }else{ sqliteFree(zFile); pFile->nRef++; + if( writeable && !pFile->writeable ){ + rc = SQLITE_READONLY; + } } pTable->pBe = pBe; pTable->pFile = pFile; pTable->readPending = 0; pTable->needRewind = 1; - return pTable; + *ppTable = pTable; + return rc; } /* @@ -293,7 +332,9 @@ void sqliteDbbeReorganizeTable(Dbbe *pBe, const char *zTable){ char *zFile; /* Name of the table file */ DbbeTable *pTab; - pTab = sqliteDbbeOpenTable(pBe, zTable, 1); + if( sqliteDbbeOpenTable(pBe, zTable, 1, &pTab)!=SQLITE_OK ){ + return; + } if( pTab && pTab->pFile && pTab->pFile->dbf ){ gdbm_reorganize(pTab->pFile->dbf); } @@ -448,7 +489,7 @@ int sqliteDbbeDataLength(DbbeTable *pTable){ */ int sqliteDbbeRewind(DbbeTable *pTable){ pTable->needRewind = 1; - return 0; + return SQLITE_OK; } /* @@ -512,15 +553,17 @@ int sqliteDbbeNew(DbbeTable *pTable){ */ int sqliteDbbePut(DbbeTable *pTable, int nKey,char *pKey,int nData,char *pData){ datum data, key; - if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return 0; + int rc; + if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return SQLITE_ERROR; data.dsize = nData; data.dptr = pData; key.dsize = nKey; key.dptr = pKey; - gdbm_store(pTable->pFile->dbf, key, data, GDBM_REPLACE); + rc = gdbm_store(pTable->pFile->dbf, key, data, GDBM_REPLACE); + if( rc ) rc = SQLITE_ERROR; datumClear(&pTable->key); datumClear(&pTable->data); - return 1; + return rc; } /* @@ -528,23 +571,26 @@ int sqliteDbbePut(DbbeTable *pTable, int nKey,char *pKey,int nData,char *pData){ */ int sqliteDbbeDelete(DbbeTable *pTable, int nKey, char *pKey){ datum key; + int rc; datumClear(&pTable->key); datumClear(&pTable->data); - if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return 0; + if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return SQLITE_ERROR; key.dsize = nKey; key.dptr = pKey; - gdbm_delete(pTable->pFile->dbf, key); - return 1; + rc = gdbm_delete(pTable->pFile->dbf, key); + if( rc ) rc = SQLITE_ERROR; + return rc; } /* ** Open a temporary file. */ -FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){ +int sqliteDbbeOpenTempFile(Dbbe *pBe, FILE **ppFile){ char *zFile; char zBuf[50]; int i, j; int limit; + int rc = SQLITE_OK; for(i=0; i<pBe->nTemp; i++){ if( pBe->apTemp[i]==0 ) break; @@ -553,7 +599,10 @@ FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){ pBe->nTemp++; pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) ); } - if( pBe->apTemp==0 ) return 0; + if( pBe->apTemp==0 ){ + *ppFile = 0; + return SQLITE_NOMEM; + } limit = 4; zFile = 0; do{ @@ -562,9 +611,12 @@ FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){ zFile = 0; sqliteSetString(&zFile, pBe->zDir, zBuf, 0); }while( access(zFile,0)==0 && limit-- >= 0 ); - pBe->apTemp[i] = fopen(zFile, "w+"); + *ppFile = pBe->apTemp[i] = fopen(zFile, "w+"); + if( pBe->apTemp[i]==0 ){ + rc = SQLITE_ERROR; + } sqliteFree(zFile); - return pBe->apTemp[i]; + return rc; } /* diff --git a/src/dbbe.h b/src/dbbe.h index b5e36011d..b30e04a7a 100644 --- a/src/dbbe.h +++ b/src/dbbe.h @@ -28,7 +28,7 @@ ** This library was originally designed to support the following ** backends: GDBM, NDBM, SDBM, Berkeley DB. ** -** $Id: dbbe.h,v 1.3 2000/05/31 20:00:52 drh Exp $ +** $Id: dbbe.h,v 1.4 2000/06/02 01:17:37 drh Exp $ */ #ifndef _SQLITE_DBBE_H_ #define _SQLITE_DBBE_H_ @@ -63,7 +63,7 @@ void sqliteDbbeClose(Dbbe*); ** If zTableName is 0 or "", then a temporary table is created that ** will be deleted when closed. */ -DbbeTable *sqliteDbbeOpenTable(Dbbe*, const char *zTableName, int writeable); +int sqliteDbbeOpenTable(Dbbe*, const char *zName, int writeable, DbbeTable **); /* Delete a table from the database */ void sqliteDbbeDropTable(Dbbe*, const char *zTableName); @@ -122,7 +122,7 @@ int sqliteDbbePut(DbbeTable*, int nKey, char *pKey, int nData, char *pData); int sqliteDbbeDelete(DbbeTable*, int nKey, char *pKey); /* Open a file suitable for temporary storage */ -FILE *sqliteDbbeOpenTempFile(Dbbe*); +int sqliteDbbeOpenTempFile(Dbbe*, FILE**); /* Close a temporary file */ void sqliteDbbeCloseTempFile(Dbbe *, FILE *); diff --git a/src/delete.c b/src/delete.c index 3ab5f5940..498c35f22 100644 --- a/src/delete.c +++ b/src/delete.c @@ -24,7 +24,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.1 2000/05/31 15:34:53 drh Exp $ +** $Id: delete.c,v 1.2 2000/06/02 01:17:37 drh Exp $ */ #include "sqliteInt.h" @@ -103,8 +103,9 @@ void sqliteDeleteFrom( /* Delete every item identified in the list. */ sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0); + sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ - sqliteVdbeAddOp(v, OP_Open, i, 0, pIdx->zName, 0); + sqliteVdbeAddOp(v, OP_Open, i, 1, pIdx->zName, 0); } end = sqliteVdbeMakeLabel(v); addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end, 0, 0); diff --git a/src/insert.c b/src/insert.c index 071e642c7..85f9af86d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -24,7 +24,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements. ** -** $Id: insert.c,v 1.1 2000/05/31 15:34:53 drh Exp $ +** $Id: insert.c,v 1.2 2000/06/02 01:17:37 drh Exp $ */ #include "sqliteInt.h" @@ -104,7 +104,7 @@ void sqliteInsert( v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe); if( v ){ Index *pIdx; - sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0); + sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0); sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0); if( pTab->pIndex ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); @@ -130,7 +130,7 @@ void sqliteInsert( if( pIdx->pNext ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0); } - sqliteVdbeAddOp(v, OP_Open, 0, 0, pIdx->zName, 0); + sqliteVdbeAddOp(v, OP_Open, 0, 1, pIdx->zName, 0); for(i=0; i<pIdx->nField; i++){ int idx = pIdx->aiField[i]; if( pField==0 ){ diff --git a/src/main.c b/src/main.c index 4deac6de0..ec960e169 100644 --- a/src/main.c +++ b/src/main.c @@ -26,7 +26,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.2 2000/05/31 22:58:39 drh Exp $ +** $Id: main.c,v 1.3 2000/06/02 01:17:37 drh Exp $ */ #include "sqliteInt.h" @@ -51,14 +51,17 @@ static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){ } /* -** Open a new SQLite database. Construct an "sqlite" structure to define -** the state of this database and return a pointer to that structure. +** Attempt to read the database schema and initialize internal +** data structures. Return one of the SQLITE_ error codes to +** indicate success or failure. */ -sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ - sqlite *db; +static int sqliteInit(sqlite *db, char **pzErrMsg){ Vdbe *vdbe; - Table *pTab; - char *azArg[2]; + int rc; + + /* + ** The master database table has a structure like this + */ static char master_schema[] = "CREATE TABLE " MASTER_NAME " (\n" " type text,\n" @@ -116,7 +119,44 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ { OP_Halt, 0, 0, 0}, /* 16 */ }; - /* Allocate space to hold the main database structure */ + /* Create a virtual machine to run the initialization program. Run + ** the program. The delete the virtual machine. + */ + vdbe = sqliteVdbeCreate(db->pBe); + sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg); + rc = sqliteVdbeExec(vdbe, sqliteOpenCb, db, pzErrMsg); + sqliteVdbeDelete(vdbe); + if( rc==SQLITE_OK ){ + Table *pTab; + char *azArg[2]; + azArg[0] = master_schema; + azArg[1] = 0; + sqliteOpenCb(db, 1, azArg, 0); + pTab = sqliteFindTable(db, MASTER_NAME); + if( pTab ){ + pTab->readOnly = 1; + } + db->flags |= SQLITE_Initialized; + }else{ + sqliteStrRealloc(pzErrMsg); + } + return rc; +} + +/* +** Open a new SQLite database. Construct an "sqlite" structure to define +** the state of this database and return a pointer to that structure. +** +** An attempt is made to initialize the in-memory data structures that +** hold the database schema. But if this fails (because the schema file +** is locked) then that step is deferred until the first call to +** sqlite_exec(). +*/ +sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ + sqlite *db; + int rc; + + /* Allocate the sqlite data structure */ db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ){ @@ -132,20 +172,12 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ return 0; } - /* Create a virtual machine to run the initialization program. Run - ** the program. The delete the virtual machine. - */ - azArg[0] = master_schema; - azArg[1] = 0; - sqliteOpenCb(db, 1, azArg, 0); - pTab = sqliteFindTable(db, MASTER_NAME); - if( pTab ){ - pTab->readOnly = 1; + /* Attempt to read the schema */ + rc = sqliteInit(db, pzErrMsg); + if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ + sqlite_close(db); + return 0; } - vdbe = sqliteVdbeCreate(db->pBe); - sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg); - sqliteVdbeExec(vdbe, sqliteOpenCb, db, pzErrMsg); - sqliteVdbeDelete(vdbe); return db; } @@ -208,14 +240,18 @@ int sqlite_exec( char **pzErrMsg /* Write error messages here */ ){ Parse sParse; - int nErr; + int rc; if( pzErrMsg ) *pzErrMsg = 0; + if( (db->flags & SQLITE_Initialized)==0 ){ + int rc = sqliteInit(db, pzErrMsg); + if( rc!=SQLITE_OK ) return rc; + } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.xCallback = xCallback; sParse.pArg = pArg; - nErr = sqliteRunParser(&sParse, zSql, pzErrMsg); + rc = sqliteRunParser(&sParse, zSql, pzErrMsg); sqliteStrRealloc(pzErrMsg); - return nErr; + return rc; } diff --git a/src/sqlite.h b/src/sqlite.h index 26b48746a..164ed11e1 100644 --- a/src/sqlite.h +++ b/src/sqlite.h @@ -24,7 +24,7 @@ ** This header file defines the interface that the sqlite library ** presents to client programs. ** -** @(#) $Id: sqlite.h,v 1.1 2000/05/29 14:26:01 drh Exp $ +** @(#) $Id: sqlite.h,v 1.2 2000/06/02 01:17:38 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -75,8 +75,7 @@ typedef int (*sqlite_callback)(void*,int,char**, char**); ** invoked once for each row of the query result. This callback ** should normally return 0. If the callback returns a non-zero ** value then the query is aborted, all subsequent SQL statements -** are skipped and the sqlite_exec() function returns the same -** value that the callback returned. +** are skipped and the sqlite_exec() function returns the SQLITE_ABORT. ** ** The 4th parameter is an arbitrary pointer that is passed ** to the callback function as its first parameter. @@ -95,7 +94,12 @@ typedef int (*sqlite_callback)(void*,int,char**, char**); ** message is written into memory obtained from malloc() and ** *errmsg is made to point to that message. If errmsg==NULL, ** then no error message is ever written. The return value is -** non-zero if an error occurs. +** SQLITE_ERROR if an error occurs. +** +** If the query could not be executed because a database file is +** locked or busy, then this function returns SQLITE_BUSY. If +** the query could not be executed because a file is missing or +** has incorrect permissions, this function returns SQLITE_ERROR. */ int sqlite_exec( sqlite*, /* An open database */ @@ -105,6 +109,16 @@ int sqlite_exec( char **errmsg /* Error msg written here */ ); +/* +** Return values fro sqlite_exec() +*/ +#define SQLITE_OK 0 /* Successful result */ +#define SQLITE_INTERNAL 1 /* An internal logic error in SQLite */ +#define SQLITE_ERROR 2 /* SQL error or missing database */ +#define SQLITE_ABORT 3 /* Callback routine requested an abort */ +#define SQLITE_BUSY 4 /* One or more database files are locked */ +#define SQLITE_NOMEM 5 /* A malloc() failed */ + /* This function returns true if the given input string comprises ** one or more complete SQL statements. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 08deeb275..5fa1917e4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -23,7 +23,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.7 2000/05/31 22:58:39 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.8 2000/06/02 01:17:38 drh Exp $ */ #include "sqlite.h" #include "dbbe.h" @@ -101,6 +101,14 @@ struct sqlite { ** Possible values for the flags field of sqlite */ #define SQLITE_VdbeTrace 0x00000001 +#define SQLITE_Initialized 0x00000002 + +/* +** Values for SQLITE_OK, SQLITE_ERROR, etc are defined in sqlite.h. +** The following are several new return codes that are used internally +** only. Take care that these values do not overlap. +*/ +#define SQLITE_READONLY 6 /* Table already opened as read-only */ /* ** Each table is represented in memory by diff --git a/src/tclsqlite.c b/src/tclsqlite.c index e261791cc..1499cf6e2 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -23,7 +23,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.3 2000/05/30 13:44:20 drh Exp $ +** $Id: tclsqlite.c,v 1.4 2000/06/02 01:17:38 drh Exp $ */ #include "sqlite.h" #include <tcl.h> @@ -201,7 +201,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){ return TCL_ERROR; } if( argc==3 ){ - mode = 0; + mode = 0666; }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){ return TCL_ERROR; } diff --git a/src/update.c b/src/update.c index a19846a91..8bd2e5dd0 100644 --- a/src/update.c +++ b/src/update.c @@ -24,7 +24,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.1 2000/05/31 15:34:53 drh Exp $ +** $Id: update.c,v 1.2 2000/06/02 01:17:38 drh Exp $ */ #include "sqliteInt.h" @@ -155,8 +155,9 @@ void sqliteUpdate( ** open every index that needs updating. */ sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0); + sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0); for(i=0; i<nIdx; i++){ - sqliteVdbeAddOp(v, OP_Open, i+1, 0, apIdx[i]->zName, 0); + sqliteVdbeAddOp(v, OP_Open, i+1, 1, apIdx[i]->zName, 0); } /* Loop over every record that needs updating. We have to load diff --git a/src/vdbe.c b/src/vdbe.c index 2c302ba08..766773e0d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -41,7 +41,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.6 2000/06/01 11:16:52 drh Exp $ +** $Id: vdbe.c,v 1.7 2000/06/02 01:17:38 drh Exp $ */ #include "sqliteInt.h" @@ -452,16 +452,18 @@ int sqliteVdbeList( azField[2] = zP1; azField[3] = zP2; azField[5] = 0; - rc = 0; + rc = SQLITE_OK; if( pzErrMsg ){ *pzErrMsg = 0; } - for(i=0; rc==0 && i<p->nOp; i++){ + for(i=0; rc==SQLITE_OK && i<p->nOp; i++){ sprintf(zAddr,"%d",i); sprintf(zP1,"%d", p->aOp[i].p1); sprintf(zP2,"%d", p->aOp[i].p2); azField[4] = p->aOp[i].p3; if( azField[4]==0 ) azField[4] = ""; azField[1] = zOpName[p->aOp[i].opcode]; - rc = xCallback(pArg, 5, azField, azColumnNames); + if( xCallback(pArg, 5, azField, azColumnNames) ){ + rc = SQLITE_ABORT; + } } return rc; } @@ -566,8 +568,15 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight){ ** The return parameter is the number of errors. ** ** If the callback every returns non-zero, then the program exits -** immediately. No error message is written but the return value -** from the callback because the return value of this routine. +** immediately. No error message but the function does return SQLITE_ABORT. +** +** A memory allocation error causes this routine to return SQLITE_NOMEM +** and abandon furture processing. +** +** Other fatal errors return SQLITE_ERROR. +** +** If a database file could not be opened because it is locked by +** another database instance, then this routine returns SQLITE_BUSY. */ int sqliteVdbeExec( Vdbe *p, /* The VDBE */ @@ -581,9 +590,9 @@ int sqliteVdbeExec( char zBuf[100]; /* Space to sprintf() and integer */ p->tos = -1; - rc = 0; + rc = SQLITE_OK; if( pzErrMsg ){ *pzErrMsg = 0; } - for(pc=0; rc==0 && pc<p->nOp && pc>=0; pc++){ + for(pc=0; rc==SQLITE_OK && pc<p->nOp && pc>=0; pc++){ pOp = &p->aOp[pc]; if( p->trace ){ fprintf(p->trace,"%4d %-12s %4d %4d %s\n", @@ -599,12 +608,7 @@ int sqliteVdbeExec( ** the program. */ case OP_Goto: { - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; break; } @@ -743,7 +747,9 @@ int sqliteVdbeExec( if( Stringify(p, j) ) goto no_mem; } p->zStack[p->tos+1] = 0; - rc = xCallback(pArg, pOp->p1, &p->zStack[i], p->azColName); + if( xCallback(pArg, pOp->p1, &p->zStack[i], p->azColName)!=0 ){ + rc = SQLITE_ABORT; + } PopStack(p, pOp->p1); break; } @@ -821,7 +827,7 @@ int sqliteVdbeExec( default: { if( a==0 ){ sqliteSetString(pzErrMsg, "division by zero", 0); - rc = 1; + rc = SQLITE_ERROR; goto cleanup; } b /= a; @@ -843,7 +849,7 @@ int sqliteVdbeExec( default: { if( a==0.0 ){ sqliteSetString(pzErrMsg, "division by zero", 0); - rc = 1; + rc = SQLITE_ERROR; goto cleanup; } b /= a; @@ -1293,7 +1299,7 @@ int sqliteVdbeExec( break; } - /* Open P1 P3 P2 + /* Opcode: Open P1 P2 P3 ** ** Open a new database table named P3. Give it an identifier P1. ** Open readonly if P2==0 and for reading and writing if P2!=0. @@ -1316,7 +1322,7 @@ int sqliteVdbeExec( }else if( p->aTab[i].pTable ){ sqliteDbbeCloseTable(p->aTab[i].pTable); } - p->aTab[i].pTable = sqliteDbbeOpenTable(p->pBe, pOp->p3, pOp->p2); + rc = sqliteDbbeOpenTable(p->pBe, pOp->p3, pOp->p2, &p->aTab[i].pTable); p->aTab[i].index = 0; break; } @@ -1351,7 +1357,8 @@ int sqliteVdbeExec( sqliteDbbeFetch(p->aTab[i].pTable, sizeof(int), (char*)&p->iStack[tos]); }else{ - sqliteDbbeFetch(p->aTab[i].pTable, p->iStack[tos], p->zStack[tos]); + sqliteDbbeFetch(p->aTab[i].pTable, p->iStack[tos], + p->zStack[tos]); } } PopStack(p, 1); @@ -1380,12 +1387,7 @@ int sqliteVdbeExec( } } if( !alreadyExists ){ - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; } break; } @@ -1536,12 +1538,7 @@ int sqliteVdbeExec( int i = pOp->p1; if( i>=0 && i<p->nTable && p->aTab[i].pTable!=0 ){ if( sqliteDbbeNextKey(p->aTab[i].pTable)==0 ){ - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; } } break; @@ -1587,12 +1584,7 @@ int sqliteVdbeExec( } if( j>=nIdx ){ j = -1; - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; PopStack(p, 1); } p->aTab[i].index = j+1; @@ -1721,7 +1713,7 @@ int sqliteVdbeExec( }else if( p->apList[i] ){ sqliteDbbeCloseTempFile(p->pBe, p->apList[i]); } - p->apList[i] = sqliteDbbeOpenTempFile(p->pBe); + rc = sqliteDbbeOpenTempFile(p->pBe, &p->apList[i]); break; } @@ -1772,12 +1764,7 @@ int sqliteVdbeExec( p->iStack[p->tos] = val; p->zStack[p->tos] = 0; }else{ - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; } break; } @@ -1980,12 +1967,7 @@ int sqliteVdbeExec( sqliteFree(pSorter->zKey); sqliteFree(pSorter); }else{ - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; } break; } @@ -2018,7 +2000,9 @@ int sqliteVdbeExec( case OP_SortCallback: { int i = p->tos; if( i<0 ) goto not_enough_stack; - rc = xCallback(pArg, pOp->p1, (char**)p->zStack[i], p->azColName); + if( xCallback(pArg, pOp->p1, (char**)p->zStack[i], p->azColName) ){ + rc = SQLITE_ABORT; + } PopStack(p, 1); break; } @@ -2060,7 +2044,7 @@ int sqliteVdbeExec( } if( p->pFile==0 ){ sqliteSetString(pzErrMsg,"unable to open file: ", pOp->p3, 0); - rc = 1; + rc = SQLITE_ERROR; goto cleanup; } break; @@ -2160,12 +2144,7 @@ int sqliteVdbeExec( /* If we reach end-of-file, or if anything goes wrong, jump here. ** This code will cause a jump to P2 */ fileread_jump: - pc = pOp->p2; - if( pc<0 || pc>p->nOp ){ - sqliteSetString(pzErrMsg, "jump destination out of range", 0); - rc = 1; - } - pc--; + pc = pOp->p2 - 1; break; } @@ -2195,10 +2174,14 @@ int sqliteVdbeExec( default: { sprintf(zBuf,"%d",pOp->opcode); sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0); - rc = 1; + rc = SQLITE_INTERNAL; break; } } + if( pc<-1 || pc>=p->nOp ){ + sqliteSetString(pzErrMsg, "jump destination out of range", 0); + rc = SQLITE_INTERNAL; + } if( p->trace && p->tos>=0 ){ int i; fprintf(p->trace, "Stack:"); @@ -2231,7 +2214,7 @@ no_mem: not_enough_stack: sprintf(zBuf,"%d",pc); sqliteSetString(pzErrMsg, "too few operands on stack at ", zBuf, 0); - rc = 1; + rc = SQLITE_INTERNAL; goto cleanup; /* Jump here if an illegal or illformed instruction is executed. @@ -2239,7 +2222,7 @@ not_enough_stack: bad_instruction: sprintf(zBuf,"%d",pc); sqliteSetString(pzErrMsg, "illegal operation at ", zBuf, 0); - rc = 1; + rc = SQLITE_INTERNAL; goto cleanup; } |