]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Eliminate the use of callbacks during schema initialization. (CVS 1242)
authordrh <drh@noemail.net>
Sat, 14 Feb 2004 23:05:52 +0000 (23:05 +0000)
committerdrh <drh@noemail.net>
Sat, 14 Feb 2004 23:05:52 +0000 (23:05 +0000)
FossilOrigin-Name: af5c2be4aed1c50f69eb9634cf051a26263dcf51

manifest
manifest.uuid
src/build.c
src/main.c
src/sqliteInt.h
src/trigger.c

index 15ea0a3724a5c7c7490a7dc44b69a00c707073e1..0d4669e26fa2de6106f4cd3bc49436655b930824 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sproblems\swith\smalloc-failure\shandling.\s(CVS\s1241)
-D 2004-02-14T17:35:07
+C Eliminate\sthe\suse\sof\scallbacks\sduring\sschema\sinitialization.\s(CVS\s1242)
+D 2004-02-14T23:05:53
 F Makefile.in cfd75c46b335881999333a9e4b982fa8491f200b
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -26,7 +26,7 @@ F src/auth.c c59ad0dab501888f8b1fccc25e2f5965d2265116
 F src/btree.c 0a40efb01fa3a431a16d8604f603431d8c9cebfa
 F src/btree.h 41cb3ff6ebc3f6da2d0a074e39ff8c7a2287469f
 F src/btree_rb.c 32b2cb4285c0fbd53b89de021637b63d52257e54
-F src/build.c 94fdf4d8abe56f957a519d139b0e49a92cbfb242
+F src/build.c f8cef53c4e11a102a0d33000ba5f108a1fb48ac9
 F src/copy.c 9e47975ea96751c658bcf1a0c4f0bb7c6ee61e73
 F src/date.c c9d2bfd40b1c95f8f97d53a5eba981d7167c7b61
 F src/delete.c 0778fe05df0a1d62ac27fd1a3dba237c186ff4d1
@@ -36,7 +36,7 @@ F src/func.c cbc5edd10c82a5193b9ca0726873328be445e6c1
 F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
 F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
 F src/insert.c 01f66866f35c986eab4a57373ca689a3255ef2df
-F src/main.c 1e4647001f9015c00bb2285b6b155a09980f4d93
+F src/main.c e803d6cc6d57e85e12e61a04768f14ff644a4180
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
 F src/os.c f5fc4954725b2fcd852979f2746085fe8ca27710
 F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
@@ -49,7 +49,7 @@ F src/random.c 775913e0b7fbd6295d21f12a7bd35b46387c44b2
 F src/select.c 7cbd9cca5294399657da9e2d6c441add4610fb18
 F src/shell.c c3d3404fa82bb0808444fda9884d1bb572fd18b9
 F src/sqlite.h.in 64f016cd5ce190643a0f47760188fdf4e0b2227e
-F src/sqliteInt.h c45fbae6278407111d7a00aa9280ddc0f51344ad
+F src/sqliteInt.h 3b64ff750133c656badcedd7cf7e1e425e4aa693
 F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
 F src/tclsqlite.c b84dafe3a8532ff534c36e96bd38880e4b9cedf3
 F src/test1.c 56e9a156df3ad5e4e98df776776e963effc727f7
@@ -57,7 +57,7 @@ F src/test2.c 75819b0f2c63c6a0fd6995445881f2eb94036996
 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
 F src/test4.c dcbbbb382626fd466a7c46907f74db35fc8bad64
 F src/tokenize.c 8c95dcd2620b18dc0db1cdc97f9e111d11e55fe0
-F src/trigger.c ce83e017b407d046e909d05373d7f8ee70f9f7f9
+F src/trigger.c c647a442427fb8c1cd761eb03b1710c9d5675a8b
 F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
 F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
 F src/vacuum.c d9e80c2b36ee1f623dbf1bdf3cedad24a23f87ac
@@ -184,7 +184,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 9771ad1e811e02e10bb738550fbea447749083c5
-R 2dd38e1847aebff09cd4368ba627e231
+P 398bc294c839368e7fa75a97ba8cc8d1639f9436
+R 2c93489f2ccfbeec94078a6113e1dd06
 U drh
