diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 124 | ||||
-rw-r--r-- | src/main.c | 150 | ||||
-rw-r--r-- | src/sqliteInt.h | 13 | ||||
-rw-r--r-- | src/tokenize.c | 8 | ||||
-rw-r--r-- | src/vdbe.c | 54 |
5 files changed, 167 insertions, 182 deletions
diff --git a/src/build.c b/src/build.c index 7f27985f2..09427a9c3 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.240 2004/07/22 01:19:35 drh Exp $ +** $Id: build.c,v 1.241 2004/07/24 03:30:48 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -231,8 +231,8 @@ void sqlite3UnlinkAndDeleteIndex(sqlite *db, Index *pIndex){ /* ** Erase all schema information from the in-memory hash tables of -** a sigle database. This routine is called to reclaim memory -** before the closes. It is also called during a rollback +** a single database. This routine is called to reclaim memory +** before the database closes. It is also called during a rollback ** if there were schema changes during the transaction or if a ** schema-cookie mismatch occurs. ** @@ -1169,14 +1169,16 @@ void sqlite3ChangeCookie(sqlite *db, Vdbe *v, int iDb){ ** Measure the number of characters needed to output the given ** identifier. The number returned includes any quotes used ** but does not include the null terminator. +** +** The estimate is conservative. It might be larger that what is +** really needed. */ static int identLength(const char *z){ int n; - int needQuote = 0; for(n=0; *z; n++, z++){ - if( *z=='\'' ){ n++; needQuote=1; } + if( *z=='"' ){ n++; } } - return n + needQuote*2; + return n + 2; } /* @@ -1191,12 +1193,12 @@ static void identPut(char *z, int *pIdx, char *zIdent){ } needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID; - if( needQuote ) z[i++] = '\''; + if( needQuote ) z[i++] = '"'; for(j=0; zIdent[j]; j++){ z[i++] = zIdent[j]; - if( zIdent[j]=='\'' ) z[i++] = '\''; + if( zIdent[j]=='"' ) z[i++] = '"'; } - if( needQuote ) z[i++] = '\''; + if( needQuote ) z[i++] = '"'; z[i] = 0; *pIdx = i; } @@ -1209,16 +1211,18 @@ static void identPut(char *z, int *pIdx, char *zIdent){ static char *createTableStmt(Table *p){ int i, k, n; char *zStmt; - char *zSep, *zSep2, *zEnd; + char *zSep, *zSep2, *zEnd, *z; + Column *pCol; n = 0; - for(i=0; i<p->nCol; i++){ - n += identLength(p->aCol[i].zName); - if( p->aCol[i].zType ){ - n += (strlen(p->aCol[i].zType) + 1); + for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){ + n += identLength(pCol->zName); + z = pCol->zType; + if( z ){ + n += (strlen(z) + 1); } } n += identLength(p->zName); - if( n<40 ){ + if( n<50 ){ zSep = ""; zSep2 = ","; zEnd = ")"; @@ -1234,15 +1238,15 @@ static char *createTableStmt(Table *p){ k = strlen(zStmt); identPut(zStmt, &k, p->zName); zStmt[k++] = '('; - for(i=0; i<p->nCol; i++){ + for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){ strcpy(&zStmt[k], zSep); k += strlen(&zStmt[k]); zSep = zSep2; - identPut(zStmt, &k, p->aCol[i].zName); - if( p->aCol[i].zType ){ + identPut(zStmt, &k, pCol->zName); + if( (z = pCol->zType)!=0 ){ zStmt[k++] = ' '; - strcpy(&zStmt[k], p->aCol[i].zType); - k += strlen(p->aCol[i].zType); + strcpy(&zStmt[k], z); + k += strlen(z); } } strcpy(&zStmt[k], zEnd); @@ -1305,12 +1309,11 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ if( p->pSelect==0 ){ /* A regular table */ - sqlite3VdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER); + sqlite3VdbeAddOp(v, OP_CreateTable, p->iDb, 0); }else{ /* A view */ sqlite3VdbeAddOp(v, OP_Integer, 0, 0); } - p->tnum = 0; sqlite3VdbeAddOp(v, OP_Close, 0, 0); @@ -1371,13 +1374,15 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); sqlite3ChangeCookie(db, v, p->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); + sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0, + sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); sqlite3EndWriteOperation(pParse); } /* Add the table to the in-memory representation of the database. */ - if( pParse->explain==0 && pParse->nErr==0 ){ + if( db->init.busy && pParse->nErr==0 ){ Table *pOld; FKey *pFKey; pOld = sqlite3HashInsert(&db->aDb[p->iDb].tblHash, @@ -1565,26 +1570,6 @@ static void sqliteViewResetAll(sqlite *db, int idx){ DbClearProperty(db, idx, DB_UnresetViews); } -#if 0 -/* -** Given a token, look up a table with that name. If not found, leave -** an error for the parser to find and return NULL. -*/ -Table *sqlite3TableFromToken(Parse *pParse, Token *pTok){ - char *zName; - Table *pTab; - zName = sqlite3NameFromToken(pTok); - if( zName==0 ) return 0; - pTab = sqlite3FindTable(pParse->db, zName, 0); - sqliteFree(zName); - if( pTab==0 ){ - sqlite3ErrorMsg(pParse, "no such table: %T", pTok); - pParse->checkSchema = 1; - } - return pTab; -} -#endif - /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. @@ -2099,7 +2084,7 @@ void sqlite3CreateIndex( /* Link the new Index structure to its table and to the other ** in-memory database structures. */ - if( !pParse->explain ){ + if( db->init.busy ){ Index *p; p = sqlite3HashInsert(&db->aDb[pIndex->iDb].idxHash, pIndex->zName, strlen(pIndex->zName)+1, pIndex); @@ -2108,14 +2093,9 @@ void sqlite3CreateIndex( goto exit_create_index; } db->flags |= SQLITE_InternChanges; - } - - /* 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 db->init.newTnum field. - */ - if( db->init.busy && pTblName!=0 ){ - pIndex->tnum = db->init.newTnum; + if( pTblName!=0 ){ + pIndex->tnum = db->init.newTnum; + } } /* If the db->init.busy is 0 then create the index on disk. This @@ -2148,8 +2128,7 @@ void sqlite3CreateIndex( sqlite3VdbeOp3(v, OP_String8, 0, 0, "index", P3_STATIC); sqlite3VdbeOp3(v, OP_String8, 0, 0, pIndex->zName, 0); sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); - sqlite3VdbeOp3(v, OP_CreateIndex, 0, iDb,(char*)&pIndex->tnum,P3_POINTER); - pIndex->tnum = 0; + sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0); if( pTblName ){ sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); @@ -2185,11 +2164,11 @@ void sqlite3CreateIndex( sqlite3VdbeResolveLabel(v, lbl2); sqlite3VdbeAddOp(v, OP_Close, 2, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); - } - if( pTblName!=0 ){ sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); + sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, + sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC); } } @@ -2198,19 +2177,21 @@ void sqlite3CreateIndex( ** OE_Ignore. This is necessary for the correct operation of UPDATE ** and INSERT. */ - if( onError!=OE_Replace || pTab->pIndex==0 - || pTab->pIndex->onError==OE_Replace){ - pIndex->pNext = pTab->pIndex; - pTab->pIndex = pIndex; - }else{ - Index *pOther = pTab->pIndex; - while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ - pOther = pOther->pNext; + if( db->init.busy || pTblName==0 ){ + if( onError!=OE_Replace || pTab->pIndex==0 + || pTab->pIndex->onError==OE_Replace){ + pIndex->pNext = pTab->pIndex; + pTab->pIndex = pIndex; + }else{ + Index *pOther = pTab->pIndex; + while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ + pOther = pOther->pNext; + } + pIndex->pNext = pOther->pNext; + pOther->pNext = pIndex; } - pIndex->pNext = pOther->pNext; - pOther->pNext = pIndex; + pIndex = 0; } - pIndex = 0; /* Clean up before exiting */ exit_create_index: @@ -2244,13 +2225,6 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } -/* - if( pIndex->iDb>1 ){ - sqlite3ErrorMsg(pParse, "cannot alter schema of attached " - "databases", 0); - goto exit_drop_index; - } -*/ #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; @@ -2272,7 +2246,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){ if( v ){ static VdbeOpList dropIndex[] = { { OP_Rewind, 0, ADDR(9), 0}, - { OP_String8, 0, 0, 0}, /* 1 */ + { OP_String8, 0, 0, 0}, /* 1 */ { OP_MemStore, 1, 1, 0}, { OP_MemLoad, 1, 0, 0}, /* 3 */ { OP_Column, 0, 1, 0}, diff --git a/src/main.c b/src/main.c index 24a4c19c4..f6cce31c6 100644 --- a/src/main.c +++ b/src/main.c @@ -14,22 +14,13 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.246 2004/07/22 01:19:35 drh Exp $ +** $Id: main.c,v 1.247 2004/07/24 03:30:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* -** A pointer to this structure is used to communicate information -** from sqlite3Init into the sqlite3InitCallback. -*/ -typedef struct { - sqlite *db; /* The database being initialized */ - char **pzErrMsg; /* Error message stored here */ -} InitData; - -/* ** The following constant value is used by the SQLITE_BIGENDIAN and ** SQLITE_LITTLEENDIAN macros. */ @@ -49,89 +40,69 @@ static void corruptSchema(InitData *pData, const char *zExtra){ /* ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. +** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** ** Each callback contains the following information: ** -** argv[0] = "table" or "index" or "view" or "trigger" -** argv[1] = name of thing being created -** argv[2] = root page number for table or index. NULL for trigger or view. -** argv[3] = SQL text for the CREATE statement. -** argv[4] = "1" for temporary files, "0" for main database, "2" or more +** argv[0] = name of thing being created +** argv[1] = root page number for table or index. NULL for trigger or view. +** argv[2] = SQL text for the CREATE statement. +** argv[3] = "1" for temporary files, "0" for main database, "2" or more ** for auxiliary database files. ** */ -static int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; - int nErr = 0; + sqlite *db = pData->db; + int iDb; - assert( argc==5 ); + assert( argc==4 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ - if( argv[0]==0 ){ + if( argv[1]==0 || argv[3]==0 ){ 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, 0); - return 1; - } - if( argv[3] && argv[3][0] ){ - /* Call the parser to process a CREATE TABLE, INDEX or VIEW. - ** 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. - */ - char *zErr; - int rc; - 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]); - rc = sqlite3_exec(db, argv[3], 0, 0, &zErr); - db->init.iDb = 0; - if( SQLITE_OK!=rc ){ - corruptSchema(pData, zErr); - sqlite3_free(zErr); - return rc; - } - }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 - ** to do here is record the root page number for that index. - */ - int iDb; - Index *pIndex; - - iDb = atoi(argv[4]); - assert( iDb>=0 && iDb<db->nDb ); - pIndex = sqlite3FindIndex(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. - */ - /* Do Nothing */; - }else{ - pIndex->tnum = atoi(argv[2]); - } - } + iDb = atoi(argv[3]); + assert( iDb>=0 && iDb<db->nDb ); + if( argv[2] && argv[2][0] ){ + /* Call the parser to process a CREATE TABLE, INDEX or VIEW. + ** 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. + */ + char *zErr; + int rc; + assert( db->init.busy ); + db->init.iDb = iDb; + db->init.newTnum = atoi(argv[1]); + rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); + db->init.iDb = 0; + if( SQLITE_OK!=rc ){ + corruptSchema(pData, zErr); + sqlite3_free(zErr); + return rc; } - break; - default: { - /* This can not happen! */ - nErr = 1; - assert( nErr==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 + ** to do here is record the root page number for that index. + */ + Index *pIndex; + pIndex = sqlite3FindIndex(db, argv[0], 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. + */ + /* Do Nothing */; + }else{ + pIndex->tnum = atoi(argv[1]); } } - return nErr; + return 0; } /* @@ -147,7 +118,7 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ BtCursor *curMain; int size; Table *pTab; - char const *azArg[6]; + char const *azArg[5]; char zDbNum[30]; int meta[10]; InitData initData; @@ -192,16 +163,15 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ /* Construct the schema tables. */ sqlite3SafetyOff(db); - azArg[0] = "table"; - azArg[1] = zMasterName; - azArg[2] = "1"; - azArg[3] = zMasterSchema; + azArg[0] = zMasterName; + azArg[1] = "1"; + azArg[2] = zMasterSchema; sprintf(zDbNum, "%d", iDb); - azArg[4] = zDbNum; - azArg[5] = 0; + azArg[3] = zDbNum; + azArg[4] = 0; initData.db = db; initData.pzErrMsg = pzErrMsg; - rc = sqlite3InitCallback(&initData, 5, (char **)azArg, 0); + rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0); if( rc!=SQLITE_OK ){ sqlite3SafetyOn(db); return rc; @@ -304,14 +274,14 @@ static int sqlite3InitOne(sqlite *db, int iDb, char **pzErrMsg){ /* For an empty database, there is nothing to read */ rc = SQLITE_OK; }else{ - char *zSql = 0; + char *zSql; + zSql = sqlite3MPrintf( + "SELECT name, rootpage, sql, %s FROM '%q'.%s", + zDbNum, db->aDb[iDb].zName, zMasterName); sqlite3SafetyOff(db); - sqlite3SetString(&zSql, - "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", - db->aDb[iDb].zName, "\".", zMasterName, (char*)0); rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); - sqliteFree(zSql); sqlite3SafetyOn(db); + sqliteFree(zSql); sqlite3BtreeCloseCursor(curMain); } if( sqlite3_malloc_failed ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d6cde4e5e..cdab05c9a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.308 2004/07/22 15:02:25 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.309 2004/07/24 03:30:48 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1160,6 +1160,16 @@ struct DbFixer { }; /* +** A pointer to this structure is used to communicate information +** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback. +*/ +typedef struct { + sqlite *db; /* The database being initialized */ + char **pzErrMsg; /* Error message stored here */ +} InitData; + + +/* * This global flag is set for performance testing of triggers. When it is set * SQLite will perform the overhead of building new and old trigger references * even when no triggers exist @@ -1210,6 +1220,7 @@ void sqlite3ExprDelete(Expr*); ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*); void sqlite3ExprListDelete(ExprList*); int sqlite3Init(sqlite*, char**); +int sqlite3InitCallback(void*, int, char**, char**); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); void sqlite3ResetInternalSchema(sqlite*, int); void sqlite3BeginParse(Parse*,int); diff --git a/src/tokenize.c b/src/tokenize.c index 8600cc6fd..dde809146 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.78 2004/06/18 06:02:35 danielk1977 Exp $ +** $Id: tokenize.c,v 1.79 2004/07/24 03:30:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -431,6 +431,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); return 1; } +#ifndef NDEBUG + if( sqlite3OsFileExists("vdbe_sqltrace") ){ + printf("SQL To Compiler: [%s]\n", zSql); + } +#endif pParse->sLastToken.dyn = 0; pParse->zTail = zSql; while( sqlite3_malloc_failed==0 && zSql[i]!=0 ){ @@ -714,4 +719,3 @@ int sqlite3_complete16(const void *zSql){ sqlite3ValueFree(pVal); return rc; } - diff --git a/src/vdbe.c b/src/vdbe.c index beeae2d7c..12e0978b3 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.403 2004/07/21 02:53:30 drh Exp $ +** $Id: vdbe.c,v 1.404 2004/07/24 03:30:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -3670,24 +3670,19 @@ case OP_Clear: { break; } -/* Opcode: CreateTable * P2 P3 +/* Opcode: CreateTable P1 * * ** ** Allocate a new table in the main database file if P2==0 or in the ** auxiliary database file if P2==1. Push the page number ** for the root page of the new table onto the stack. ** -** The root page number is also written to a memory location that P3 -** points to. This is the mechanism is used to write the root page -** number into the parser's internal data structures that describe the -** new table. -** ** The difference between a table and an index is this: A table must ** have a 4-byte integer key and can have arbitrary data. An index ** has an arbitrary key but no data. ** ** See also: CreateIndex */ -/* Opcode: CreateIndex * P2 P3 +/* Opcode: CreateIndex P1 * * ** ** Allocate a new index in the main database file if P2==0 or in the ** auxiliary database file if P2==1. Push the page number of the @@ -3699,28 +3694,59 @@ case OP_CreateIndex: case OP_CreateTable: { int pgno; int flags; - assert( pOp->p3!=0 && pOp->p3type==P3_POINTER ); - assert( pOp->p2>=0 && pOp->p2<db->nDb ); - assert( db->aDb[pOp->p2].pBt!=0 ); + Db *pDb; + assert( pOp->p1>=0 && pOp->p1<db->nDb ); + pDb = &db->aDb[pOp->p1]; + assert( pDb->pBt!=0 ); if( pOp->opcode==OP_CreateTable ){ /* flags = BTREE_INTKEY; */ flags = BTREE_LEAFDATA|BTREE_INTKEY; }else{ flags = BTREE_ZERODATA; } - rc = sqlite3BtreeCreateTable(db->aDb[pOp->p2].pBt, &pgno, flags); + rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags); pTos++; if( rc==SQLITE_OK ){ pTos->i = pgno; pTos->flags = MEM_Int; - *(u32*)pOp->p3 = pgno; - pOp->p3 = 0; }else{ pTos->flags = MEM_Null; } break; } +/* Opcode: ParseSchema P1 * P3 +** +** Read and parse all entries from the SQLITE_MASTER table of database P1 +** that match the WHERE clause P3. +** +** This opcode invokes the parser to create a new virtual machine, +** then runs the new virtual machine. It is thus a reentrant opcode. +*/ +case OP_ParseSchema: { + char *zSql; + int iDb = pOp->p1; + const char *zMaster; + InitData initData; + + assert( iDb>=0 && iDb<db->nDb ); + zMaster = iDb==1 ? TEMP_MASTER_NAME : MASTER_NAME; + initData.db = db; + initData.pzErrMsg = &p->zErrMsg; + zSql = sqlite3MPrintf( + "SELECT name, rootpage, sql, %d FROM '%q'.%s WHERE %s", + pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3); + sqlite3SafetyOff(db); + assert( db->init.busy==0 ); + db->init.busy = 1; + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + db->init.busy = 0; + sqlite3SafetyOn(db); + sqliteFree(zSql); + break; +} + + /* Opcode: IntegrityCk * P2 * ** ** Do an analysis of the currently open database. Push onto the |