]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
:-) (CVS 34)
authordrh <drh@noemail.net>
Fri, 2 Jun 2000 01:17:37 +0000 (01:17 +0000)
committerdrh <drh@noemail.net>
Fri, 2 Jun 2000 01:17:37 +0000 (01:17 +0000)
FossilOrigin-Name: 52338f4ab5990fefc61f615cd65c3a724b365199

13 files changed:
manifest
manifest.uuid
src/build.c
src/dbbe.c
src/dbbe.h
src/delete.c
src/insert.c
src/main.c
src/sqlite.h
src/sqliteInt.h
src/tclsqlite.c
src/update.c
src/vdbe.c

index 0ca476e080c49985a669928d6f1db25328cf738d..19d413c33b93f97463df239f500ab356bb495b4c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,28 +1,28 @@
-C :-)\s(CVS\s33)
-D 2000-06-01T11:16:52
+C :-)\s(CVS\s34)
+D 2000-06-02T01:17:37
 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
 F Makefile.in 7ac2fef265940d93a544cb454efa836451559a71
 F README 6b5960603c7f8bf42fc022b4b6436f242f238dbb
 F configure 00a5b5c82147a576fa6e82d7c1b0d55c321d6d2c x
 F configure.in 6ccfd5fc80517f7cfe605a7fc7e0f62d962a233c
 F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
-F src/build.c 03f83e95d46e328a2ac08aace102b142ea38e6d7
-F src/dbbe.c da2bb60d72f848ed38b96ee01d163aa98592d52a
-F src/dbbe.h 0147c9f8539d421d6c5558d3e854b78387372fae
-F src/delete.c 16ef3418b19be9ab39db836c693970ca7bbff605
+F src/build.c f56c47f08c2f01fd640abb920c5da6b6614fbf3f
+F src/dbbe.c 5ab70123cae6b2791843817448cbc4964328f542
+F src/dbbe.h a8a46f71238e0f09f3ec08fd9d1c8c7f4cdc49bf
+F src/delete.c e11433c14ed5cc8553cba14296b3baa3c23054bc
 F src/expr.c 91970700e3e39b2b725b028c166f588a5bb0c038
-F src/insert.c bd34716d0bba5561f6b55101adbf16fa75f872e8
-F src/main.c a14b1e8837836e59eb4855bf22879c7139892276
+F src/insert.c 5d713f4a05cef76a188207aa986776e02349ba70
+F src/main.c ff4e6abaeac2033cf2ec206f932f7b4c768c469c
 F src/parse.y 16322c46ec117082ef745715f7a4761f2491a0b2
 F src/select.c 25cada7cb2b0b4973b3e17c81ba1b1c887829f71
 F src/shell.c 9a42923e9c8ec1654dd1ef1aa113eca26dcf30db
-F src/sqlite.h 2397c17a8f4ca90c09acab0100dc7e2f8f441b69
-F src/sqliteInt.h a3c662ff65826f3b51d4aa946b4201e864c4587c
-F src/tclsqlite.c 9efd29f79ded6a900aa3d142169c8bfe03b7affd
+F src/sqlite.h 91e551b1ec455a981fa935f19c32abc93867e382
+F src/sqliteInt.h 447a156c3b77378b34c8668d668002674db55205
+F src/tclsqlite.c 10c00c460246cfba375b768c90b22bfe3c774c8f
 F src/tokenize.c 15c229fee77325334c6814652e429b0930eba6c1
-F src/update.c 9194f548dafc9884d79489874e22974ed67cd6a2
+F src/update.c 1f7284e00921352c3ae699fb60f2c2fbf8098212
 F src/util.c da47fe65efa6ff4c5e663cc7c832964bd599c0d2
-F src/vdbe.c e2190038a8e19c44f85f0d1b1ea1b3e1f78dd44b
+F src/vdbe.c 8631fdffc2583c13594b34ffa9139928b7f3cb8f
 F src/vdbe.h ab574c91c6328c5795f68b84074fbcf860eae70e
 F src/where.c bed9a8360cbfbf712bdc397c8e22216a5e5f9800
 F test/all.test 66a8a5b8291a472157944edcdce51a320ebd1f35
@@ -45,7 +45,7 @@ F www/c_interface.tcl f875864edf7974157d1c257ca08de854660882a5
 F www/changes.tcl 37f4906f0b03f2160d2b2e4ed3cedb0b91d253cb
 F www/index.tcl 001f8c8c4edbe20e25c508005a12f2f265f84c9c
 F www/sqlite.tcl 2a0056dd6d78839636176b770d9f37d12e66660e
-P 81bee278dc8304b12891b5319bcbf1de361b3659
-R 038d4d001d0c419b0ab6fccf5a518f57
+P 6b9056364e62cff017447ea979bb29dc78fb9f73
+R 16424dcd9ee13071fcab886f6e440991
 U drh
-Z 4f4a9e00724f32423f37a7d2a6efebff
+Z 98d8da8fcec9ae290876645d0b50c778
index cc8d405a5cc478b7b5398c520186a7a81226ea25..a31bea748ac7bce2be29b33196a3ff7ce8d55651 100644 (file)
@@ -1 +1 @@
-6b9056364e62cff017447ea979bb29dc78fb9f73
\ No newline at end of file
+52338f4ab5990fefc61f615cd65c3a724b365199
\ No newline at end of file
index 380ce94a0628bafa55ab203f9c70a50e3f4f0f62..d5e98435ceea22e1aea496dc7090dedd56788c84 100644 (file)
@@ -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);
index 6d8ed4222db6085ba5e619fa47b5f08d6eb2271a..321a5de2ef329c999201bb21bfba47437ba2cfa4 100644 (file)
@@ -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;
 }
 
 /*
index b5e36011d6dd8c1fe7d49683350f79738e20d9aa..b30e04a7a8810f0056ad4640d48bbe0e92d8bbf8 100644 (file)
@@ -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 *);
index 3ab5f59404607994b0e5e6a3f938d46041af4097..498c35f22f3d12d7510e2ec0eb22b62f4bcc8748 100644 (file)
@@ -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);
index 071e642c7db14ea299fb3568fa05442c6972d1e6..85f9af86dc1ab02dca2d2167012e406f0d142bc7 100644 (file)
@@ -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 ){
index 4deac6de0dc3f2261aaf9d3a82f56fdb1dd3c799..ec960e169f9a43d84b7bf6e28082f415b32e57cc 100644 (file)
@@ -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;
 }
index 26b48746ad724a4968fe2d1c44459c1e4e585b4d..164ed11e14ef9f1ce50723ed8c0f74d034539b58 100644 (file)
@@ -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.
index 08deeb275cde82fe0c30d55daf877e9d19cee570..5fa1917e4c09f7ce3ca6c4ea9a489661500dafcc 100644 (file)
@@ -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
index e261791cca0e03ec7d25d4ac2ef4712a7b50a666..1499cf6e272adb6d6d4149de448161bc9ff67556 100644 (file)
@@ -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;
   }
index a19846a91d088925c87ae85528a70c76c712a2cf..8bd2e5dd0a89359ceda059ccc3e979b91f254bd3 100644 (file)
@@ -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
index 2c302ba0858f7cdbc50cca84790cb4c3a38b66db..766773e0dcba11c692cf08f9b8d8de1c9195a08f 100644 (file)
@@ -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;
 
 }