-Z c4bcf89beb16b0907aa99e04bfa67229
+Z 914d3c303ed4bd19601ee7fa1346d33f
index a6df30cb282d005a503c406235ad882bd076ea16..0af5d2c15f505a1a5c4cfac24b85024e2dbb09f9 100644 (file)
@@ -1 +1 @@
-398bc294c839368e7fa75a97ba8cc8d1639f9436
\ No newline at end of file
+af5c2be4aed1c50f69eb9634cf051a26263dcf51
\ No newline at end of file
index 7d4347e54e00f7e954852b5c7be1970d3dbdff91..5683a261d6e2f146c50cd5374244db04fb03e9bc 100644 (file)
@@ -23,7 +23,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.168 2004/02/14 16:31:03 drh Exp $
+** $Id: build.c,v 1.169 2004/02/14 23:05:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -38,7 +38,7 @@ void sqliteBeginParse(Parse *pParse, int explainFlag){
   sqlite *db = pParse->db;
   int i;
   pParse->explain = explainFlag;
-  if((db->flags & SQLITE_Initialized)==0 && pParse->initFlag==0 ){
+  if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
     int rc = sqliteInit(db, &pParse->zErrMsg);
     if( rc!=SQLITE_OK ){
       pParse->rc = rc;
@@ -471,7 +471,7 @@ void sqliteStartTable(
   pParse->sFirstToken = *pStart;
   zName = sqliteTableNameFromToken(pName);
   if( zName==0 ) return;
-  if( pParse->iDb==1 ) isTemp = 1;
+  if( db->init.iDb==1 ) isTemp = 1;
 #ifndef SQLITE_OMIT_AUTHORIZATION
   assert( (isTemp & 1)==isTemp );
   {
@@ -532,8 +532,8 @@ void sqliteStartTable(
   ** an existing temporary table, that is not an error.
   */
   pTable = sqliteFindTable(db, zName, 0);
-  iDb = isTemp ? 1 : pParse->iDb;
-  if( pTable!=0 && (pTable->iDb==iDb || !pParse->initFlag) ){
+  iDb = isTemp ? 1 : db->init.iDb;
+  if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
     sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
         " already exists", 0, 0);
     sqliteFree(zName);
@@ -541,7 +541,7 @@ void sqliteStartTable(
     return;
   }
   if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
-          (pIdx->iDb==0 || !pParse->initFlag) ){
+          (pIdx->iDb==0 || !db->init.busy) ){
     sqliteSetString(&pParse->zErrMsg, "there is already an index named ", 
        zName, (char*)0);
     sqliteFree(zName);
@@ -570,7 +570,7 @@ void sqliteStartTable(
   ** indices.  Hence, the record number for the table must be allocated
   ** now.
   */
-  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
+  if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
     sqliteBeginWriteOperation(pParse, 0, isTemp);
     if( !isTemp ){
       sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
@@ -927,8 +927,8 @@ static char *createTableStmt(Table *p){
 ** is added to the internal hash tables, assuming no errors have
 ** occurred.
 **
-** An entry for the table is made in the master table on disk,
-** unless this is a temporary table or initFlag==1.  When initFlag==1,
+** An entry for the table is made in the master table on disk, unless
+** this is a temporary table or db->init.busy==1.  When db->init.busy==1
 ** it means we are reading the sqlite_master table because we just
 ** connected to the database or because the sqlite_master table has
 ** recently changes, so the entry for this table already exists in
@@ -961,14 +961,14 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
     sqliteDeleteTable(0, pSelTab);
   }
 
-  /* If the initFlag is 1 it means we are reading the SQL off the
+  /* If the db->init.busy is 1 it means we are reading the SQL off the
   ** "sqlite_master" or "sqlite_temp_master" table on the disk.
   ** So do not write to the disk again.  Extract the root page number
-  ** for the table from the pParse->newTnum field.  (The page number
+  ** for the table from the db->init.newTnum field.  (The page number
   ** should have been put there by the sqliteOpenCb routine.)
   */
-  if( pParse->initFlag ){
-    p->tnum = pParse->newTnum;
+  if( db->init.busy ){
+    p->tnum = db->init.newTnum;
   }
 
   /* If not initializing, then create a record for the new table
@@ -978,7 +978,7 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
   ** If this is a TEMPORARY table, write the entry into the auxiliary
   ** file instead of into the main database file.
   */
-  if( !pParse->initFlag ){
+  if( !db->init.busy ){
     int n;
     Vdbe *v;
 
@@ -1001,9 +1001,9 @@ void sqliteEndTable(Parse *pParse, Token *pEnd, Select *pSelect){
       sqliteVdbeChangeP3(v, -1, "view", P3_STATIC);
     }
     sqliteVdbeAddOp(v, OP_String, 0, 0);
-    sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
+    sqliteVdbeChangeP3(v, -1, p->zName, 0);
     sqliteVdbeAddOp(v, OP_String, 0, 0);
-    sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
+    sqliteVdbeChangeP3(v, -1, p->zName, 0);
     sqliteVdbeAddOp(v, OP_Dup, 4, 0);
     sqliteVdbeAddOp(v, OP_String, 0, 0);
     if( pSelect ){
@@ -1089,7 +1089,7 @@ void sqliteCreateView(
   */
   p->pSelect = sqliteSelectDup(pSelect);
   sqliteSelectDelete(pSelect);
-  if( !pParse->initFlag ){
+  if( !pParse->db->init.busy ){
     sqliteViewGetColumnNames(pParse, p);
   }
 
@@ -1567,8 +1567,8 @@ void sqliteCreateIndex(
   sqlite *db = pParse->db;
 
   if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
-  if( pParse->initFlag 
-     && sqliteFixInit(&sFix, pParse, pParse->iDb, "index", pName)
+  if( db->init.busy 
+     && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
      && sqliteFixSrcList(&sFix, pTable)
   ){
     goto exit_create_index;
@@ -1592,7 +1592,7 @@ void sqliteCreateIndex(
     pParse->nErr++;
     goto exit_create_index;
   }
-  if( pTab->iDb>=2 && pParse->initFlag==0 ){
+  if( pTab->iDb>=2 && db->init.busy==0 ){
     sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
       " may not have indices added", (char*)0);
     pParse->nErr++;
@@ -1618,7 +1618,7 @@ void sqliteCreateIndex(
   ** dealing with a primary key or UNIQUE constraint.  We have to invent our
   ** own name.
   */
-  if( pName && !pParse->initFlag ){
+  if( pName && !db->init.busy ){
     Index *pISameName;    /* Another index with the same name */
     Table *pTSameName;    /* A table with same name as the index */
     zName = sqliteStrNDup(pName->z, pName->n);
@@ -1654,7 +1654,7 @@ void sqliteCreateIndex(
   {
     const char *zDb = db->aDb[pTab->iDb].zName;
 
-    assert( pTab->iDb==pParse->iDb || isTemp );
+    assert( pTab->iDb==db->init.iDb || isTemp );
     if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
       goto exit_create_index;
     }
@@ -1690,7 +1690,7 @@ void sqliteCreateIndex(
   pIndex->nColumn = pList->nId;
   pIndex->onError = onError;
   pIndex->autoIndex = pName==0;
-  pIndex->iDb = isTemp ? 1 : pParse->iDb;
+  pIndex->iDb = isTemp ? 1 : db->init.iDb;
 
   /* Scan the names of the columns of the table to be indexed and
   ** load the column indices into the Index structure.  Report an error
@@ -1743,20 +1743,20 @@ void sqliteCreateIndex(
     pOther->pNext = pIndex;
   }
 
-  /* If the initFlag is 1 it means we are reading the SQL off the
+  /* If the db->init.busy is 1 it means we are reading the SQL off the
   ** "sqlite_master" table on the disk.  So do not write to the disk
-  ** again.  Extract the table number from the pParse->newTnum field.
+  ** again.  Extract the table number from the db->init.newTnum field.
   */
-  if( pParse->initFlag && pTable!=0 ){
-    pIndex->tnum = pParse->newTnum;
+  if( db->init.busy && pTable!=0 ){
+    pIndex->tnum = db->init.newTnum;
   }
 
-  /* If the initFlag is 0 then create the index on disk.  This
+  /* If the db->init.busy is 0 then create the index on disk.  This
   ** involves writing the index into the master table and filling in the
   ** index with the current table contents.
   **
-  ** The initFlag is 0 when the user first enters a CREATE INDEX 
-  ** command.  The initFlag is 1 when a database is opened and 
+  ** The db->init.busy is 0 when the user first enters a CREATE INDEX 
+  ** command.  db->init.busy is 1 when a database is opened and 
   ** CREATE INDEX statements are read out of the master table.  In
   ** the latter case the index already exists on disk, which is why
   ** we don't want to recreate it.
@@ -1766,7 +1766,7 @@ void sqliteCreateIndex(
   ** has just been created, it contains no data and the index initialization
   ** step can be skipped.
   */
-  else if( pParse->initFlag==0 ){
+  else if( db->init.busy==0 ){
     int n;
     Vdbe *v;
     int lbl1, lbl2;
@@ -1785,7 +1785,7 @@ void sqliteCreateIndex(
     sqliteVdbeAddOp(v, OP_String, 0, 0);
     sqliteVdbeChangeP3(v, -1, pIndex->zName, strlen(pIndex->zName));
     sqliteVdbeAddOp(v, OP_String, 0, 0);
-    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
+    sqliteVdbeChangeP3(v, -1, pTab->zName, 0);
     addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, isTemp);
     sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, P3_POINTER);
     pIndex->tnum = 0;
@@ -1804,7 +1804,7 @@ void sqliteCreateIndex(
     if( pTable ){
       sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
       sqliteVdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
-      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
+      sqliteVdbeChangeP3(v, -1, pTab->zName, 0);
       lbl2 = sqliteVdbeMakeLabel(v);
       sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
       lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
index e0a86ca031825e66808348431cd8342337698047..9cc621d51e4fc9b0b2aa4b655819dd35910c862d 100644 (file)
@@ -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.153 2004/02/14 17:35:07 drh Exp $
+** $Id: main.c,v 1.154 2004/02/14 23:05:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -33,8 +33,9 @@ typedef struct {
 ** Fill the InitData structure with an error message that indicates
 ** that the database is corrupt.
 */
-static void corruptSchema(InitData *pData){
-  sqliteSetString(pData->pzErrMsg, "malformed database schema", (char*)0);
+static void corruptSchema(InitData *pData, const char *zExtra){
+  sqliteSetString(pData->pzErrMsg, "malformed database schema",
+     zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
 }
 
 /*
@@ -54,36 +55,39 @@ static void corruptSchema(InitData *pData){
 static
 int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
   InitData *pData = (InitData*)pInit;
-  Parse sParse;
   int nErr = 0;
 
   assert( argc==5 );
   if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
   if( argv[0]==0 ){
-    corruptSchema(pData);
+    corruptSchema(pData, 0);
     return 1;
   }
   switch( argv[0][0] ){
     case 'v':
     case 'i':
     case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
+      sqlite *db = pData->db;
       if( argv[2]==0 || argv[4]==0 ){
-        corruptSchema(pData);
+        corruptSchema(pData, 0);
         return 1;
       }
       if( argv[3] && argv[3][0] ){
         /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
-        ** But because sParse.initFlag is set to 1, no VDBE code is generated
+        ** But because db->init.busy is set to 1, no VDBE code is generated
         ** or executed.  All the parser does is build the internal data
         ** structures that describe the table, index, or view.
         */
-        memset(&sParse, 0, sizeof(sParse));
-        sParse.db = pData->db;
-        sParse.initFlag = 1;
-        sParse.iDb = atoi(argv[4]);
-        sParse.newTnum = atoi(argv[2]);
-        sParse.useCallback = 1;
-        sqliteRunParser(&sParse, argv[3], pData->pzErrMsg);
+        char *zErr;
+        assert( db->init.busy );
+        db->init.iDb = atoi(argv[4]);
+        assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
+        db->init.newTnum = atoi(argv[2]);
+        if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
+          corruptSchema(pData, zErr);
+          sqlite_freemem(zErr);
+        }
+        db->init.iDb = 0;
       }else{
         /* If the SQL column is blank it means this is an index that
         ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -95,8 +99,8 @@ int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
         Index *pIndex;
 
         iDb = atoi(argv[4]);
-        assert( iDb>=0 && iDb<pData->db->nDb );
-        pIndex = sqliteFindIndex(pData->db, argv[1], pData->db->aDb[iDb].zName);
+        assert( iDb>=0 && iDb<db->nDb );
+        pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);
         if( pIndex==0 || pIndex->tnum!=0 ){
           /* This can occur if there exists an index on a TEMP table which
           ** has the same name as another index on a permanent index.  Since
@@ -188,7 +192,6 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
   char *azArg[6];
   char zDbNum[30];
   int meta[SQLITE_N_BTREE_META];
-  Parse sParse;
   InitData initData;
 
   /*
@@ -245,6 +248,7 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
 
   /* Construct the schema tables: sqlite_master and sqlite_temp_master
   */
+  sqliteSafetyOff(db);
   azArg[0] = "table";
   azArg[1] = MASTER_NAME;
   azArg[2] = "2";
@@ -269,6 +273,7 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
       pTab->readOnly = 1;
     }
   }
+  sqliteSafetyOn(db);
 
   /* Create a cursor to hold the database open
   */
@@ -330,31 +335,28 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
 
   /* Read the schema information out of the schema tables
   */
-  memset(&sParse, 0, sizeof(sParse));
-  sParse.db = db;
-  sParse.xCallback = sqliteInitCallback;
-  sParse.pArg = (void*)&initData;
-  sParse.initFlag = 1;
-  sParse.useCallback = 1;
+  assert( db->init.busy );
+  sqliteSafetyOff(db);
   if( iDb==0 ){
-    sqliteRunParser(&sParse,
+    rc = sqlite_exec(db, 
         db->file_format>=2 ? init_script : older_init_script,
-        pzErrMsg);
+        sqliteInitCallback, &initData, 0);
   }else{
     char *zSql = 0;
     sqliteSetString(&zSql, 
        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
        db->aDb[iDb].zName, "\".sqlite_master", (char*)0);
-    sqliteRunParser(&sParse, zSql, pzErrMsg);
+    rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);
     sqliteFree(zSql);
   }
+  sqliteSafetyOn(db);
   sqliteBtreeCloseCursor(curMain);
   if( sqlite_malloc_failed ){
     sqliteSetString(pzErrMsg, "out of memory", (char*)0);
-    sParse.rc = SQLITE_NOMEM;
+    rc = SQLITE_NOMEM;
     sqliteResetInternalSchema(db, 0);
   }
-  if( sParse.rc==SQLITE_OK ){
+  if( rc==SQLITE_OK ){
     DbSetProperty(db, iDb, DB_SchemaLoaded);
     if( iDb==0 ){
       DbSetProperty(db, 1, DB_SchemaLoaded);
@@ -362,7 +364,7 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
   }else{
     sqliteResetInternalSchema(db, iDb);
   }
-  return sParse.rc;
+  return rc;
 }
 
 /*
@@ -381,8 +383,10 @@ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
 int sqliteInit(sqlite *db, char **pzErrMsg){
   int i, rc;
   
+  if( db->init.busy ) return SQLITE_OK;
   assert( (db->flags & SQLITE_Initialized)==0 );
   rc = SQLITE_OK;
+  db->init.busy = 1;
   for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
     if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
     assert( i!=1 );  /* Should have been initialized together with 0 */
@@ -391,6 +395,7 @@ int sqliteInit(sqlite *db, char **pzErrMsg){
       sqliteResetInternalSchema(db, i);
     }
   }
+  db->init.busy = 0;
   if( rc==SQLITE_OK ){
     db->flags |= SQLITE_Initialized;
     sqliteCommitInternalChanges(db);
@@ -669,25 +674,29 @@ int sqlite_compile(
 
   if( pzErrMsg ) *pzErrMsg = 0;
   if( sqliteSafetyOn(db) ) goto exec_misuse;
-  if( (db->flags & SQLITE_Initialized)==0 ){
-    int rc, cnt = 1;
-    while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
-       && db->xBusyCallback && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
-    if( rc!=SQLITE_OK ){
-      sqliteStrRealloc(pzErrMsg);
-      sqliteSafetyOff(db);
-      return rc;
+  if( !db->init.busy ){
+    if( (db->flags & SQLITE_Initialized)==0 ){
+      int rc, cnt = 1;
+      while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
+         && db->xBusyCallback
+         && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
+      if( rc!=SQLITE_OK ){
+        sqliteStrRealloc(pzErrMsg);
+        sqliteSafetyOff(db);
+        return rc;
+      }
+      if( pzErrMsg ){
+        sqliteFree(*pzErrMsg);
+        *pzErrMsg = 0;
+      }
     }
-    if( pzErrMsg ){
-      sqliteFree(*pzErrMsg);
-      *pzErrMsg = 0;
+    if( db->file_format<3 ){
+      sqliteSafetyOff(db);
+      sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
+      return SQLITE_ERROR;
     }
   }
-  if( db->file_format<3 ){
-    sqliteSafetyOff(db);
-    sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
-    return SQLITE_ERROR;
-  }
+  assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
   if( db->pVdbe==0 ){ db->nChange = 0; }
   memset(&sParse, 0, sizeof(sParse));
   sParse.db = db;
index 5ad74c29846a33d5cc5abcb2eeb9fa850536a7ba..30e74e3e23b74f40abfec9f905dfe4cfaa66c74e 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.211 2004/02/12 18:46:39 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.212 2004/02/14 23:05:53 drh Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -318,9 +318,10 @@ struct sqlite {
   u8 file_format;               /* What file format version is this database? */
   u8 safety_level;              /* How aggressive at synching data to disk */
   u8 want_to_close;             /* Close after all VDBEs are deallocated */
+  u8 temp_store;                /* 1=file, 2=memory, 0=compile-time default */
+  u8 onError;                   /* Default conflict algorithm */
   int next_cookie;              /* Next value of aDb[0].schema_cookie */
   int cache_size;               /* Number of pages to use in the cache */
-  int temp_store;               /* 1=file, 2=memory, 0=compile-time default */
   int nTable;                   /* Number of tables in the database */
   void *pBusyArg;               /* 1st Argument to the busy callback */
   int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
@@ -329,9 +330,13 @@ struct sqlite {
   Hash aFunc;                   /* All functions that can be in SQL exprs */
   int lastRowid;                /* ROWID of most recent insert */
   int priorNewRowid;            /* Last randomly generated ROWID */
-  int onError;                  /* Default conflict algorithm */
   int magic;                    /* Magic number for detect library misuse */
   int nChange;                  /* Number of rows changed */
+  struct sqliteInitInfo {       /* Information used during initialization */
+    int iDb;                       /* When back is being initialized */
+    int newTnum;                   /* Rootpage of table being initialized */
+    u8 busy;                       /* TRUE if currently initializing */
+  } init;
   struct Vdbe *pVdbe;           /* List of active virtual machines */
   void (*xTrace)(void*,const char*);     /* Trace function */
   void *pTraceArg;                       /* Argument to the trace function */
@@ -878,13 +883,10 @@ struct Parse {
   Vdbe *pVdbe;         /* An engine for executing database bytecode */
   u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
   u8 explain;          /* True if the EXPLAIN flag is found on the query */
-  u8 initFlag;         /* True if reparsing CREATE TABLEs */
   u8 nameClash;        /* A permanent table name clashes with temp table name */
   u8 useAgg;           /* If true, extract field values from the aggregator
                        ** while generating expressions.  Normally false */
-  u8 iDb;              /* Index of database whose schema is being parsed */
   u8 useCallback;      /* True if callbacks should be used to report results */
-  int newTnum;         /* Table number to use when reparsing CREATE TABLEs */
   int nErr;            /* Number of errors seen */
   int nTab;            /* Number of previously allocated VDBE cursors */
   int nMem;            /* Number of memory cells used so far */
index 82b679755a8a56ed929010db5870015497cd4db5..e727dcc0c294dc0ac26958af57d4776c00fbf5d3 100644 (file)
@@ -65,8 +65,8 @@ void sqliteBeginTrigger(
   */
   if( sqlite_malloc_failed ) goto trigger_cleanup;
   assert( pTableName->nSrc==1 );
-  if( pParse->initFlag 
-   && sqliteFixInit(&sFix, pParse, pParse->iDb, "trigger", pName)
+  if( db->init.busy
+   && sqliteFixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
    && sqliteFixSrcList(&sFix, pTableName)
   ){
     goto trigger_cleanup;
@@ -76,7 +76,7 @@ void sqliteBeginTrigger(
     goto trigger_cleanup;
   }
   iDb = isTemp ? 1 : tab->iDb;
-  if( iDb>=2 && !pParse->initFlag ){
+  if( iDb>=2 && !db->init.busy ){
     sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
        "database %s", db->aDb[tab->iDb].zName);
     goto trigger_cleanup;
@@ -181,7 +181,7 @@ void sqliteFinishTrigger(
   /* if we are not initializing, and this trigger is not on a TEMP table, 
   ** build the sqlite_master entry
   */
-  if( !pParse->initFlag ){
+  if( !db->init.busy ){
     static VdbeOp insertTrig[] = {
       { OP_NewRecno,   0, 0,  0          },
       { OP_String,     0, 0,  "trigger"  },