ds@1952: /* ds@1952: ** ds@1952: ** The author disclaims copyright to this source code. In place of ds@1952: ** a legal notice, here is a blessing: ds@1952: ** ds@1952: ** May you do good and not evil. ds@1952: ** May you find forgiveness for yourself and forgive others. ds@1952: ** May you share freely, never taking more than you give. ds@1952: ** ds@1952: ************************************************************************* ds@1952: * ds@1952: */ ds@1952: #include "sqliteInt.h" ds@1952: ds@1952: #ifndef SQLITE_OMIT_TRIGGER ds@1952: /* ds@1952: ** Delete a linked list of TriggerStep structures. ds@1952: */ ds@1952: void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){ ds@1952: while( pTriggerStep ){ ds@1952: TriggerStep * pTmp = pTriggerStep; ds@1952: pTriggerStep = pTriggerStep->pNext; ds@1952: ds@1952: if( pTmp->target.dyn ) sqlite3_free((char*)pTmp->target.z); ds@1952: sqlite3ExprDelete(pTmp->pWhere); ds@1952: sqlite3ExprListDelete(pTmp->pExprList); ds@1952: sqlite3SelectDelete(pTmp->pSelect); ds@1952: sqlite3IdListDelete(pTmp->pIdList); ds@1952: ds@1952: sqlite3_free(pTmp); ds@1952: } ds@1952: } ds@1952: ds@1952: /* ds@1952: ** This is called by the parser when it sees a CREATE TRIGGER statement ds@1952: ** up to the point of the BEGIN before the trigger actions. A Trigger ds@1952: ** structure is generated based on the information available and stored ds@1952: ** in pParse->pNewTrigger. After the trigger actions have been parsed, the ds@1952: ** sqlite3FinishTrigger() function is called to complete the trigger ds@1952: ** construction process. ds@1952: */ ds@1952: void sqlite3BeginTrigger( ds@1952: Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ ds@1952: Token *pName1, /* The name of the trigger */ ds@1952: Token *pName2, /* The name of the trigger */ ds@1952: int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ ds@1952: int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ ds@1952: IdList *pColumns, /* column list if this is an UPDATE OF trigger */ ds@1952: SrcList *pTableName,/* The name of the table/view the trigger applies to */ ds@1952: Expr *pWhen, /* WHEN clause */ ds@1952: int isTemp, /* True if the TEMPORARY keyword is present */ ds@1952: int noErr /* Suppress errors if the trigger already exists */ ds@1952: ){ ds@1952: Trigger *pTrigger = 0; ds@1952: Table *pTab; ds@1952: char *zName = 0; /* Name of the trigger */ ds@1952: sqlite3 *db = pParse->db; ds@1952: int iDb; /* The database to store the trigger in */ ds@1952: Token *pName; /* The unqualified db name */ ds@1952: DbFixer sFix; ds@1952: int iTabDb; ds@1952: ds@1952: assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ ds@1952: assert( pName2!=0 ); ds@1952: if( isTemp ){ ds@1952: /* If TEMP was specified, then the trigger name may not be qualified. */ ds@1952: if( pName2->n>0 ){ ds@1952: sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: iDb = 1; ds@1952: pName = pName1; ds@1952: }else{ ds@1952: /* Figure out the db that the the trigger will be created in */ ds@1952: iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); ds@1952: if( iDb<0 ){ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: } ds@1952: ds@1952: /* If the trigger name was unqualified, and the table is a temp table, ds@1952: ** then set iDb to 1 to create the trigger in the temporary database. ds@1952: ** If sqlite3SrcListLookup() returns 0, indicating the table does not ds@1952: ** exist, the error is caught by the block below. ds@1952: */ ds@1952: if( !pTableName || db->mallocFailed ){ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: pTab = sqlite3SrcListLookup(pParse, pTableName); ds@1952: if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ ds@1952: iDb = 1; ds@1952: } ds@1952: ds@1952: /* Ensure the table name matches database name and that the table exists */ ds@1952: if( db->mallocFailed ) goto trigger_cleanup; ds@1952: assert( pTableName->nSrc==1 ); ds@1952: if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && ds@1952: sqlite3FixSrcList(&sFix, pTableName) ){ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: pTab = sqlite3SrcListLookup(pParse, pTableName); ds@1952: if( !pTab ){ ds@1952: /* The table does not exist. */ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: if( IsVirtual(pTab) ){ ds@1952: sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: ds@1952: /* Check that the trigger name is not reserved and that no trigger of the ds@1952: ** specified name exists */ ds@1952: zName = sqlite3NameFromToken(db, pName); ds@1952: if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){ ds@1952: if( !noErr ){ ds@1952: sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); ds@1952: } ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: ds@1952: /* Do not create a trigger on a system table */ ds@1952: if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ ds@1952: sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); ds@1952: pParse->nErr++; ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: ds@1952: /* INSTEAD of triggers are only for views and views only support INSTEAD ds@1952: ** of triggers. ds@1952: */ ds@1952: if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ ds@1952: sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", ds@1952: (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ ds@1952: sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" ds@1952: " trigger on table: %S", pTableName, 0); ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); ds@1952: ds@1952: #ifndef SQLITE_OMIT_AUTHORIZATION ds@1952: { ds@1952: int code = SQLITE_CREATE_TRIGGER; ds@1952: const char *zDb = db->aDb[iTabDb].zName; ds@1952: const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; ds@1952: if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; ds@1952: if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ ds@1952: goto trigger_cleanup; ds@1952: } ds@1952: } ds@1952: #endif ds@1952: ds@1952: /* INSTEAD OF triggers can only appear on views and BEFORE triggers ds@1952: ** cannot appear on views. So we might as well translate every ds@1952: ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code ds@1952: ** elsewhere. ds@1952: */ ds@1952: if (tr_tm == TK_INSTEAD){ ds@1952: tr_tm = TK_BEFORE; ds@1952: } ds@1952: ds@1952: /* Build the Trigger object */ ds@1952: pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger)); ds@1952: if( pTrigger==0 ) goto trigger_cleanup; ds@1952: pTrigger->name = zName; ds@1952: zName = 0; ds@1952: pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName); ds@1952: pTrigger->pSchema = db->aDb[iDb].pSchema; ds@1952: pTrigger->pTabSchema = pTab->pSchema; ds@1952: pTrigger->op = op; ds@1952: pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; ds@1952: pTrigger->pWhen = sqlite3ExprDup(db, pWhen); ds@1952: pTrigger->pColumns = sqlite3IdListDup(db, pColumns); ds@1952: sqlite3TokenCopy(db, &pTrigger->nameToken,pName); ds@1952: assert( pParse->pNewTrigger==0 ); ds@1952: pParse->pNewTrigger = pTrigger; ds@1952: ds@1952: trigger_cleanup: ds@1952: sqlite3_free(zName); ds@1952: sqlite3SrcListDelete(pTableName); ds@1952: sqlite3IdListDelete(pColumns); ds@1952: sqlite3ExprDelete(pWhen); ds@1952: if( !pParse->pNewTrigger ){ ds@1952: sqlite3DeleteTrigger(pTrigger); ds@1952: }else{ ds@1952: assert( pParse->pNewTrigger==pTrigger ); ds@1952: } ds@1952: } ds@1952: ds@1952: /* ds@1952: ** This routine is called after all of the trigger actions have been parsed ds@1952: ** in order to complete the process of building the trigger. ds@1952: */ ds@1952: void sqlite3FinishTrigger( ds@1952: Parse *pParse, /* Parser context */ ds@1952: TriggerStep *pStepList, /* The triggered program */ ds@1952: Token *pAll /* Token that describes the complete CREATE TRIGGER */ ds@1952: ){ ds@1952: Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ ds@1952: sqlite3 *db = pParse->db; /* The database */ ds@1952: DbFixer sFix; ds@1952: int iDb; /* Database containing the trigger */ ds@1952: ds@1952: pTrig = pParse->pNewTrigger; ds@1952: pParse->pNewTrigger = 0; ds@1952: if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; ds@1952: iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); ds@1952: pTrig->step_list = pStepList; ds@1952: while( pStepList ){ ds@1952: pStepList->pTrig = pTrig; ds@1952: pStepList = pStepList->pNext; ds@1952: } ds@1952: if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) ds@1952: && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ ds@1952: goto triggerfinish_cleanup; ds@1952: } ds@1952: ds@1952: /* if we are not initializing, and this trigger is not on a TEMP table, ds@1952: ** build the sqlite_master entry ds@1952: */ ds@1952: if( !db->init.busy ){ ds@1952: static const VdbeOpList insertTrig[] = { ds@1952: { OP_NewRowid, 0, 0, 0 }, ds@1952: { OP_String8, 0, 0, "trigger" }, ds@1952: { OP_String8, 0, 0, 0 }, /* 2: trigger name */ ds@1952: { OP_String8, 0, 0, 0 }, /* 3: table name */ ds@1952: { OP_Integer, 0, 0, 0 }, ds@1952: { OP_String8, 0, 0, "CREATE TRIGGER "}, ds@1952: { OP_String8, 0, 0, 0 }, /* 6: SQL */ ds@1952: { OP_Concat, 0, 0, 0 }, ds@1952: { OP_MakeRecord, 5, 0, "aaada" }, ds@1952: { OP_Insert, 0, 0, 0 }, ds@1952: }; ds@1952: int addr; ds@1952: Vdbe *v; ds@1952: ds@1952: /* Make an entry in the sqlite_master table */ ds@1952: v = sqlite3GetVdbe(pParse); ds@1952: if( v==0 ) goto triggerfinish_cleanup; ds@1952: sqlite3BeginWriteOperation(pParse, 0, iDb); ds@1952: sqlite3OpenMasterTable(pParse, iDb); ds@1952: addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); ds@1952: sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); ds@1952: sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); ds@1952: sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n); ds@1952: sqlite3ChangeCookie(db, v, iDb); ds@1952: sqlite3VdbeAddOp(v, OP_Close, 0, 0); ds@1952: sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, sqlite3MPrintf( ds@1952: db, "type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC ds@1952: ); ds@1952: } ds@1952: ds@1952: if( db->init.busy ){ ds@1952: int n; ds@1952: Table *pTab; ds@1952: Trigger *pDel; ds@1952: pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, ds@1952: pTrig->name, strlen(pTrig->name), pTrig); ds@1952: if( pDel ){ ds@1952: assert( pDel==pTrig ); ds@1952: db->mallocFailed = 1; ds@1952: goto triggerfinish_cleanup; ds@1952: } ds@1952: n = strlen(pTrig->table) + 1; ds@1952: pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); ds@1952: assert( pTab!=0 ); ds@1952: pTrig->pNext = pTab->pTrigger; ds@1952: pTab->pTrigger = pTrig; ds@1952: pTrig = 0; ds@1952: } ds@1952: ds@1952: triggerfinish_cleanup: ds@1952: sqlite3DeleteTrigger(pTrig); ds@1952: assert( !pParse->pNewTrigger ); ds@1952: sqlite3DeleteTriggerStep(pStepList); ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Make a copy of all components of the given trigger step. This has ds@1952: ** the effect of copying all Expr.token.z values into memory obtained ds@1952: ** from sqlite3_malloc(). As initially created, the Expr.token.z values ds@1952: ** all point to the input string that was fed to the parser. But that ds@1952: ** string is ephemeral - it will go away as soon as the sqlite3_exec() ds@1952: ** call that started the parser exits. This routine makes a persistent ds@1952: ** copy of all the Expr.token.z strings so that the TriggerStep structure ds@1952: ** will be valid even after the sqlite3_exec() call returns. ds@1952: */ ds@1952: static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){ ds@1952: if( p->target.z ){ ds@1952: p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n); ds@1952: p->target.dyn = 1; ds@1952: } ds@1952: if( p->pSelect ){ ds@1952: Select *pNew = sqlite3SelectDup(db, p->pSelect); ds@1952: sqlite3SelectDelete(p->pSelect); ds@1952: p->pSelect = pNew; ds@1952: } ds@1952: if( p->pWhere ){ ds@1952: Expr *pNew = sqlite3ExprDup(db, p->pWhere); ds@1952: sqlite3ExprDelete(p->pWhere); ds@1952: p->pWhere = pNew; ds@1952: } ds@1952: if( p->pExprList ){ ds@1952: ExprList *pNew = sqlite3ExprListDup(db, p->pExprList); ds@1952: sqlite3ExprListDelete(p->pExprList); ds@1952: p->pExprList = pNew; ds@1952: } ds@1952: if( p->pIdList ){ ds@1952: IdList *pNew = sqlite3IdListDup(db, p->pIdList); ds@1952: sqlite3IdListDelete(p->pIdList); ds@1952: p->pIdList = pNew; ds@1952: } ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Turn a SELECT statement (that the pSelect parameter points to) into ds@1952: ** a trigger step. Return a pointer to a TriggerStep structure. ds@1952: ** ds@1952: ** The parser calls this routine when it finds a SELECT statement in ds@1952: ** body of a TRIGGER. ds@1952: */ ds@1952: TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ ds@1952: TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); ds@1952: if( pTriggerStep==0 ) { ds@1952: sqlite3SelectDelete(pSelect); ds@1952: return 0; ds@1952: } ds@1952: ds@1952: pTriggerStep->op = TK_SELECT; ds@1952: pTriggerStep->pSelect = pSelect; ds@1952: pTriggerStep->orconf = OE_Default; ds@1952: sqlitePersistTriggerStep(db, pTriggerStep); ds@1952: ds@1952: return pTriggerStep; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Build a trigger step out of an INSERT statement. Return a pointer ds@1952: ** to the new trigger step. ds@1952: ** ds@1952: ** The parser calls this routine when it sees an INSERT inside the ds@1952: ** body of a trigger. ds@1952: */ ds@1952: TriggerStep *sqlite3TriggerInsertStep( ds@1952: sqlite3 *db, /* The database connection */ ds@1952: Token *pTableName, /* Name of the table into which we insert */ ds@1952: IdList *pColumn, /* List of columns in pTableName to insert into */ ds@1952: ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ ds@1952: Select *pSelect, /* A SELECT statement that supplies values */ ds@1952: int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ ds@1952: ){ ds@1952: TriggerStep *pTriggerStep; ds@1952: ds@1952: assert(pEList == 0 || pSelect == 0); ds@1952: assert(pEList != 0 || pSelect != 0 || db->mallocFailed); ds@1952: ds@1952: pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); ds@1952: if( pTriggerStep ){ ds@1952: pTriggerStep->op = TK_INSERT; ds@1952: pTriggerStep->pSelect = pSelect; ds@1952: pTriggerStep->target = *pTableName; ds@1952: pTriggerStep->pIdList = pColumn; ds@1952: pTriggerStep->pExprList = pEList; ds@1952: pTriggerStep->orconf = orconf; ds@1952: sqlitePersistTriggerStep(db, pTriggerStep); ds@1952: }else{ ds@1952: sqlite3IdListDelete(pColumn); ds@1952: sqlite3ExprListDelete(pEList); ds@1952: sqlite3SelectDelete(pSelect); ds@1952: } ds@1952: ds@1952: return pTriggerStep; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Construct a trigger step that implements an UPDATE statement and return ds@1952: ** a pointer to that trigger step. The parser calls this routine when it ds@1952: ** sees an UPDATE statement inside the body of a CREATE TRIGGER. ds@1952: */ ds@1952: TriggerStep *sqlite3TriggerUpdateStep( ds@1952: sqlite3 *db, /* The database connection */ ds@1952: Token *pTableName, /* Name of the table to be updated */ ds@1952: ExprList *pEList, /* The SET clause: list of column and new values */ ds@1952: Expr *pWhere, /* The WHERE clause */ ds@1952: int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ ds@1952: ){ ds@1952: TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); ds@1952: if( pTriggerStep==0 ){ ds@1952: sqlite3ExprListDelete(pEList); ds@1952: sqlite3ExprDelete(pWhere); ds@1952: return 0; ds@1952: } ds@1952: ds@1952: pTriggerStep->op = TK_UPDATE; ds@1952: pTriggerStep->target = *pTableName; ds@1952: pTriggerStep->pExprList = pEList; ds@1952: pTriggerStep->pWhere = pWhere; ds@1952: pTriggerStep->orconf = orconf; ds@1952: sqlitePersistTriggerStep(db, pTriggerStep); ds@1952: ds@1952: return pTriggerStep; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Construct a trigger step that implements a DELETE statement and return ds@1952: ** a pointer to that trigger step. The parser calls this routine when it ds@1952: ** sees a DELETE statement inside the body of a CREATE TRIGGER. ds@1952: */ ds@1952: TriggerStep *sqlite3TriggerDeleteStep( ds@1952: sqlite3 *db, /* Database connection */ ds@1952: Token *pTableName, /* The table from which rows are deleted */ ds@1952: Expr *pWhere /* The WHERE clause */ ds@1952: ){ ds@1952: TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); ds@1952: if( pTriggerStep==0 ){ ds@1952: sqlite3ExprDelete(pWhere); ds@1952: return 0; ds@1952: } ds@1952: ds@1952: pTriggerStep->op = TK_DELETE; ds@1952: pTriggerStep->target = *pTableName; ds@1952: pTriggerStep->pWhere = pWhere; ds@1952: pTriggerStep->orconf = OE_Default; ds@1952: sqlitePersistTriggerStep(db, pTriggerStep); ds@1952: ds@1952: return pTriggerStep; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Recursively delete a Trigger structure ds@1952: */ ds@1952: void sqlite3DeleteTrigger(Trigger *pTrigger){ ds@1952: if( pTrigger==0 ) return; ds@1952: sqlite3DeleteTriggerStep(pTrigger->step_list); ds@1952: sqlite3_free(pTrigger->name); ds@1952: sqlite3_free(pTrigger->table); ds@1952: sqlite3ExprDelete(pTrigger->pWhen); ds@1952: sqlite3IdListDelete(pTrigger->pColumns); ds@1952: if( pTrigger->nameToken.dyn ) sqlite3_free((char*)pTrigger->nameToken.z); ds@1952: sqlite3_free(pTrigger); ds@1952: } ds@1952: ds@1952: /* ds@1952: ** This function is called to drop a trigger from the database schema. ds@1952: ** ds@1952: ** This may be called directly from the parser and therefore identifies ds@1952: ** the trigger by name. The sqlite3DropTriggerPtr() routine does the ds@1952: ** same job as this routine except it takes a pointer to the trigger ds@1952: ** instead of the trigger name. ds@1952: **/ ds@1952: void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ ds@1952: Trigger *pTrigger = 0; ds@1952: int i; ds@1952: const char *zDb; ds@1952: const char *zName; ds@1952: int nName; ds@1952: sqlite3 *db = pParse->db; ds@1952: ds@1952: if( db->mallocFailed ) goto drop_trigger_cleanup; ds@1952: if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ ds@1952: goto drop_trigger_cleanup; ds@1952: } ds@1952: ds@1952: assert( pName->nSrc==1 ); ds@1952: zDb = pName->a[0].zDatabase; ds@1952: zName = pName->a[0].zName; ds@1952: nName = strlen(zName); ds@1952: for(i=OMIT_TEMPDB; inDb; i++){ ds@1952: int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ ds@1952: if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; ds@1952: pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); ds@1952: if( pTrigger ) break; ds@1952: } ds@1952: if( !pTrigger ){ ds@1952: if( !noErr ){ ds@1952: sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); ds@1952: } ds@1952: goto drop_trigger_cleanup; ds@1952: } ds@1952: sqlite3DropTriggerPtr(pParse, pTrigger); ds@1952: ds@1952: drop_trigger_cleanup: ds@1952: sqlite3SrcListDelete(pName); ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Return a pointer to the Table structure for the table that a trigger ds@1952: ** is set on. ds@1952: */ ds@1952: static Table *tableOfTrigger(Trigger *pTrigger){ ds@1952: int n = strlen(pTrigger->table) + 1; ds@1952: return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); ds@1952: } ds@1952: ds@1952: ds@1952: /* ds@1952: ** Drop a trigger given a pointer to that trigger. ds@1952: */ ds@1952: void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ ds@1952: Table *pTable; ds@1952: Vdbe *v; ds@1952: sqlite3 *db = pParse->db; ds@1952: int iDb; ds@1952: ds@1952: iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); ds@1952: assert( iDb>=0 && iDbnDb ); ds@1952: pTable = tableOfTrigger(pTrigger); ds@1952: assert( pTable ); ds@1952: assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); ds@1952: #ifndef SQLITE_OMIT_AUTHORIZATION ds@1952: { ds@1952: int code = SQLITE_DROP_TRIGGER; ds@1952: const char *zDb = db->aDb[iDb].zName; ds@1952: const char *zTab = SCHEMA_TABLE(iDb); ds@1952: if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; ds@1952: if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || ds@1952: sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ ds@1952: return; ds@1952: } ds@1952: } ds@1952: #endif ds@1952: ds@1952: /* Generate code to destroy the database record of the trigger. ds@1952: */ ds@1952: assert( pTable!=0 ); ds@1952: if( (v = sqlite3GetVdbe(pParse))!=0 ){ ds@1952: int base; ds@1952: static const VdbeOpList dropTrigger[] = { ds@1952: { OP_Rewind, 0, ADDR(9), 0}, ds@1952: { OP_String8, 0, 0, 0}, /* 1 */ ds@1952: { OP_Column, 0, 1, 0}, ds@1952: { OP_Ne, 0, ADDR(8), 0}, ds@1952: { OP_String8, 0, 0, "trigger"}, ds@1952: { OP_Column, 0, 0, 0}, ds@1952: { OP_Ne, 0, ADDR(8), 0}, ds@1952: { OP_Delete, 0, 0, 0}, ds@1952: { OP_Next, 0, ADDR(1), 0}, /* 8 */ ds@1952: }; ds@1952: ds@1952: sqlite3BeginWriteOperation(pParse, 0, iDb); ds@1952: sqlite3OpenMasterTable(pParse, iDb); ds@1952: base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); ds@1952: sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); ds@1952: sqlite3ChangeCookie(db, v, iDb); ds@1952: sqlite3VdbeAddOp(v, OP_Close, 0, 0); ds@1952: sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); ds@1952: } ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Remove a trigger from the hash tables of the sqlite* pointer. ds@1952: */ ds@1952: void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ ds@1952: Trigger *pTrigger; ds@1952: int nName = strlen(zName); ds@1952: pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash), ds@1952: zName, nName, 0); ds@1952: if( pTrigger ){ ds@1952: Table *pTable = tableOfTrigger(pTrigger); ds@1952: assert( pTable!=0 ); ds@1952: if( pTable->pTrigger == pTrigger ){ ds@1952: pTable->pTrigger = pTrigger->pNext; ds@1952: }else{ ds@1952: Trigger *cc = pTable->pTrigger; ds@1952: while( cc ){ ds@1952: if( cc->pNext == pTrigger ){ ds@1952: cc->pNext = cc->pNext->pNext; ds@1952: break; ds@1952: } ds@1952: cc = cc->pNext; ds@1952: } ds@1952: assert(cc); ds@1952: } ds@1952: sqlite3DeleteTrigger(pTrigger); ds@1952: db->flags |= SQLITE_InternChanges; ds@1952: } ds@1952: } ds@1952: ds@1952: /* ds@1952: ** pEList is the SET clause of an UPDATE statement. Each entry ds@1952: ** in pEList is of the format =. If any of the entries ds@1952: ** in pEList have an which matches an identifier in pIdList, ds@1952: ** then return TRUE. If pIdList==NULL, then it is considered a ds@1952: ** wildcard that matches anything. Likewise if pEList==NULL then ds@1952: ** it matches anything so always return true. Return false only ds@1952: ** if there is no match. ds@1952: */ ds@1952: static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ ds@1952: int e; ds@1952: if( !pIdList || !pEList ) return 1; ds@1952: for(e=0; enExpr; e++){ ds@1952: if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; ds@1952: } ds@1952: return 0; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Return a bit vector to indicate what kind of triggers exist for operation ds@1952: ** "op" on table pTab. If pChanges is not NULL then it is a list of columns ds@1952: ** that are being updated. Triggers only match if the ON clause of the ds@1952: ** trigger definition overlaps the set of columns being updated. ds@1952: ** ds@1952: ** The returned bit vector is some combination of TRIGGER_BEFORE and ds@1952: ** TRIGGER_AFTER. ds@1952: */ ds@1952: int sqlite3TriggersExist( ds@1952: Parse *pParse, /* Used to check for recursive triggers */ ds@1952: Table *pTab, /* The table the contains the triggers */ ds@1952: int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ ds@1952: ExprList *pChanges /* Columns that change in an UPDATE statement */ ds@1952: ){ ds@1952: Trigger *pTrigger; ds@1952: int mask = 0; ds@1952: ds@1952: pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger; ds@1952: while( pTrigger ){ ds@1952: if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){ ds@1952: mask |= pTrigger->tr_tm; ds@1952: } ds@1952: pTrigger = pTrigger->pNext; ds@1952: } ds@1952: return mask; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Convert the pStep->target token into a SrcList and return a pointer ds@1952: ** to that SrcList. ds@1952: ** ds@1952: ** This routine adds a specific database name, if needed, to the target when ds@1952: ** forming the SrcList. This prevents a trigger in one database from ds@1952: ** referring to a target in another database. An exception is when the ds@1952: ** trigger is in TEMP in which case it can refer to any other database it ds@1952: ** wants. ds@1952: */ ds@1952: static SrcList *targetSrcList( ds@1952: Parse *pParse, /* The parsing context */ ds@1952: TriggerStep *pStep /* The trigger containing the target token */ ds@1952: ){ ds@1952: Token sDb; /* Dummy database name token */ ds@1952: int iDb; /* Index of the database to use */ ds@1952: SrcList *pSrc; /* SrcList to be returned */ ds@1952: ds@1952: iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); ds@1952: if( iDb==0 || iDb>=2 ){ ds@1952: assert( iDbdb->nDb ); ds@1952: sDb.z = (u8*)pParse->db->aDb[iDb].zName; ds@1952: sDb.n = strlen((char*)sDb.z); ds@1952: pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target); ds@1952: } else { ds@1952: pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0); ds@1952: } ds@1952: return pSrc; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** Generate VDBE code for zero or more statements inside the body of a ds@1952: ** trigger. ds@1952: */ ds@1952: static int codeTriggerProgram( ds@1952: Parse *pParse, /* The parser context */ ds@1952: TriggerStep *pStepList, /* List of statements inside the trigger body */ ds@1952: int orconfin /* Conflict algorithm. (OE_Abort, etc) */ ds@1952: ){ ds@1952: TriggerStep * pTriggerStep = pStepList; ds@1952: int orconf; ds@1952: Vdbe *v = pParse->pVdbe; ds@1952: sqlite3 *db = pParse->db; ds@1952: ds@1952: assert( pTriggerStep!=0 ); ds@1952: assert( v!=0 ); ds@1952: sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); ds@1952: VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name)); ds@1952: while( pTriggerStep ){ ds@1952: orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; ds@1952: pParse->trigStack->orconf = orconf; ds@1952: switch( pTriggerStep->op ){ ds@1952: case TK_SELECT: { ds@1952: Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect); ds@1952: if( ss ){ ds@1952: sqlite3SelectResolve(pParse, ss, 0); ds@1952: sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); ds@1952: sqlite3SelectDelete(ss); ds@1952: } ds@1952: break; ds@1952: } ds@1952: case TK_UPDATE: { ds@1952: SrcList *pSrc; ds@1952: pSrc = targetSrcList(pParse, pTriggerStep); ds@1952: sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); ds@1952: sqlite3Update(pParse, pSrc, ds@1952: sqlite3ExprListDup(db, pTriggerStep->pExprList), ds@1952: sqlite3ExprDup(db, pTriggerStep->pWhere), orconf); ds@1952: sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); ds@1952: break; ds@1952: } ds@1952: case TK_INSERT: { ds@1952: SrcList *pSrc; ds@1952: pSrc = targetSrcList(pParse, pTriggerStep); ds@1952: sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); ds@1952: sqlite3Insert(pParse, pSrc, ds@1952: sqlite3ExprListDup(db, pTriggerStep->pExprList), ds@1952: sqlite3SelectDup(db, pTriggerStep->pSelect), ds@1952: sqlite3IdListDup(db, pTriggerStep->pIdList), orconf); ds@1952: sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); ds@1952: break; ds@1952: } ds@1952: case TK_DELETE: { ds@1952: SrcList *pSrc; ds@1952: sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); ds@1952: pSrc = targetSrcList(pParse, pTriggerStep); ds@1952: sqlite3DeleteFrom(pParse, pSrc, ds@1952: sqlite3ExprDup(db, pTriggerStep->pWhere)); ds@1952: sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); ds@1952: break; ds@1952: } ds@1952: default: ds@1952: assert(0); ds@1952: } ds@1952: pTriggerStep = pTriggerStep->pNext; ds@1952: } ds@1952: sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); ds@1952: VdbeComment((v, "# end trigger %s", pStepList->pTrig->name)); ds@1952: ds@1952: return 0; ds@1952: } ds@1952: ds@1952: /* ds@1952: ** This is called to code FOR EACH ROW triggers. ds@1952: ** ds@1952: ** When the code that this function generates is executed, the following ds@1952: ** must be true: ds@1952: ** ds@1952: ** 1. No cursors may be open in the main database. (But newIdx and oldIdx ds@1952: ** can be indices of cursors in temporary tables. See below.) ds@1952: ** ds@1952: ** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then ds@1952: ** a temporary vdbe cursor (index newIdx) must be open and pointing at ds@1952: ** a row containing values to be substituted for new.* expressions in the ds@1952: ** trigger program(s). ds@1952: ** ds@1952: ** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then ds@1952: ** a temporary vdbe cursor (index oldIdx) must be open and pointing at ds@1952: ** a row containing values to be substituted for old.* expressions in the ds@1952: ** trigger program(s). ds@1952: ** ds@1952: */ ds@1952: int sqlite3CodeRowTrigger( ds@1952: Parse *pParse, /* Parse context */ ds@1952: int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ds@1952: ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ ds@1952: int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ ds@1952: Table *pTab, /* The table to code triggers from */ ds@1952: int newIdx, /* The indice of the "new" row to access */ ds@1952: int oldIdx, /* The indice of the "old" row to access */ ds@1952: int orconf, /* ON CONFLICT policy */ ds@1952: int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ ds@1952: ){ ds@1952: Trigger *p; ds@1952: TriggerStack trigStackEntry; ds@1952: ds@1952: assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); ds@1952: assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); ds@1952: ds@1952: assert(newIdx != -1 || oldIdx != -1); ds@1952: ds@1952: for(p=pTab->pTrigger; p; p=p->pNext){ ds@1952: int fire_this = 0; ds@1952: ds@1952: /* Determine whether we should code this trigger */ ds@1952: if( ds@1952: p->op==op && ds@1952: p->tr_tm==tr_tm && ds@1952: (p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) && ds@1952: (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) ds@1952: ){ ds@1952: TriggerStack *pS; /* Pointer to trigger-stack entry */ ds@1952: for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){} ds@1952: if( !pS ){ ds@1952: fire_this = 1; ds@1952: } ds@1952: #if 0 /* Give no warning for recursive triggers. Just do not do them */ ds@1952: else{ ds@1952: sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)", ds@1952: p->name); ds@1952: return SQLITE_ERROR; ds@1952: } ds@1952: #endif ds@1952: } ds@1952: ds@1952: if( fire_this ){ ds@1952: int endTrigger; ds@1952: Expr * whenExpr; ds@1952: AuthContext sContext; ds@1952: NameContext sNC; ds@1952: ds@1952: memset(&sNC, 0, sizeof(sNC)); ds@1952: sNC.pParse = pParse; ds@1952: ds@1952: /* Push an entry on to the trigger stack */ ds@1952: trigStackEntry.pTrigger = p; ds@1952: trigStackEntry.newIdx = newIdx; ds@1952: trigStackEntry.oldIdx = oldIdx; ds@1952: trigStackEntry.pTab = pTab; ds@1952: trigStackEntry.pNext = pParse->trigStack; ds@1952: trigStackEntry.ignoreJump = ignoreJump; ds@1952: pParse->trigStack = &trigStackEntry; ds@1952: sqlite3AuthContextPush(pParse, &sContext, p->name); ds@1952: ds@1952: /* code the WHEN clause */ ds@1952: endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); ds@1952: whenExpr = sqlite3ExprDup(pParse->db, p->pWhen); ds@1952: if( sqlite3ExprResolveNames(&sNC, whenExpr) ){ ds@1952: pParse->trigStack = trigStackEntry.pNext; ds@1952: sqlite3ExprDelete(whenExpr); ds@1952: return 1; ds@1952: } ds@1952: sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); ds@1952: sqlite3ExprDelete(whenExpr); ds@1952: ds@1952: codeTriggerProgram(pParse, p->step_list, orconf); ds@1952: ds@1952: /* Pop the entry off the trigger stack */ ds@1952: pParse->trigStack = trigStackEntry.pNext; ds@1952: sqlite3AuthContextPop(&sContext); ds@1952: ds@1952: sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); ds@1952: } ds@1952: } ds@1952: return 0; ds@1952: } ds@1952: #endif /* !defined(SQLITE_OMIT_TRIGGER) */