/* ** 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] = name of thing being created ** argv[1] = root page number for table or index. 0 for trigger or view. ** argv[2] = SQL text for the CREATE statement. ** */ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ InitData *pData = (InitData*)pInit; sqlite3 *db = pData->db; int iDb = pData->iDb; assert( argc==3 ); UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ corruptSchema(pData, argv[0], 0); return 1; } assert( iDb>=0 && iDb<db->nDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ corruptSchema(pData, argv[0], 0); }else if( sqlite3_strnicmp(argv[2],"create ",7)==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. */ int rc; u8 saved_iDb = db->init.iDb; sqlite3_stmt *pStmt; TESTONLY(int rcp); /* Return code from sqlite3_prepare() */ assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = sqlite3Atoi(argv[1]); db->init.orphanTrigger = 0; TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = saved_iDb; assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 ); if( SQLITE_OK!=rc ){ if( db->init.orphanTrigger ){ assert( iDb==1 ); }else{ pData->rc = rc; if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){ corruptSchema(pData, argv[0], sqlite3_errmsg(db)); } } } sqlite3_finalize(pStmt); }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed) { InitData *pData = (InitData*)pInit; sqlite3 *db = pData->db; int iDb = pData->iDb; assert( argc==3 ); UNUSED_PARAMETER2(NotUsed, argc); assert( sqlite3_mutex_held(db->mutex) ); DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ) { corruptSchema(pData, argv[0], 0); return 1; } assert( iDb>=0 && iDb<db->nDb ); if( argv==0 ) return 0; if( argv[1]==0 ) { corruptSchema(pData, argv[0], 0); } else if( argv[2] && argv[2][0] ) { int rc; sqlite3_stmt *pStmt; TESTONLY(int rcp); assert( db->init.busy ); db->init.iDb = iDb; db->init.newTnum = sqlite3Atoi(argv[1]); db->init.orphanTrigger = 0; TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0); rc = db->errCode; assert( (rc&0xFF)==(rcp&0xFF) ); db->init.iDb = 0; if( SQLITE_OK!=rc ) { if( db->init.orphanTrigger ) { assert( iDb==1 ); } else { pData->rc = rc; if( rc==SQLITE_NOMEM ) { db->mallocFailed = 1; } else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ) { corruptSchema(pData, argv[0], sqlite3_errmsg(db)); } } } sqlite3_finalize(pStmt); } else if( argv[0]==0 ) {
/* ** 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] = name of thing being created ** argv[1] = root page number for table or index. 0 for trigger or view. ** argv[2] = SQL text for the CREATE statement. ** */ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; sqlite3 *db = pData->db; int iDb = pData->iDb; pData->rc = SQLITE_OK; DbClearProperty(db, iDb, DB_Empty); if( sqlite3MallocFailed() ){ corruptSchema(pData, 0); return SQLITE_NOMEM; } assert( argc==3 ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ corruptSchema(pData, 0); return 1; } 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; assert( rc!=SQLITE_OK || zErr==0 ); if( SQLITE_OK!=rc ){ pData->rc = rc; if( rc==SQLITE_NOMEM ){ sqlite3FailedMalloc(); }else if( rc!=SQLITE_INTERRUPT ){ corruptSchema(pData, zErr); } sqlite3_free(zErr); return 1; } }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 0; }
/* ** This routine is called after the body of the procedure has been parsed ** in order to complete the process of building the procedure object. */ void sqliteFinishProc( Parse *pParse, /* Parser context */ Block *pBlock, /* The procedure body */ Token *pAll /* Token that describes the complete CREATE text */ ){ Object *no = 0; /* The object whose construction is finishing up */ sqlite *db = pParse->db; /* The database */ Vdbe *v = sqliteGetVdbe(pParse); if( pParse->nErr || pParse->pNewObject==0 ) goto objectfinish_cleanup; no = pParse->pNewObject; pParse->pNewObject = 0; sqliteCompileBlock(pParse, pBlock); sqliteVdbeAddOp(v, OP_Halt, 0, 0); /* save compiled body code, reset vdbe */ if( !pParse->explain ){ no->nOp = v->nOp; v->nOp = 0; no->aOp = v->aOp; v->aOp = 0; v->nOpAlloc = 0; } DbClearProperty(db, 0, DB_Locked); DbClearProperty(db, 1, DB_Locked); /* if we are not initializing build the sqlite_master entry */ if( !db->init.busy ){ static VdbeOpList insertObj[] = { { OP_NewRecno, 0, 0, 0 }, { OP_String, 0, 0, "procedure" }, { OP_String, 0, 0, 0 }, /* 2: object name */ { OP_String, 0, 0, 0 }, { OP_Integer, 0, 0, 0 }, { OP_String, 0, 0, 0 }, /* 5: SQL */ { OP_MakeRecord, 5, 0, 0 }, { OP_PutIntKey, 0, 0, 0 }, }; int addr; /* Make an entry in the sqlite_master table */ if( v==0 ) goto objectfinish_cleanup; sqliteBeginWriteOperation(pParse, 0, 0); sqliteOpenMasterTable(v, 0); addr = sqliteVdbeAddOpList(v, ArraySize(insertObj), insertObj); sqliteVdbeChangeP3(v, addr+2, no->name, 0); sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n); if( no->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteEndWriteOperation(pParse); } if( !pParse->explain ){ sqliteHashInsert(&db->aDb[no->iDb].objectHash, no->name, strlen(no->name)+1, no); no = 0; } objectfinish_cleanup: sqliteDeleteObject(no); sqliteDeleteObject(pParse->pNewObject); pParse->pNewObject = 0; }