1c3f9bad2Sdanielk1977 /* 2633ed08dSdanielk1977 ** 3633ed08dSdanielk1977 ** The author disclaims copyright to this source code. In place of 4633ed08dSdanielk1977 ** a legal notice, here is a blessing: 5633ed08dSdanielk1977 ** 6633ed08dSdanielk1977 ** May you do good and not evil. 7633ed08dSdanielk1977 ** May you find forgiveness for yourself and forgive others. 8633ed08dSdanielk1977 ** May you share freely, never taking more than you give. 9633ed08dSdanielk1977 ** 10633ed08dSdanielk1977 ************************************************************************* 11633ed08dSdanielk1977 * 12c3f9bad2Sdanielk1977 */ 13c3f9bad2Sdanielk1977 #include "sqliteInt.h" 149adf9ac4Sdrh 15b7f9164eSdrh #ifndef SQLITE_OMIT_TRIGGER 16c3f9bad2Sdanielk1977 /* 174b59ab5eSdrh ** Delete a linked list of TriggerStep structures. 184b59ab5eSdrh */ 194adee20fSdanielk1977 void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){ 204b59ab5eSdrh while( pTriggerStep ){ 214b59ab5eSdrh TriggerStep * pTmp = pTriggerStep; 224b59ab5eSdrh pTriggerStep = pTriggerStep->pNext; 234b59ab5eSdrh 248c74a8caSdrh if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z); 254adee20fSdanielk1977 sqlite3ExprDelete(pTmp->pWhere); 264adee20fSdanielk1977 sqlite3ExprListDelete(pTmp->pExprList); 274adee20fSdanielk1977 sqlite3SelectDelete(pTmp->pSelect); 284adee20fSdanielk1977 sqlite3IdListDelete(pTmp->pIdList); 294b59ab5eSdrh 304b59ab5eSdrh sqliteFree(pTmp); 314b59ab5eSdrh } 324b59ab5eSdrh } 334b59ab5eSdrh 344b59ab5eSdrh /* 35f0f258b1Sdrh ** This is called by the parser when it sees a CREATE TRIGGER statement 36f0f258b1Sdrh ** up to the point of the BEGIN before the trigger actions. A Trigger 37f0f258b1Sdrh ** structure is generated based on the information available and stored 38f0f258b1Sdrh ** in pParse->pNewTrigger. After the trigger actions have been parsed, the 394adee20fSdanielk1977 ** sqlite3FinishTrigger() function is called to complete the trigger 40f0f258b1Sdrh ** construction process. 41c3f9bad2Sdanielk1977 */ 424adee20fSdanielk1977 void sqlite3BeginTrigger( 43c3f9bad2Sdanielk1977 Parse *pParse, /* The parse context of the CREATE TRIGGER statement */ 44ef2cb63eSdanielk1977 Token *pName1, /* The name of the trigger */ 45ef2cb63eSdanielk1977 Token *pName2, /* The name of the trigger */ 46d702fccbSdanielk1977 int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */ 47c3f9bad2Sdanielk1977 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */ 48633ed08dSdanielk1977 IdList *pColumns, /* column list if this is an UPDATE OF trigger */ 49d24cc427Sdrh SrcList *pTableName,/* The name of the table/view the trigger applies to */ 50c3f9bad2Sdanielk1977 int foreach, /* One of TK_ROW or TK_STATEMENT */ 51c3f9bad2Sdanielk1977 Expr *pWhen, /* WHEN clause */ 52f0f258b1Sdrh int isTemp /* True if the TEMPORARY keyword is present */ 539adf9ac4Sdrh ){ 54d5d56523Sdanielk1977 Trigger *pTrigger = 0; 55ef2cb63eSdanielk1977 Table *pTab; 56e5f9c644Sdrh char *zName = 0; /* Name of the trigger */ 579bb575fdSdrh sqlite3 *db = pParse->db; 58ef2cb63eSdanielk1977 int iDb; /* The database to store the trigger in */ 59ef2cb63eSdanielk1977 Token *pName; /* The unqualified db name */ 604312db55Sdrh DbFixer sFix; 61da184236Sdanielk1977 int iTabDb; 62ed6c8671Sdrh 6343617e9aSdrh assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ 6443617e9aSdrh assert( pName2!=0 ); 65ef2cb63eSdanielk1977 if( isTemp ){ 66ef2cb63eSdanielk1977 /* If TEMP was specified, then the trigger name may not be qualified. */ 6743617e9aSdrh if( pName2->n>0 ){ 68ef2cb63eSdanielk1977 sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); 69ef2cb63eSdanielk1977 goto trigger_cleanup; 70ef2cb63eSdanielk1977 } 71ef2cb63eSdanielk1977 iDb = 1; 72ef2cb63eSdanielk1977 pName = pName1; 73ef2cb63eSdanielk1977 }else{ 74ef2cb63eSdanielk1977 /* Figure out the db that the the trigger will be created in */ 75ef2cb63eSdanielk1977 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); 76ef2cb63eSdanielk1977 if( iDb<0 ){ 77ef2cb63eSdanielk1977 goto trigger_cleanup; 78ef2cb63eSdanielk1977 } 79ef2cb63eSdanielk1977 } 80ef2cb63eSdanielk1977 81ef2cb63eSdanielk1977 /* If the trigger name was unqualified, and the table is a temp table, 82ef2cb63eSdanielk1977 ** then set iDb to 1 to create the trigger in the temporary database. 83ef2cb63eSdanielk1977 ** If sqlite3SrcListLookup() returns 0, indicating the table does not 84ef2cb63eSdanielk1977 ** exist, the error is caught by the block below. 85c3f9bad2Sdanielk1977 */ 869e12800dSdanielk1977 if( !pTableName || sqlite3MallocFailed() ){ 876f7adc8aSdrh goto trigger_cleanup; 886f7adc8aSdrh } 89ef2cb63eSdanielk1977 pTab = sqlite3SrcListLookup(pParse, pTableName); 90da184236Sdanielk1977 if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ 91ef2cb63eSdanielk1977 iDb = 1; 92ef2cb63eSdanielk1977 } 93ef2cb63eSdanielk1977 94ef2cb63eSdanielk1977 /* Ensure the table name matches database name and that the table exists */ 959e12800dSdanielk1977 if( sqlite3MallocFailed() ) goto trigger_cleanup; 96d24cc427Sdrh assert( pTableName->nSrc==1 ); 97ef2cb63eSdanielk1977 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && 98ef2cb63eSdanielk1977 sqlite3FixSrcList(&sFix, pTableName) ){ 994312db55Sdrh goto trigger_cleanup; 100f26e09c8Sdrh } 101ef2cb63eSdanielk1977 pTab = sqlite3SrcListLookup(pParse, pTableName); 102ef2cb63eSdanielk1977 if( !pTab ){ 103ef2cb63eSdanielk1977 /* The table does not exist. */ 104d24cc427Sdrh goto trigger_cleanup; 105d24cc427Sdrh } 106d24cc427Sdrh 107d8123366Sdanielk1977 /* Check that the trigger name is not reserved and that no trigger of the 108d8123366Sdanielk1977 ** specified name exists */ 109a99db3b6Sdrh zName = sqlite3NameFromToken(pName); 110d8123366Sdanielk1977 if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ 111d8123366Sdanielk1977 goto trigger_cleanup; 112d8123366Sdanielk1977 } 113da184236Sdanielk1977 if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,pName->n+1) ){ 1144adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); 115c3f9bad2Sdanielk1977 goto trigger_cleanup; 116c3f9bad2Sdanielk1977 } 117ef2cb63eSdanielk1977 118ef2cb63eSdanielk1977 /* Do not create a trigger on a system table */ 119dca76841Sdrh if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ 1204adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); 121e0bc4048Sdrh pParse->nErr++; 122e0bc4048Sdrh goto trigger_cleanup; 123e0bc4048Sdrh } 124ef2cb63eSdanielk1977 125ef2cb63eSdanielk1977 /* INSTEAD of triggers are only for views and views only support INSTEAD 126ef2cb63eSdanielk1977 ** of triggers. 127ef2cb63eSdanielk1977 */ 128ef2cb63eSdanielk1977 if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ 1294adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 130da93d238Sdrh (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); 131d702fccbSdanielk1977 goto trigger_cleanup; 132d702fccbSdanielk1977 } 133ef2cb63eSdanielk1977 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ 1344adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" 135da93d238Sdrh " trigger on table: %S", pTableName, 0); 136d702fccbSdanielk1977 goto trigger_cleanup; 137d702fccbSdanielk1977 } 138da184236Sdanielk1977 iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); 139ef2cb63eSdanielk1977 140e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 141e5f9c644Sdrh { 142e5f9c644Sdrh int code = SQLITE_CREATE_TRIGGER; 143da184236Sdanielk1977 const char *zDb = db->aDb[iTabDb].zName; 144e22a334bSdrh const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; 145da184236Sdanielk1977 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; 146ef2cb63eSdanielk1977 if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ 147ed6c8671Sdrh goto trigger_cleanup; 148ed6c8671Sdrh } 149da184236Sdanielk1977 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ 15077ad4e41Sdrh goto trigger_cleanup; 15177ad4e41Sdrh } 152d702fccbSdanielk1977 } 153e5f9c644Sdrh #endif 154d702fccbSdanielk1977 155ef2cb63eSdanielk1977 /* INSTEAD OF triggers can only appear on views and BEFORE triggers 1565cf590c1Sdrh ** cannot appear on views. So we might as well translate every 1575cf590c1Sdrh ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code 1585cf590c1Sdrh ** elsewhere. 1595cf590c1Sdrh */ 160d702fccbSdanielk1977 if (tr_tm == TK_INSTEAD){ 161d702fccbSdanielk1977 tr_tm = TK_BEFORE; 162c3f9bad2Sdanielk1977 } 163c3f9bad2Sdanielk1977 164c3f9bad2Sdanielk1977 /* Build the Trigger object */ 165ef2cb63eSdanielk1977 pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger)); 166ef2cb63eSdanielk1977 if( pTrigger==0 ) goto trigger_cleanup; 167ef2cb63eSdanielk1977 pTrigger->name = zName; 168e5f9c644Sdrh zName = 0; 169ef2cb63eSdanielk1977 pTrigger->table = sqliteStrDup(pTableName->a[0].zName); 170da184236Sdanielk1977 pTrigger->pSchema = db->aDb[iDb].pSchema; 171aaf22685Sdanielk1977 pTrigger->pTabSchema = pTab->pSchema; 172ef2cb63eSdanielk1977 pTrigger->op = op; 173dca76841Sdrh pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; 174ef2cb63eSdanielk1977 pTrigger->pWhen = sqlite3ExprDup(pWhen); 175ef2cb63eSdanielk1977 pTrigger->pColumns = sqlite3IdListDup(pColumns); 176ef2cb63eSdanielk1977 pTrigger->foreach = foreach; 177ef2cb63eSdanielk1977 sqlite3TokenCopy(&pTrigger->nameToken,pName); 178f0f258b1Sdrh assert( pParse->pNewTrigger==0 ); 179ef2cb63eSdanielk1977 pParse->pNewTrigger = pTrigger; 180f0f258b1Sdrh 181f0f258b1Sdrh trigger_cleanup: 182f0f258b1Sdrh sqliteFree(zName); 1834adee20fSdanielk1977 sqlite3SrcListDelete(pTableName); 1844adee20fSdanielk1977 sqlite3IdListDelete(pColumns); 1854adee20fSdanielk1977 sqlite3ExprDelete(pWhen); 186d5d56523Sdanielk1977 if( !pParse->pNewTrigger ){ 187d5d56523Sdanielk1977 sqlite3DeleteTrigger(pTrigger); 188d5d56523Sdanielk1977 }else{ 189d5d56523Sdanielk1977 assert( pParse->pNewTrigger==pTrigger ); 190d5d56523Sdanielk1977 } 191f0f258b1Sdrh } 192f0f258b1Sdrh 193f0f258b1Sdrh /* 194f0f258b1Sdrh ** This routine is called after all of the trigger actions have been parsed 195f0f258b1Sdrh ** in order to complete the process of building the trigger. 196f0f258b1Sdrh */ 1974adee20fSdanielk1977 void sqlite3FinishTrigger( 198f0f258b1Sdrh Parse *pParse, /* Parser context */ 199f0f258b1Sdrh TriggerStep *pStepList, /* The triggered program */ 200f0f258b1Sdrh Token *pAll /* Token that describes the complete CREATE TRIGGER */ 201f0f258b1Sdrh ){ 202bfb9e35bSdanielk1977 Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ 2039bb575fdSdrh sqlite3 *db = pParse->db; /* The database */ 204f26e09c8Sdrh DbFixer sFix; 205da184236Sdanielk1977 int iDb; /* Database containing the trigger */ 206f0f258b1Sdrh 207bfb9e35bSdanielk1977 pTrig = pParse->pNewTrigger; 208f0f258b1Sdrh pParse->pNewTrigger = 0; 2092e588c75Sdanielk1977 if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; 210da184236Sdanielk1977 iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); 211bfb9e35bSdanielk1977 pTrig->step_list = pStepList; 212a69d9168Sdrh while( pStepList ){ 213bfb9e35bSdanielk1977 pStepList->pTrig = pTrig; 214a69d9168Sdrh pStepList = pStepList->pNext; 215a69d9168Sdrh } 216da184236Sdanielk1977 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) 217bfb9e35bSdanielk1977 && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ 218f26e09c8Sdrh goto triggerfinish_cleanup; 219f26e09c8Sdrh } 220c3f9bad2Sdanielk1977 221c3f9bad2Sdanielk1977 /* if we are not initializing, and this trigger is not on a TEMP table, 2229adf9ac4Sdrh ** build the sqlite_master entry 2239adf9ac4Sdrh */ 2241d85d931Sdrh if( !db->init.busy ){ 2255719628aSdrh static const VdbeOpList insertTrig[] = { 226f0863fe5Sdrh { OP_NewRowid, 0, 0, 0 }, 2270f69c1e3Sdanielk1977 { OP_String8, 0, 0, "trigger" }, 2280f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0 }, /* 2: trigger name */ 2290f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0 }, /* 3: table name */ 230c977f7f5Sdrh { OP_Integer, 0, 0, 0 }, 2310f69c1e3Sdanielk1977 { OP_String8, 0, 0, "CREATE TRIGGER "}, 2320f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0 }, /* 6: SQL */ 233855eb1cfSdrh { OP_Concat, 0, 0, 0 }, 2348a51256cSdrh { OP_MakeRecord, 5, 0, "aaada" }, 235f0863fe5Sdrh { OP_Insert, 0, 0, 0 }, 236c977f7f5Sdrh }; 237c977f7f5Sdrh int addr; 238c977f7f5Sdrh Vdbe *v; 239c3f9bad2Sdanielk1977 240c3f9bad2Sdanielk1977 /* Make an entry in the sqlite_master table */ 2414adee20fSdanielk1977 v = sqlite3GetVdbe(pParse); 242f0f258b1Sdrh if( v==0 ) goto triggerfinish_cleanup; 243da184236Sdanielk1977 sqlite3BeginWriteOperation(pParse, 0, iDb); 244c00da105Sdanielk1977 sqlite3OpenMasterTable(pParse, iDb); 2454adee20fSdanielk1977 addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); 246bfb9e35bSdanielk1977 sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); 247bfb9e35bSdanielk1977 sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); 2482646da7eSdrh sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n); 249da184236Sdanielk1977 sqlite3ChangeCookie(db, v, iDb); 2504adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, 0, 0); 251da184236Sdanielk1977 sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, 252bfb9e35bSdanielk1977 sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC); 253c3f9bad2Sdanielk1977 } 254c3f9bad2Sdanielk1977 255956bc92cSdrh if( db->init.busy ){ 256aaf22685Sdanielk1977 int n; 257f0f258b1Sdrh Table *pTab; 258d5d56523Sdanielk1977 Trigger *pDel; 259da184236Sdanielk1977 pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, 260bfb9e35bSdanielk1977 pTrig->name, strlen(pTrig->name)+1, pTrig); 261d5d56523Sdanielk1977 if( pDel ){ 2629e12800dSdanielk1977 assert( sqlite3MallocFailed() && pDel==pTrig ); 263d5d56523Sdanielk1977 goto triggerfinish_cleanup; 264d5d56523Sdanielk1977 } 265aaf22685Sdanielk1977 n = strlen(pTrig->table) + 1; 266aaf22685Sdanielk1977 pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); 267f0f258b1Sdrh assert( pTab!=0 ); 268bfb9e35bSdanielk1977 pTrig->pNext = pTab->pTrigger; 269bfb9e35bSdanielk1977 pTab->pTrigger = pTrig; 270bfb9e35bSdanielk1977 pTrig = 0; 271c3f9bad2Sdanielk1977 } 272c3f9bad2Sdanielk1977 273f0f258b1Sdrh triggerfinish_cleanup: 274bfb9e35bSdanielk1977 sqlite3DeleteTrigger(pTrig); 275bfb9e35bSdanielk1977 assert( !pParse->pNewTrigger ); 2764adee20fSdanielk1977 sqlite3DeleteTriggerStep(pStepList); 277c3f9bad2Sdanielk1977 } 2784b59ab5eSdrh 2794b59ab5eSdrh /* 2804b59ab5eSdrh ** Make a copy of all components of the given trigger step. This has 2814b59ab5eSdrh ** the effect of copying all Expr.token.z values into memory obtained 2824b59ab5eSdrh ** from sqliteMalloc(). As initially created, the Expr.token.z values 2834b59ab5eSdrh ** all point to the input string that was fed to the parser. But that 2846f8a503dSdanielk1977 ** string is ephemeral - it will go away as soon as the sqlite3_exec() 2854b59ab5eSdrh ** call that started the parser exits. This routine makes a persistent 2864b59ab5eSdrh ** copy of all the Expr.token.z strings so that the TriggerStep structure 2876f8a503dSdanielk1977 ** will be valid even after the sqlite3_exec() call returns. 2884b59ab5eSdrh */ 2894b59ab5eSdrh static void sqlitePersistTriggerStep(TriggerStep *p){ 2904b59ab5eSdrh if( p->target.z ){ 2912646da7eSdrh p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n); 2924b59ab5eSdrh p->target.dyn = 1; 2934b59ab5eSdrh } 2944b59ab5eSdrh if( p->pSelect ){ 2954adee20fSdanielk1977 Select *pNew = sqlite3SelectDup(p->pSelect); 2964adee20fSdanielk1977 sqlite3SelectDelete(p->pSelect); 2974b59ab5eSdrh p->pSelect = pNew; 2984b59ab5eSdrh } 2994b59ab5eSdrh if( p->pWhere ){ 3004adee20fSdanielk1977 Expr *pNew = sqlite3ExprDup(p->pWhere); 3014adee20fSdanielk1977 sqlite3ExprDelete(p->pWhere); 3024b59ab5eSdrh p->pWhere = pNew; 3034b59ab5eSdrh } 3044b59ab5eSdrh if( p->pExprList ){ 3054adee20fSdanielk1977 ExprList *pNew = sqlite3ExprListDup(p->pExprList); 3064adee20fSdanielk1977 sqlite3ExprListDelete(p->pExprList); 3074b59ab5eSdrh p->pExprList = pNew; 3084b59ab5eSdrh } 3094b59ab5eSdrh if( p->pIdList ){ 3104adee20fSdanielk1977 IdList *pNew = sqlite3IdListDup(p->pIdList); 3114adee20fSdanielk1977 sqlite3IdListDelete(p->pIdList); 3124b59ab5eSdrh p->pIdList = pNew; 313c3f9bad2Sdanielk1977 } 314c3f9bad2Sdanielk1977 } 315c3f9bad2Sdanielk1977 316c977f7f5Sdrh /* 317c977f7f5Sdrh ** Turn a SELECT statement (that the pSelect parameter points to) into 318c977f7f5Sdrh ** a trigger step. Return a pointer to a TriggerStep structure. 319c977f7f5Sdrh ** 320c977f7f5Sdrh ** The parser calls this routine when it finds a SELECT statement in 321c977f7f5Sdrh ** body of a TRIGGER. 322c977f7f5Sdrh */ 3234adee20fSdanielk1977 TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ 324633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 3252e588c75Sdanielk1977 if( pTriggerStep==0 ) { 3262e588c75Sdanielk1977 sqlite3SelectDelete(pSelect); 3272e588c75Sdanielk1977 return 0; 3282e588c75Sdanielk1977 } 329c3f9bad2Sdanielk1977 330633ed08dSdanielk1977 pTriggerStep->op = TK_SELECT; 331633ed08dSdanielk1977 pTriggerStep->pSelect = pSelect; 332633ed08dSdanielk1977 pTriggerStep->orconf = OE_Default; 3334b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 334c3f9bad2Sdanielk1977 335633ed08dSdanielk1977 return pTriggerStep; 336c3f9bad2Sdanielk1977 } 337c3f9bad2Sdanielk1977 338c977f7f5Sdrh /* 339c977f7f5Sdrh ** Build a trigger step out of an INSERT statement. Return a pointer 340c977f7f5Sdrh ** to the new trigger step. 341c977f7f5Sdrh ** 342c977f7f5Sdrh ** The parser calls this routine when it sees an INSERT inside the 343c977f7f5Sdrh ** body of a trigger. 344c977f7f5Sdrh */ 3454adee20fSdanielk1977 TriggerStep *sqlite3TriggerInsertStep( 346c977f7f5Sdrh Token *pTableName, /* Name of the table into which we insert */ 347c977f7f5Sdrh IdList *pColumn, /* List of columns in pTableName to insert into */ 348c977f7f5Sdrh ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ 349c977f7f5Sdrh Select *pSelect, /* A SELECT statement that supplies values */ 350c977f7f5Sdrh int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ 351633ed08dSdanielk1977 ){ 352633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 353c3f9bad2Sdanielk1977 354633ed08dSdanielk1977 assert(pEList == 0 || pSelect == 0); 355633ed08dSdanielk1977 assert(pEList != 0 || pSelect != 0); 356c3f9bad2Sdanielk1977 357d5d56523Sdanielk1977 if( pTriggerStep ){ 358633ed08dSdanielk1977 pTriggerStep->op = TK_INSERT; 359633ed08dSdanielk1977 pTriggerStep->pSelect = pSelect; 360633ed08dSdanielk1977 pTriggerStep->target = *pTableName; 361633ed08dSdanielk1977 pTriggerStep->pIdList = pColumn; 362633ed08dSdanielk1977 pTriggerStep->pExprList = pEList; 363633ed08dSdanielk1977 pTriggerStep->orconf = orconf; 3644b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 365d5d56523Sdanielk1977 }else{ 366d5d56523Sdanielk1977 sqlite3IdListDelete(pColumn); 367d5d56523Sdanielk1977 sqlite3ExprListDelete(pEList); 368d5d56523Sdanielk1977 sqlite3SelectDup(pSelect); 369d5d56523Sdanielk1977 } 370c3f9bad2Sdanielk1977 371633ed08dSdanielk1977 return pTriggerStep; 372c3f9bad2Sdanielk1977 } 373c3f9bad2Sdanielk1977 374c977f7f5Sdrh /* 375c977f7f5Sdrh ** Construct a trigger step that implements an UPDATE statement and return 376c977f7f5Sdrh ** a pointer to that trigger step. The parser calls this routine when it 377c977f7f5Sdrh ** sees an UPDATE statement inside the body of a CREATE TRIGGER. 378c977f7f5Sdrh */ 3794adee20fSdanielk1977 TriggerStep *sqlite3TriggerUpdateStep( 380c977f7f5Sdrh Token *pTableName, /* Name of the table to be updated */ 381c977f7f5Sdrh ExprList *pEList, /* The SET clause: list of column and new values */ 382c977f7f5Sdrh Expr *pWhere, /* The WHERE clause */ 383c977f7f5Sdrh int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ 384c977f7f5Sdrh ){ 385633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 386e4697f5eSdrh if( pTriggerStep==0 ) return 0; 387c3f9bad2Sdanielk1977 388633ed08dSdanielk1977 pTriggerStep->op = TK_UPDATE; 389633ed08dSdanielk1977 pTriggerStep->target = *pTableName; 390633ed08dSdanielk1977 pTriggerStep->pExprList = pEList; 391633ed08dSdanielk1977 pTriggerStep->pWhere = pWhere; 392633ed08dSdanielk1977 pTriggerStep->orconf = orconf; 3934b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 394c3f9bad2Sdanielk1977 395633ed08dSdanielk1977 return pTriggerStep; 396c3f9bad2Sdanielk1977 } 397c3f9bad2Sdanielk1977 398c977f7f5Sdrh /* 399c977f7f5Sdrh ** Construct a trigger step that implements a DELETE statement and return 400c977f7f5Sdrh ** a pointer to that trigger step. The parser calls this routine when it 401c977f7f5Sdrh ** sees a DELETE statement inside the body of a CREATE TRIGGER. 402c977f7f5Sdrh */ 4034adee20fSdanielk1977 TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){ 404633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 405e4697f5eSdrh if( pTriggerStep==0 ) return 0; 406c3f9bad2Sdanielk1977 407633ed08dSdanielk1977 pTriggerStep->op = TK_DELETE; 408633ed08dSdanielk1977 pTriggerStep->target = *pTableName; 409633ed08dSdanielk1977 pTriggerStep->pWhere = pWhere; 410633ed08dSdanielk1977 pTriggerStep->orconf = OE_Default; 4114b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 412c3f9bad2Sdanielk1977 413633ed08dSdanielk1977 return pTriggerStep; 414c3f9bad2Sdanielk1977 } 415c3f9bad2Sdanielk1977 416c3f9bad2Sdanielk1977 /* 417633ed08dSdanielk1977 ** Recursively delete a Trigger structure 418c3f9bad2Sdanielk1977 */ 4194adee20fSdanielk1977 void sqlite3DeleteTrigger(Trigger *pTrigger){ 420f0f258b1Sdrh if( pTrigger==0 ) return; 4214adee20fSdanielk1977 sqlite3DeleteTriggerStep(pTrigger->step_list); 422633ed08dSdanielk1977 sqliteFree(pTrigger->name); 423633ed08dSdanielk1977 sqliteFree(pTrigger->table); 4244adee20fSdanielk1977 sqlite3ExprDelete(pTrigger->pWhen); 4254adee20fSdanielk1977 sqlite3IdListDelete(pTrigger->pColumns); 4264312db55Sdrh if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z); 427633ed08dSdanielk1977 sqliteFree(pTrigger); 428633ed08dSdanielk1977 } 429633ed08dSdanielk1977 430633ed08dSdanielk1977 /* 4318a41449eSdanielk1977 ** This function is called to drop a trigger from the database schema. 4328a41449eSdanielk1977 ** 4338a41449eSdanielk1977 ** This may be called directly from the parser and therefore identifies 4348a41449eSdanielk1977 ** the trigger by name. The sqlite3DropTriggerPtr() routine does the 4358a41449eSdanielk1977 ** same job as this routine except it takes a pointer to the trigger 4368a41449eSdanielk1977 ** instead of the trigger name. 4378a41449eSdanielk1977 **/ 4384adee20fSdanielk1977 void sqlite3DropTrigger(Parse *pParse, SrcList *pName){ 439742f947bSdanielk1977 Trigger *pTrigger = 0; 440d24cc427Sdrh int i; 441d24cc427Sdrh const char *zDb; 442d24cc427Sdrh const char *zName; 443d24cc427Sdrh int nName; 4449bb575fdSdrh sqlite3 *db = pParse->db; 445633ed08dSdanielk1977 4469e12800dSdanielk1977 if( sqlite3MallocFailed() ) goto drop_trigger_cleanup; 4478a41449eSdanielk1977 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ 448c0391398Sdanielk1977 goto drop_trigger_cleanup; 449c0391398Sdanielk1977 } 4508e227875Sdanielk1977 451d24cc427Sdrh assert( pName->nSrc==1 ); 452d24cc427Sdrh zDb = pName->a[0].zDatabase; 453d24cc427Sdrh zName = pName->a[0].zName; 454d24cc427Sdrh nName = strlen(zName); 45553c0f748Sdanielk1977 for(i=OMIT_TEMPDB; i<db->nDb; i++){ 456812d7a21Sdrh int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ 4574adee20fSdanielk1977 if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; 458da184236Sdanielk1977 pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName+1); 459d24cc427Sdrh if( pTrigger ) break; 460c3f9bad2Sdanielk1977 } 461d24cc427Sdrh if( !pTrigger ){ 4624adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); 463d24cc427Sdrh goto drop_trigger_cleanup; 464d24cc427Sdrh } 46574161705Sdrh sqlite3DropTriggerPtr(pParse, pTrigger); 46679a519c0Sdrh 46779a519c0Sdrh drop_trigger_cleanup: 4684adee20fSdanielk1977 sqlite3SrcListDelete(pName); 46979a519c0Sdrh } 47079a519c0Sdrh 47179a519c0Sdrh /* 472956bc92cSdrh ** Return a pointer to the Table structure for the table that a trigger 473956bc92cSdrh ** is set on. 474956bc92cSdrh */ 47574161705Sdrh static Table *tableOfTrigger(Trigger *pTrigger){ 476aaf22685Sdanielk1977 int n = strlen(pTrigger->table) + 1; 477aaf22685Sdanielk1977 return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); 478956bc92cSdrh } 479956bc92cSdrh 480956bc92cSdrh 481956bc92cSdrh /* 48274161705Sdrh ** Drop a trigger given a pointer to that trigger. 48379a519c0Sdrh */ 48474161705Sdrh void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ 48579a519c0Sdrh Table *pTable; 48679a519c0Sdrh Vdbe *v; 4879bb575fdSdrh sqlite3 *db = pParse->db; 488956bc92cSdrh int iDb; 48979a519c0Sdrh 490da184236Sdanielk1977 iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); 491956bc92cSdrh assert( iDb>=0 && iDb<db->nDb ); 49274161705Sdrh pTable = tableOfTrigger(pTrigger); 493ed6c8671Sdrh assert( pTable ); 494da184236Sdanielk1977 assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); 495e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 496e5f9c644Sdrh { 497e5f9c644Sdrh int code = SQLITE_DROP_TRIGGER; 498956bc92cSdrh const char *zDb = db->aDb[iDb].zName; 499956bc92cSdrh const char *zTab = SCHEMA_TABLE(iDb); 500956bc92cSdrh if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; 5014adee20fSdanielk1977 if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || 5024adee20fSdanielk1977 sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ 50379a519c0Sdrh return; 504ed6c8671Sdrh } 505e5f9c644Sdrh } 506e5f9c644Sdrh #endif 507c3f9bad2Sdanielk1977 508f0f258b1Sdrh /* Generate code to destroy the database record of the trigger. 509f0f258b1Sdrh */ 51043617e9aSdrh assert( pTable!=0 ); 51143617e9aSdrh if( (v = sqlite3GetVdbe(pParse))!=0 ){ 512f0f258b1Sdrh int base; 5135719628aSdrh static const VdbeOpList dropTrigger[] = { 5149b1b01bbSdrh { OP_Rewind, 0, ADDR(9), 0}, 5150f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0}, /* 1 */ 516f0f258b1Sdrh { OP_Column, 0, 1, 0}, 5179b1b01bbSdrh { OP_Ne, 0, ADDR(8), 0}, 5180f69c1e3Sdanielk1977 { OP_String8, 0, 0, "trigger"}, 5199b1b01bbSdrh { OP_Column, 0, 0, 0}, 5209b1b01bbSdrh { OP_Ne, 0, ADDR(8), 0}, 521f0f258b1Sdrh { OP_Delete, 0, 0, 0}, 5229b1b01bbSdrh { OP_Next, 0, ADDR(1), 0}, /* 8 */ 523f0f258b1Sdrh }; 524f0f258b1Sdrh 525956bc92cSdrh sqlite3BeginWriteOperation(pParse, 0, iDb); 526c00da105Sdanielk1977 sqlite3OpenMasterTable(pParse, iDb); 5274adee20fSdanielk1977 base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); 5284adee20fSdanielk1977 sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); 529956bc92cSdrh sqlite3ChangeCookie(db, v, iDb); 5304adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, 0, 0); 531956bc92cSdrh sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); 532956bc92cSdrh } 533f0f258b1Sdrh } 534f0f258b1Sdrh 535c3f9bad2Sdanielk1977 /* 536956bc92cSdrh ** Remove a trigger from the hash tables of the sqlite* pointer. 537c3f9bad2Sdanielk1977 */ 538956bc92cSdrh void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ 539956bc92cSdrh Trigger *pTrigger; 54079a519c0Sdrh int nName = strlen(zName); 541da184236Sdanielk1977 pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash), zName, nName+1, 0); 542956bc92cSdrh if( pTrigger ){ 54374161705Sdrh Table *pTable = tableOfTrigger(pTrigger); 544956bc92cSdrh assert( pTable!=0 ); 545633ed08dSdanielk1977 if( pTable->pTrigger == pTrigger ){ 546633ed08dSdanielk1977 pTable->pTrigger = pTrigger->pNext; 547633ed08dSdanielk1977 }else{ 548633ed08dSdanielk1977 Trigger *cc = pTable->pTrigger; 549c3f9bad2Sdanielk1977 while( cc ){ 550633ed08dSdanielk1977 if( cc->pNext == pTrigger ){ 551c3f9bad2Sdanielk1977 cc->pNext = cc->pNext->pNext; 552c3f9bad2Sdanielk1977 break; 553c3f9bad2Sdanielk1977 } 554c3f9bad2Sdanielk1977 cc = cc->pNext; 555c3f9bad2Sdanielk1977 } 556c3f9bad2Sdanielk1977 assert(cc); 557c3f9bad2Sdanielk1977 } 5584adee20fSdanielk1977 sqlite3DeleteTrigger(pTrigger); 559956bc92cSdrh db->flags |= SQLITE_InternChanges; 560c3f9bad2Sdanielk1977 } 561c3f9bad2Sdanielk1977 } 562c3f9bad2Sdanielk1977 563c977f7f5Sdrh /* 564c977f7f5Sdrh ** pEList is the SET clause of an UPDATE statement. Each entry 565c977f7f5Sdrh ** in pEList is of the format <id>=<expr>. If any of the entries 566c977f7f5Sdrh ** in pEList have an <id> which matches an identifier in pIdList, 567c977f7f5Sdrh ** then return TRUE. If pIdList==NULL, then it is considered a 568c977f7f5Sdrh ** wildcard that matches anything. Likewise if pEList==NULL then 569c977f7f5Sdrh ** it matches anything so always return true. Return false only 570c977f7f5Sdrh ** if there is no match. 571c977f7f5Sdrh */ 572c977f7f5Sdrh static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ 573ad2d8307Sdrh int e; 574ad2d8307Sdrh if( !pIdList || !pEList ) return 1; 575f29ce559Sdanielk1977 for(e=0; e<pEList->nExpr; e++){ 5764adee20fSdanielk1977 if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; 577f29ce559Sdanielk1977 } 578c3f9bad2Sdanielk1977 return 0; 579c3f9bad2Sdanielk1977 } 580c3f9bad2Sdanielk1977 581c3f9bad2Sdanielk1977 /* 582dca76841Sdrh ** Return a bit vector to indicate what kind of triggers exist for operation 583dca76841Sdrh ** "op" on table pTab. If pChanges is not NULL then it is a list of columns 584dca76841Sdrh ** that are being updated. Triggers only match if the ON clause of the 585dca76841Sdrh ** trigger definition overlaps the set of columns being updated. 586dca76841Sdrh ** 587dca76841Sdrh ** The returned bit vector is some combination of TRIGGER_BEFORE and 588dca76841Sdrh ** TRIGGER_AFTER. 589c3f9bad2Sdanielk1977 */ 5904adee20fSdanielk1977 int sqlite3TriggersExist( 591c977f7f5Sdrh Parse *pParse, /* Used to check for recursive triggers */ 592dca76841Sdrh Table *pTab, /* The table the contains the triggers */ 593c3f9bad2Sdanielk1977 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ 594c977f7f5Sdrh ExprList *pChanges /* Columns that change in an UPDATE statement */ 595c977f7f5Sdrh ){ 596dca76841Sdrh Trigger *pTrigger = pTab->pTrigger; 597dca76841Sdrh int mask = 0; 598c3f9bad2Sdanielk1977 599dca76841Sdrh while( pTrigger ){ 600dca76841Sdrh if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){ 601dca76841Sdrh mask |= pTrigger->tr_tm; 602c3f9bad2Sdanielk1977 } 603dca76841Sdrh pTrigger = pTrigger->pNext; 604dca76841Sdrh } 605dca76841Sdrh return mask; 606c3f9bad2Sdanielk1977 } 607c3f9bad2Sdanielk1977 608c977f7f5Sdrh /* 609f26e09c8Sdrh ** Convert the pStep->target token into a SrcList and return a pointer 610f26e09c8Sdrh ** to that SrcList. 611f26e09c8Sdrh ** 612f26e09c8Sdrh ** This routine adds a specific database name, if needed, to the target when 613f26e09c8Sdrh ** forming the SrcList. This prevents a trigger in one database from 614f26e09c8Sdrh ** referring to a target in another database. An exception is when the 615f26e09c8Sdrh ** trigger is in TEMP in which case it can refer to any other database it 616f26e09c8Sdrh ** wants. 617f26e09c8Sdrh */ 618f26e09c8Sdrh static SrcList *targetSrcList( 619f26e09c8Sdrh Parse *pParse, /* The parsing context */ 620f26e09c8Sdrh TriggerStep *pStep /* The trigger containing the target token */ 621f26e09c8Sdrh ){ 622f26e09c8Sdrh Token sDb; /* Dummy database name token */ 623f26e09c8Sdrh int iDb; /* Index of the database to use */ 624f26e09c8Sdrh SrcList *pSrc; /* SrcList to be returned */ 625f26e09c8Sdrh 626da184236Sdanielk1977 iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); 627f26e09c8Sdrh if( iDb==0 || iDb>=2 ){ 628f26e09c8Sdrh assert( iDb<pParse->db->nDb ); 6292646da7eSdrh sDb.z = (u8*)pParse->db->aDb[iDb].zName; 6302646da7eSdrh sDb.n = strlen((char*)sDb.z); 6314adee20fSdanielk1977 pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target); 632f26e09c8Sdrh } else { 6334adee20fSdanielk1977 pSrc = sqlite3SrcListAppend(0, &pStep->target, 0); 634f26e09c8Sdrh } 635f26e09c8Sdrh return pSrc; 636f26e09c8Sdrh } 637f26e09c8Sdrh 638f26e09c8Sdrh /* 639c977f7f5Sdrh ** Generate VDBE code for zero or more statements inside the body of a 640c977f7f5Sdrh ** trigger. 641c977f7f5Sdrh */ 642c3f9bad2Sdanielk1977 static int codeTriggerProgram( 643c977f7f5Sdrh Parse *pParse, /* The parser context */ 644c977f7f5Sdrh TriggerStep *pStepList, /* List of statements inside the trigger body */ 645c977f7f5Sdrh int orconfin /* Conflict algorithm. (OE_Abort, etc) */ 646633ed08dSdanielk1977 ){ 647633ed08dSdanielk1977 TriggerStep * pTriggerStep = pStepList; 648c3f9bad2Sdanielk1977 int orconf; 649344737f6Sdrh Vdbe *v = pParse->pVdbe; 650c3f9bad2Sdanielk1977 651344737f6Sdrh assert( pTriggerStep!=0 ); 652344737f6Sdrh assert( v!=0 ); 653344737f6Sdrh sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); 65467040462Sdrh VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name)); 655633ed08dSdanielk1977 while( pTriggerStep ){ 656633ed08dSdanielk1977 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; 657c3f9bad2Sdanielk1977 pParse->trigStack->orconf = orconf; 658633ed08dSdanielk1977 switch( pTriggerStep->op ){ 659c3f9bad2Sdanielk1977 case TK_SELECT: { 6604adee20fSdanielk1977 Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); 6616f34903eSdanielk1977 assert(ss); 6626f34903eSdanielk1977 assert(ss->pSrc); 663b3bce662Sdanielk1977 sqlite3SelectResolve(pParse, ss, 0); 664b3bce662Sdanielk1977 sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); 6654adee20fSdanielk1977 sqlite3SelectDelete(ss); 666c3f9bad2Sdanielk1977 break; 667c3f9bad2Sdanielk1977 } 668c3f9bad2Sdanielk1977 case TK_UPDATE: { 669113088ecSdrh SrcList *pSrc; 670f26e09c8Sdrh pSrc = targetSrcList(pParse, pTriggerStep); 671344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); 6724adee20fSdanielk1977 sqlite3Update(pParse, pSrc, 6734adee20fSdanielk1977 sqlite3ExprListDup(pTriggerStep->pExprList), 6744adee20fSdanielk1977 sqlite3ExprDup(pTriggerStep->pWhere), orconf); 675344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); 676c3f9bad2Sdanielk1977 break; 677c3f9bad2Sdanielk1977 } 678c3f9bad2Sdanielk1977 case TK_INSERT: { 679113088ecSdrh SrcList *pSrc; 680f26e09c8Sdrh pSrc = targetSrcList(pParse, pTriggerStep); 681344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); 6824adee20fSdanielk1977 sqlite3Insert(pParse, pSrc, 6834adee20fSdanielk1977 sqlite3ExprListDup(pTriggerStep->pExprList), 6844adee20fSdanielk1977 sqlite3SelectDup(pTriggerStep->pSelect), 6854adee20fSdanielk1977 sqlite3IdListDup(pTriggerStep->pIdList), orconf); 686344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); 687c3f9bad2Sdanielk1977 break; 688c3f9bad2Sdanielk1977 } 689c3f9bad2Sdanielk1977 case TK_DELETE: { 690113088ecSdrh SrcList *pSrc; 691344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); 692f26e09c8Sdrh pSrc = targetSrcList(pParse, pTriggerStep); 6934adee20fSdanielk1977 sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere)); 694344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); 695c3f9bad2Sdanielk1977 break; 696c3f9bad2Sdanielk1977 } 697c3f9bad2Sdanielk1977 default: 698c3f9bad2Sdanielk1977 assert(0); 699c3f9bad2Sdanielk1977 } 700633ed08dSdanielk1977 pTriggerStep = pTriggerStep->pNext; 701c3f9bad2Sdanielk1977 } 702344737f6Sdrh sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); 70367040462Sdrh VdbeComment((v, "# end trigger %s", pStepList->pTrig->name)); 704c3f9bad2Sdanielk1977 705c3f9bad2Sdanielk1977 return 0; 706c3f9bad2Sdanielk1977 } 707c3f9bad2Sdanielk1977 708633ed08dSdanielk1977 /* 709633ed08dSdanielk1977 ** This is called to code FOR EACH ROW triggers. 710633ed08dSdanielk1977 ** 711633ed08dSdanielk1977 ** When the code that this function generates is executed, the following 712633ed08dSdanielk1977 ** must be true: 713c977f7f5Sdrh ** 714c977f7f5Sdrh ** 1. No cursors may be open in the main database. (But newIdx and oldIdx 715c977f7f5Sdrh ** can be indices of cursors in temporary tables. See below.) 716c977f7f5Sdrh ** 717633ed08dSdanielk1977 ** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then 718633ed08dSdanielk1977 ** a temporary vdbe cursor (index newIdx) must be open and pointing at 719633ed08dSdanielk1977 ** a row containing values to be substituted for new.* expressions in the 720633ed08dSdanielk1977 ** trigger program(s). 721c977f7f5Sdrh ** 722633ed08dSdanielk1977 ** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then 723633ed08dSdanielk1977 ** a temporary vdbe cursor (index oldIdx) must be open and pointing at 724633ed08dSdanielk1977 ** a row containing values to be substituted for old.* expressions in the 725633ed08dSdanielk1977 ** trigger program(s). 726633ed08dSdanielk1977 ** 727633ed08dSdanielk1977 */ 7284adee20fSdanielk1977 int sqlite3CodeRowTrigger( 729c3f9bad2Sdanielk1977 Parse *pParse, /* Parse context */ 730c3f9bad2Sdanielk1977 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ 731633ed08dSdanielk1977 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ 732dca76841Sdrh int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ 733633ed08dSdanielk1977 Table *pTab, /* The table to code triggers from */ 734633ed08dSdanielk1977 int newIdx, /* The indice of the "new" row to access */ 735633ed08dSdanielk1977 int oldIdx, /* The indice of the "old" row to access */ 7366f34903eSdanielk1977 int orconf, /* ON CONFLICT policy */ 7376f34903eSdanielk1977 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ 738c977f7f5Sdrh ){ 739eecfb3eeSdanielk1977 Trigger *p; 74067040462Sdrh TriggerStack trigStackEntry; 741c3f9bad2Sdanielk1977 742c3f9bad2Sdanielk1977 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); 743dca76841Sdrh assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); 744c3f9bad2Sdanielk1977 745633ed08dSdanielk1977 assert(newIdx != -1 || oldIdx != -1); 746c3f9bad2Sdanielk1977 747eecfb3eeSdanielk1977 for(p=pTab->pTrigger; p; p=p->pNext){ 748c3f9bad2Sdanielk1977 int fire_this = 0; 749c3f9bad2Sdanielk1977 750eecfb3eeSdanielk1977 /* Determine whether we should code this trigger */ 751eecfb3eeSdanielk1977 if( 752eecfb3eeSdanielk1977 p->op==op && 753eecfb3eeSdanielk1977 p->tr_tm==tr_tm && 754eecfb3eeSdanielk1977 (p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) && 755eecfb3eeSdanielk1977 (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) 756eecfb3eeSdanielk1977 ){ 757eecfb3eeSdanielk1977 TriggerStack *pS; /* Pointer to trigger-stack entry */ 75874161705Sdrh for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){} 759eecfb3eeSdanielk1977 if( !pS ){ 760c3f9bad2Sdanielk1977 fire_this = 1; 761c3f9bad2Sdanielk1977 } 762*229caa36Sdrh #if 0 /* Give no warning for recursive triggers. Just do not do them */ 763*229caa36Sdrh else{ 764*229caa36Sdrh sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)", 765*229caa36Sdrh p->name); 766*229caa36Sdrh return SQLITE_ERROR; 767*229caa36Sdrh } 768*229caa36Sdrh #endif 769f29ce559Sdanielk1977 } 770c3f9bad2Sdanielk1977 77167040462Sdrh if( fire_this ){ 772c3f9bad2Sdanielk1977 int endTrigger; 773c3f9bad2Sdanielk1977 Expr * whenExpr; 77485e2096fSdrh AuthContext sContext; 775b3bce662Sdanielk1977 NameContext sNC; 776c3f9bad2Sdanielk1977 777b3bce662Sdanielk1977 memset(&sNC, 0, sizeof(sNC)); 778b3bce662Sdanielk1977 sNC.pParse = pParse; 779c3f9bad2Sdanielk1977 780c3f9bad2Sdanielk1977 /* Push an entry on to the trigger stack */ 781eecfb3eeSdanielk1977 trigStackEntry.pTrigger = p; 78267040462Sdrh trigStackEntry.newIdx = newIdx; 78367040462Sdrh trigStackEntry.oldIdx = oldIdx; 78467040462Sdrh trigStackEntry.pTab = pTab; 78567040462Sdrh trigStackEntry.pNext = pParse->trigStack; 78667040462Sdrh trigStackEntry.ignoreJump = ignoreJump; 78767040462Sdrh pParse->trigStack = &trigStackEntry; 788eecfb3eeSdanielk1977 sqlite3AuthContextPush(pParse, &sContext, p->name); 789c3f9bad2Sdanielk1977 790c3f9bad2Sdanielk1977 /* code the WHEN clause */ 7914adee20fSdanielk1977 endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); 792eecfb3eeSdanielk1977 whenExpr = sqlite3ExprDup(p->pWhen); 793b3bce662Sdanielk1977 if( sqlite3ExprResolveNames(&sNC, whenExpr) ){ 79467040462Sdrh pParse->trigStack = trigStackEntry.pNext; 7954adee20fSdanielk1977 sqlite3ExprDelete(whenExpr); 796c3f9bad2Sdanielk1977 return 1; 797c3f9bad2Sdanielk1977 } 7984adee20fSdanielk1977 sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); 7994adee20fSdanielk1977 sqlite3ExprDelete(whenExpr); 800c3f9bad2Sdanielk1977 801eecfb3eeSdanielk1977 codeTriggerProgram(pParse, p->step_list, orconf); 802c3f9bad2Sdanielk1977 803c3f9bad2Sdanielk1977 /* Pop the entry off the trigger stack */ 80467040462Sdrh pParse->trigStack = trigStackEntry.pNext; 8054adee20fSdanielk1977 sqlite3AuthContextPop(&sContext); 806c3f9bad2Sdanielk1977 8074adee20fSdanielk1977 sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); 808c3f9bad2Sdanielk1977 } 809c3f9bad2Sdanielk1977 } 810c3f9bad2Sdanielk1977 return 0; 811c3f9bad2Sdanielk1977 } 812b7f9164eSdrh #endif /* !defined(SQLITE_OMIT_TRIGGER) */ 813