Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -21,11 +21,11 @@ ** BEGIN TRANSACTION ** COMMIT ** 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 /* @@ -36,11 +36,11 @@ */ 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; pParse->nErr++; } @@ -469,11 +469,11 @@ int iDb; 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 ); { int code; char *zDb = isTemp ? "temp" : "main"; @@ -530,20 +530,20 @@ ** If we are re-reading the sqlite_master table because of a schema ** change and a new permanent table is found whose name collides with ** 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); pParse->nErr++; 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); pParse->nErr++; return; @@ -568,11 +568,11 @@ ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ** indices to be created and the table record must come before the ** 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); sqliteVdbeAddOp(v, OP_SetCookie, 0, 1); } @@ -925,12 +925,12 @@ ** ** The table structure that other action routines have been building ** 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 ** the sqlite_master table. We do not want to create it again. ** @@ -959,28 +959,28 @@ pSelTab->nCol = 0; pSelTab->aCol = 0; 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 ** in the SQLITE_MASTER table of the database. The record number ** for the new table entry should already be on the stack. ** ** 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; v = sqliteGetVdbe(pParse); if( v==0 ) return; @@ -999,13 +999,13 @@ sqliteVdbeChangeP3(v, -1, "table", P3_STATIC); }else{ 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 ){ char *z = createTableStmt(p); n = z ? strlen(z) : 0; @@ -1087,11 +1087,11 @@ ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite_exec() call returns. */ p->pSelect = sqliteSelectDup(pSelect); sqliteSelectDelete(pSelect); - if( !pParse->initFlag ){ + if( !pParse->db->init.busy ){ sqliteViewGetColumnNames(pParse, p); } /* Locate the end of the CREATE VIEW statement. Make sEnd point to ** the end. @@ -1565,12 +1565,12 @@ DbFixer sFix; /* For assigning database names to pTable */ int isTemp; /* True for a temporary index */ 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; } @@ -1590,11 +1590,11 @@ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not be indexed", (char*)0); 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++; goto exit_create_index; } @@ -1616,11 +1616,11 @@ ** ** If pName==0 it means that we are ** 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); if( zName==0 ) goto exit_create_index; if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){ @@ -1652,11 +1652,11 @@ */ #ifndef SQLITE_OMIT_AUTHORIZATION { 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; } i = SQLITE_CREATE_INDEX; if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX; @@ -1688,11 +1688,11 @@ strcpy(pIndex->zName, zName); pIndex->pTable = pTab; 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 ** if any column is not found. */ @@ -1741,34 +1741,34 @@ } pIndex->pNext = pOther->pNext; 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. ** ** If pTable==0 it means this index is generated as a primary key ** or UNIQUE constraint of a CREATE TABLE statement. Since the table ** 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; int i; int addr; @@ -1783,11 +1783,11 @@ sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeChangeP3(v, -1, "index", P3_STATIC); 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; if( pTable ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); @@ -1802,11 +1802,11 @@ sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); 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); for(i=0; inColumn; i++){ int iCol = pIndex->aiColumn[i]; Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -12,11 +12,11 @@ ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** 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" #include @@ -31,12 +31,13 @@ /* ** 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); } /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. @@ -52,40 +53,43 @@ ** */ 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.iDbnDb ); + 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 ** constraint for a CREATE TABLE. The index should have already ** been created when we processed the CREATE TABLE. All we have @@ -93,12 +97,12 @@ */ int iDb; Index *pIndex; iDb = atoi(argv[4]); - assert( iDb>=0 && iDbdb->nDb ); - pIndex = sqliteFindIndex(pData->db, argv[1], pData->db->aDb[iDb].zName); + assert( iDb>=0 && iDbnDb ); + 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 ** the permanent table is hidden by the TEMP table, we can also ** safely ignore the index on the permanent table. @@ -186,11 +190,10 @@ int size; Table *pTab; char *azArg[6]; char zDbNum[30]; int meta[SQLITE_N_BTREE_META]; - Parse sParse; InitData initData; /* ** The master database table has a structure like this */ @@ -243,10 +246,11 @@ assert( iDb>=0 && iDb!=1 && iDbnDb ); /* Construct the schema tables: sqlite_master and sqlite_temp_master */ + sqliteSafetyOff(db); azArg[0] = "table"; azArg[1] = MASTER_NAME; azArg[2] = "2"; azArg[3] = master_schema; sprintf(zDbNum, "%d", iDb); @@ -267,10 +271,11 @@ pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp"); if( pTab ){ pTab->readOnly = 1; } } + sqliteSafetyOn(db); /* Create a cursor to hold the database open */ if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain); @@ -328,43 +333,40 @@ sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size); sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]); /* 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); } }else{ sqliteResetInternalSchema(db, iDb); } - return sParse.rc; + return rc; } /* ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files @@ -379,20 +381,23 @@ ** is made the first time the database is accessed. */ 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 && inDb; i++){ if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue; assert( i!=1 ); /* Should have been initialized together with 0 */ rc = sqliteInitOne(db, i, pzErrMsg); if( rc ){ sqliteResetInternalSchema(db, i); } } + db->init.busy = 0; if( rc==SQLITE_OK ){ db->flags |= SQLITE_Initialized; sqliteCommitInternalChanges(db); } @@ -667,29 +672,33 @@ ){ Parse sParse; 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( 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->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( 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; sParse.useCallback = 0; if( db->xTrace ) db->xTrace(db->pTraceArg, zSql); Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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" #include "hash.h" #include "vdbe.h" @@ -316,24 +316,29 @@ Db aDbStatic[2]; /* Static space for the 2 default backends */ int flags; /* Miscellanous flags. See below */ 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 */ void *pCommitArg; /* Argument to xCommitCallback() */ int (*xCommitCallback)(void*);/* Invoked at every commit. */ 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 */ #ifndef SQLITE_OMIT_AUTHORIZATION int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); @@ -876,17 +881,14 @@ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ 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 */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ Index: src/trigger.c ================================================================== --- src/trigger.c +++ src/trigger.c @@ -63,22 +63,22 @@ ** 4. That we are not trying to create an INSTEAD OF trigger on a table. ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view. */ 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; } tab = sqliteSrcListLookup(pParse, pTableName); if( !tab ){ 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; } @@ -179,11 +179,11 @@ } /* 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" }, { OP_String, 0, 0, 0 }, /* 2: trigger name */ { OP_String, 0, 0, 0 }, /* 3: table name */