void sqliteDropProc(Parse *pParse, Token *pName){ Object *pObj; char *zName; Vdbe *v = sqliteGetVdbe(pParse); sqlite *db = pParse->db; zName = sqliteStrNDup(pName->z, pName->n); sqliteDequote(zName); pObj = sqliteHashFind(&(db->aDb[0].objectHash), zName, pName->n+1); if( !pParse->explain && !pObj ){ sqliteErrorMsg(pParse, "no such object: %T", pName); goto dropobject_cleanup; } /* Generate code to destroy the database record of the trigger. */ if( v ){ int base; static VdbeOpList dropObject[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String, 0, 0, 0}, /* 1 */ { OP_Column, 0, 1, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_String, 0, 0, "procedure"}, { OP_Column, 0, 0, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqliteBeginWriteOperation(pParse, 0, 0); sqliteOpenMasterTable(v, 0); base = sqliteVdbeAddOpList(v, ArraySize(dropObject), dropObject); sqliteVdbeChangeP3(v, base+1, zName, 0); if( pObj && pObj->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteEndWriteOperation(pParse); } /* * If this is not an "explain", then delete the trigger structure. */ if( !pParse->explain ){ sqliteHashInsert(&(db->aDb[pObj->iDb].objectHash), zName, pName->n+1, 0); sqliteDeleteObject(pObj); } dropobject_cleanup: sqliteFree(zName); }
/* ** 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; }
/* ** Drop a trigger given a pointer to that trigger. If nested is false, ** then also generate code to remove the trigger from the SQLITE_MASTER ** table. */ void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ Table *pTable; Vdbe *v; sqlite *db = pParse->db; assert( pTrigger->iDb<db->nDb ); if( pTrigger->iDb>=2 ){ sqliteErrorMsg(pParse, "triggers may not be removed from " "auxiliary database %s", db->aDb[pTrigger->iDb].zName); return; } pTable = sqliteFindTable(db, pTrigger->table,db->aDb[pTrigger->iTabDb].zName); assert(pTable); assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[pTrigger->iDb].zName; const char *zTab = SCHEMA_TABLE(pTrigger->iDb); if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ return; } } #endif /* Generate code to destroy the database record of the trigger. */ if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){ int base; static VdbeOpList dropTrigger[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String, 0, 0, 0}, /* 1 */ { OP_Column, 0, 1, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_String, 0, 0, "trigger"}, { OP_Column, 0, 0, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(1), 0}, /* 8 */ }; sqliteBeginWriteOperation(pParse, 0, 0); sqliteOpenMasterTable(v, pTrigger->iDb); base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqliteVdbeChangeP3(v, base+1, pTrigger->name, 0); if( pTrigger->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteEndWriteOperation(pParse); } /* * If this is not an "explain", then delete the trigger structure. */ if( !pParse->explain ){ const char *zName = pTrigger->name; int nName = strlen(zName); if( pTable->pTrigger == pTrigger ){ pTable->pTrigger = pTrigger->pNext; }else{ Trigger *cc = pTable->pTrigger; while( cc ){ if( cc->pNext == pTrigger ){ cc->pNext = cc->pNext->pNext; break; } cc = cc->pNext; } assert(cc); } sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0); sqliteDeleteTrigger(pTrigger); } }
/* ** This routine is called after all of the trigger actions have been parsed ** in order to complete the process of building the trigger. */ void sqliteFinishTrigger( Parse *pParse, /* Parser context */ TriggerStep *pStepList, /* The triggered program */ Token *pAll /* Token that describes the complete CREATE TRIGGER */ ){ Trigger *nt = 0; /* The trigger whose construction is finishing up */ sqlite *db = pParse->db; /* The database */ DbFixer sFix; if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup; nt = pParse->pNewTrigger; pParse->pNewTrigger = 0; nt->step_list = pStepList; while( pStepList ){ pStepList->pTrig = nt; pStepList = pStepList->pNext; } if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) && sqliteFixTriggerStep(&sFix, nt->step_list) ){ goto triggerfinish_cleanup; } /* if we are not initializing, and this trigger is not on a TEMP table, ** build the sqlite_master entry */ if( !db->init.busy ){ static VdbeOpList 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 */ { OP_Integer, 0, 0, 0 }, { OP_String, 0, 0, 0 }, /* 5: SQL */ { OP_MakeRecord, 5, 0, 0 }, { OP_PutIntKey, 0, 0, 0 }, }; int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqliteGetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqliteBeginWriteOperation(pParse, 0, 0); sqliteOpenMasterTable(v, nt->iDb); addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqliteVdbeChangeP3(v, addr+2, nt->name, 0); sqliteVdbeChangeP3(v, addr+3, nt->table, 0); sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n); if( nt->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteEndWriteOperation(pParse); } if( !pParse->explain ){ Table *pTab; sqliteHashInsert(&db->aDb[nt->iDb].trigHash, nt->name, strlen(nt->name)+1, nt); pTab = sqliteLocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName); assert( pTab!=0 ); nt->pNext = pTab->pTrigger; pTab->pTrigger = nt; nt = 0; } triggerfinish_cleanup: sqliteDeleteTrigger(nt); sqliteDeleteTrigger(pParse->pNewTrigger); pParse->pNewTrigger = 0; sqliteDeleteTriggerStep(pStepList); }