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 */ 52fdd48a76Sdrh int isTemp, /* True if the TEMPORARY keyword is present */ 53fdd48a76Sdrh int noErr /* Suppress errors if the trigger already exists */ 549adf9ac4Sdrh ){ 55d5d56523Sdanielk1977 Trigger *pTrigger = 0; 56ef2cb63eSdanielk1977 Table *pTab; 57e5f9c644Sdrh char *zName = 0; /* Name of the trigger */ 589bb575fdSdrh sqlite3 *db = pParse->db; 59ef2cb63eSdanielk1977 int iDb; /* The database to store the trigger in */ 60ef2cb63eSdanielk1977 Token *pName; /* The unqualified db name */ 614312db55Sdrh DbFixer sFix; 62da184236Sdanielk1977 int iTabDb; 63ed6c8671Sdrh 6443617e9aSdrh assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */ 6543617e9aSdrh assert( pName2!=0 ); 66ef2cb63eSdanielk1977 if( isTemp ){ 67ef2cb63eSdanielk1977 /* If TEMP was specified, then the trigger name may not be qualified. */ 6843617e9aSdrh if( pName2->n>0 ){ 69ef2cb63eSdanielk1977 sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name"); 70ef2cb63eSdanielk1977 goto trigger_cleanup; 71ef2cb63eSdanielk1977 } 72ef2cb63eSdanielk1977 iDb = 1; 73ef2cb63eSdanielk1977 pName = pName1; 74ef2cb63eSdanielk1977 }else{ 75ef2cb63eSdanielk1977 /* Figure out the db that the the trigger will be created in */ 76ef2cb63eSdanielk1977 iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); 77ef2cb63eSdanielk1977 if( iDb<0 ){ 78ef2cb63eSdanielk1977 goto trigger_cleanup; 79ef2cb63eSdanielk1977 } 80ef2cb63eSdanielk1977 } 81ef2cb63eSdanielk1977 82ef2cb63eSdanielk1977 /* If the trigger name was unqualified, and the table is a temp table, 83ef2cb63eSdanielk1977 ** then set iDb to 1 to create the trigger in the temporary database. 84ef2cb63eSdanielk1977 ** If sqlite3SrcListLookup() returns 0, indicating the table does not 85ef2cb63eSdanielk1977 ** exist, the error is caught by the block below. 86c3f9bad2Sdanielk1977 */ 879e12800dSdanielk1977 if( !pTableName || sqlite3MallocFailed() ){ 886f7adc8aSdrh goto trigger_cleanup; 896f7adc8aSdrh } 90ef2cb63eSdanielk1977 pTab = sqlite3SrcListLookup(pParse, pTableName); 91da184236Sdanielk1977 if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ 92ef2cb63eSdanielk1977 iDb = 1; 93ef2cb63eSdanielk1977 } 94ef2cb63eSdanielk1977 95ef2cb63eSdanielk1977 /* Ensure the table name matches database name and that the table exists */ 969e12800dSdanielk1977 if( sqlite3MallocFailed() ) goto trigger_cleanup; 97d24cc427Sdrh assert( pTableName->nSrc==1 ); 98ef2cb63eSdanielk1977 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) && 99ef2cb63eSdanielk1977 sqlite3FixSrcList(&sFix, pTableName) ){ 1004312db55Sdrh goto trigger_cleanup; 101f26e09c8Sdrh } 102ef2cb63eSdanielk1977 pTab = sqlite3SrcListLookup(pParse, pTableName); 103ef2cb63eSdanielk1977 if( !pTab ){ 104ef2cb63eSdanielk1977 /* The table does not exist. */ 105d24cc427Sdrh goto trigger_cleanup; 106d24cc427Sdrh } 1074cbdda9eSdrh if( IsVirtual(pTab) ){ 1084cbdda9eSdrh sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables"); 1094cbdda9eSdrh goto trigger_cleanup; 1104cbdda9eSdrh } 111d24cc427Sdrh 112d8123366Sdanielk1977 /* Check that the trigger name is not reserved and that no trigger of the 113d8123366Sdanielk1977 ** specified name exists */ 114a99db3b6Sdrh zName = sqlite3NameFromToken(pName); 115d8123366Sdanielk1977 if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ 116d8123366Sdanielk1977 goto trigger_cleanup; 117d8123366Sdanielk1977 } 118e4df0e74Sdrh if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){ 119fdd48a76Sdrh if( !noErr ){ 1204adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); 121fdd48a76Sdrh } 122c3f9bad2Sdanielk1977 goto trigger_cleanup; 123c3f9bad2Sdanielk1977 } 124ef2cb63eSdanielk1977 125ef2cb63eSdanielk1977 /* Do not create a trigger on a system table */ 126dca76841Sdrh if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ 1274adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); 128e0bc4048Sdrh pParse->nErr++; 129e0bc4048Sdrh goto trigger_cleanup; 130e0bc4048Sdrh } 131ef2cb63eSdanielk1977 132ef2cb63eSdanielk1977 /* INSTEAD of triggers are only for views and views only support INSTEAD 133ef2cb63eSdanielk1977 ** of triggers. 134ef2cb63eSdanielk1977 */ 135ef2cb63eSdanielk1977 if( pTab->pSelect && tr_tm!=TK_INSTEAD ){ 1364adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 137da93d238Sdrh (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); 138d702fccbSdanielk1977 goto trigger_cleanup; 139d702fccbSdanielk1977 } 140ef2cb63eSdanielk1977 if( !pTab->pSelect && tr_tm==TK_INSTEAD ){ 1414adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" 142da93d238Sdrh " trigger on table: %S", pTableName, 0); 143d702fccbSdanielk1977 goto trigger_cleanup; 144d702fccbSdanielk1977 } 145da184236Sdanielk1977 iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); 146ef2cb63eSdanielk1977 147e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 148e5f9c644Sdrh { 149e5f9c644Sdrh int code = SQLITE_CREATE_TRIGGER; 150da184236Sdanielk1977 const char *zDb = db->aDb[iTabDb].zName; 151e22a334bSdrh const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; 152da184236Sdanielk1977 if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; 153ef2cb63eSdanielk1977 if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ 154ed6c8671Sdrh goto trigger_cleanup; 155ed6c8671Sdrh } 156da184236Sdanielk1977 if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){ 15777ad4e41Sdrh goto trigger_cleanup; 15877ad4e41Sdrh } 159d702fccbSdanielk1977 } 160e5f9c644Sdrh #endif 161d702fccbSdanielk1977 162ef2cb63eSdanielk1977 /* INSTEAD OF triggers can only appear on views and BEFORE triggers 1635cf590c1Sdrh ** cannot appear on views. So we might as well translate every 1645cf590c1Sdrh ** INSTEAD OF trigger into a BEFORE trigger. It simplifies code 1655cf590c1Sdrh ** elsewhere. 1665cf590c1Sdrh */ 167d702fccbSdanielk1977 if (tr_tm == TK_INSTEAD){ 168d702fccbSdanielk1977 tr_tm = TK_BEFORE; 169c3f9bad2Sdanielk1977 } 170c3f9bad2Sdanielk1977 171c3f9bad2Sdanielk1977 /* Build the Trigger object */ 172ef2cb63eSdanielk1977 pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger)); 173ef2cb63eSdanielk1977 if( pTrigger==0 ) goto trigger_cleanup; 174ef2cb63eSdanielk1977 pTrigger->name = zName; 175e5f9c644Sdrh zName = 0; 176ef2cb63eSdanielk1977 pTrigger->table = sqliteStrDup(pTableName->a[0].zName); 177da184236Sdanielk1977 pTrigger->pSchema = db->aDb[iDb].pSchema; 178aaf22685Sdanielk1977 pTrigger->pTabSchema = pTab->pSchema; 179ef2cb63eSdanielk1977 pTrigger->op = op; 180dca76841Sdrh pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; 181ef2cb63eSdanielk1977 pTrigger->pWhen = sqlite3ExprDup(pWhen); 182ef2cb63eSdanielk1977 pTrigger->pColumns = sqlite3IdListDup(pColumns); 183ef2cb63eSdanielk1977 pTrigger->foreach = foreach; 184ef2cb63eSdanielk1977 sqlite3TokenCopy(&pTrigger->nameToken,pName); 185f0f258b1Sdrh assert( pParse->pNewTrigger==0 ); 186ef2cb63eSdanielk1977 pParse->pNewTrigger = pTrigger; 187f0f258b1Sdrh 188f0f258b1Sdrh trigger_cleanup: 189f0f258b1Sdrh sqliteFree(zName); 1904adee20fSdanielk1977 sqlite3SrcListDelete(pTableName); 1914adee20fSdanielk1977 sqlite3IdListDelete(pColumns); 1924adee20fSdanielk1977 sqlite3ExprDelete(pWhen); 193d5d56523Sdanielk1977 if( !pParse->pNewTrigger ){ 194d5d56523Sdanielk1977 sqlite3DeleteTrigger(pTrigger); 195d5d56523Sdanielk1977 }else{ 196d5d56523Sdanielk1977 assert( pParse->pNewTrigger==pTrigger ); 197d5d56523Sdanielk1977 } 198f0f258b1Sdrh } 199f0f258b1Sdrh 200f0f258b1Sdrh /* 201f0f258b1Sdrh ** This routine is called after all of the trigger actions have been parsed 202f0f258b1Sdrh ** in order to complete the process of building the trigger. 203f0f258b1Sdrh */ 2044adee20fSdanielk1977 void sqlite3FinishTrigger( 205f0f258b1Sdrh Parse *pParse, /* Parser context */ 206f0f258b1Sdrh TriggerStep *pStepList, /* The triggered program */ 207f0f258b1Sdrh Token *pAll /* Token that describes the complete CREATE TRIGGER */ 208f0f258b1Sdrh ){ 209bfb9e35bSdanielk1977 Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ 2109bb575fdSdrh sqlite3 *db = pParse->db; /* The database */ 211f26e09c8Sdrh DbFixer sFix; 212da184236Sdanielk1977 int iDb; /* Database containing the trigger */ 213f0f258b1Sdrh 214bfb9e35bSdanielk1977 pTrig = pParse->pNewTrigger; 215f0f258b1Sdrh pParse->pNewTrigger = 0; 2162e588c75Sdanielk1977 if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup; 217da184236Sdanielk1977 iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); 218bfb9e35bSdanielk1977 pTrig->step_list = pStepList; 219a69d9168Sdrh while( pStepList ){ 220bfb9e35bSdanielk1977 pStepList->pTrig = pTrig; 221a69d9168Sdrh pStepList = pStepList->pNext; 222a69d9168Sdrh } 223da184236Sdanielk1977 if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken) 224bfb9e35bSdanielk1977 && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ 225f26e09c8Sdrh goto triggerfinish_cleanup; 226f26e09c8Sdrh } 227c3f9bad2Sdanielk1977 228c3f9bad2Sdanielk1977 /* if we are not initializing, and this trigger is not on a TEMP table, 2299adf9ac4Sdrh ** build the sqlite_master entry 2309adf9ac4Sdrh */ 2311d85d931Sdrh if( !db->init.busy ){ 2325719628aSdrh static const VdbeOpList insertTrig[] = { 233f0863fe5Sdrh { OP_NewRowid, 0, 0, 0 }, 2340f69c1e3Sdanielk1977 { OP_String8, 0, 0, "trigger" }, 2350f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0 }, /* 2: trigger name */ 2360f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0 }, /* 3: table name */ 237c977f7f5Sdrh { OP_Integer, 0, 0, 0 }, 2380f69c1e3Sdanielk1977 { OP_String8, 0, 0, "CREATE TRIGGER "}, 2390f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0 }, /* 6: SQL */ 240855eb1cfSdrh { OP_Concat, 0, 0, 0 }, 2418a51256cSdrh { OP_MakeRecord, 5, 0, "aaada" }, 242f0863fe5Sdrh { OP_Insert, 0, 0, 0 }, 243c977f7f5Sdrh }; 244c977f7f5Sdrh int addr; 245c977f7f5Sdrh Vdbe *v; 246c3f9bad2Sdanielk1977 247c3f9bad2Sdanielk1977 /* Make an entry in the sqlite_master table */ 2484adee20fSdanielk1977 v = sqlite3GetVdbe(pParse); 249f0f258b1Sdrh if( v==0 ) goto triggerfinish_cleanup; 250da184236Sdanielk1977 sqlite3BeginWriteOperation(pParse, 0, iDb); 251c00da105Sdanielk1977 sqlite3OpenMasterTable(pParse, iDb); 2524adee20fSdanielk1977 addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); 253bfb9e35bSdanielk1977 sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); 254bfb9e35bSdanielk1977 sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); 2552646da7eSdrh sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n); 256da184236Sdanielk1977 sqlite3ChangeCookie(db, v, iDb); 2574adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, 0, 0); 258da184236Sdanielk1977 sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, 259bfb9e35bSdanielk1977 sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC); 260c3f9bad2Sdanielk1977 } 261c3f9bad2Sdanielk1977 262956bc92cSdrh if( db->init.busy ){ 263aaf22685Sdanielk1977 int n; 264f0f258b1Sdrh Table *pTab; 265d5d56523Sdanielk1977 Trigger *pDel; 266da184236Sdanielk1977 pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash, 267e4df0e74Sdrh pTrig->name, strlen(pTrig->name), pTrig); 268d5d56523Sdanielk1977 if( pDel ){ 2699e12800dSdanielk1977 assert( sqlite3MallocFailed() && pDel==pTrig ); 270d5d56523Sdanielk1977 goto triggerfinish_cleanup; 271d5d56523Sdanielk1977 } 272aaf22685Sdanielk1977 n = strlen(pTrig->table) + 1; 273aaf22685Sdanielk1977 pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n); 274f0f258b1Sdrh assert( pTab!=0 ); 275bfb9e35bSdanielk1977 pTrig->pNext = pTab->pTrigger; 276bfb9e35bSdanielk1977 pTab->pTrigger = pTrig; 277bfb9e35bSdanielk1977 pTrig = 0; 278c3f9bad2Sdanielk1977 } 279c3f9bad2Sdanielk1977 280f0f258b1Sdrh triggerfinish_cleanup: 281bfb9e35bSdanielk1977 sqlite3DeleteTrigger(pTrig); 282bfb9e35bSdanielk1977 assert( !pParse->pNewTrigger ); 2834adee20fSdanielk1977 sqlite3DeleteTriggerStep(pStepList); 284c3f9bad2Sdanielk1977 } 2854b59ab5eSdrh 2864b59ab5eSdrh /* 2874b59ab5eSdrh ** Make a copy of all components of the given trigger step. This has 2884b59ab5eSdrh ** the effect of copying all Expr.token.z values into memory obtained 2894b59ab5eSdrh ** from sqliteMalloc(). As initially created, the Expr.token.z values 2904b59ab5eSdrh ** all point to the input string that was fed to the parser. But that 2916f8a503dSdanielk1977 ** string is ephemeral - it will go away as soon as the sqlite3_exec() 2924b59ab5eSdrh ** call that started the parser exits. This routine makes a persistent 2934b59ab5eSdrh ** copy of all the Expr.token.z strings so that the TriggerStep structure 2946f8a503dSdanielk1977 ** will be valid even after the sqlite3_exec() call returns. 2954b59ab5eSdrh */ 2964b59ab5eSdrh static void sqlitePersistTriggerStep(TriggerStep *p){ 2974b59ab5eSdrh if( p->target.z ){ 2982646da7eSdrh p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n); 2994b59ab5eSdrh p->target.dyn = 1; 3004b59ab5eSdrh } 3014b59ab5eSdrh if( p->pSelect ){ 3024adee20fSdanielk1977 Select *pNew = sqlite3SelectDup(p->pSelect); 3034adee20fSdanielk1977 sqlite3SelectDelete(p->pSelect); 3044b59ab5eSdrh p->pSelect = pNew; 3054b59ab5eSdrh } 3064b59ab5eSdrh if( p->pWhere ){ 3074adee20fSdanielk1977 Expr *pNew = sqlite3ExprDup(p->pWhere); 3084adee20fSdanielk1977 sqlite3ExprDelete(p->pWhere); 3094b59ab5eSdrh p->pWhere = pNew; 3104b59ab5eSdrh } 3114b59ab5eSdrh if( p->pExprList ){ 3124adee20fSdanielk1977 ExprList *pNew = sqlite3ExprListDup(p->pExprList); 3134adee20fSdanielk1977 sqlite3ExprListDelete(p->pExprList); 3144b59ab5eSdrh p->pExprList = pNew; 3154b59ab5eSdrh } 3164b59ab5eSdrh if( p->pIdList ){ 3174adee20fSdanielk1977 IdList *pNew = sqlite3IdListDup(p->pIdList); 3184adee20fSdanielk1977 sqlite3IdListDelete(p->pIdList); 3194b59ab5eSdrh p->pIdList = pNew; 320c3f9bad2Sdanielk1977 } 321c3f9bad2Sdanielk1977 } 322c3f9bad2Sdanielk1977 323c977f7f5Sdrh /* 324c977f7f5Sdrh ** Turn a SELECT statement (that the pSelect parameter points to) into 325c977f7f5Sdrh ** a trigger step. Return a pointer to a TriggerStep structure. 326c977f7f5Sdrh ** 327c977f7f5Sdrh ** The parser calls this routine when it finds a SELECT statement in 328c977f7f5Sdrh ** body of a TRIGGER. 329c977f7f5Sdrh */ 3304adee20fSdanielk1977 TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){ 331633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 3322e588c75Sdanielk1977 if( pTriggerStep==0 ) { 3332e588c75Sdanielk1977 sqlite3SelectDelete(pSelect); 3342e588c75Sdanielk1977 return 0; 3352e588c75Sdanielk1977 } 336c3f9bad2Sdanielk1977 337633ed08dSdanielk1977 pTriggerStep->op = TK_SELECT; 338633ed08dSdanielk1977 pTriggerStep->pSelect = pSelect; 339633ed08dSdanielk1977 pTriggerStep->orconf = OE_Default; 3404b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 341c3f9bad2Sdanielk1977 342633ed08dSdanielk1977 return pTriggerStep; 343c3f9bad2Sdanielk1977 } 344c3f9bad2Sdanielk1977 345c977f7f5Sdrh /* 346c977f7f5Sdrh ** Build a trigger step out of an INSERT statement. Return a pointer 347c977f7f5Sdrh ** to the new trigger step. 348c977f7f5Sdrh ** 349c977f7f5Sdrh ** The parser calls this routine when it sees an INSERT inside the 350c977f7f5Sdrh ** body of a trigger. 351c977f7f5Sdrh */ 3524adee20fSdanielk1977 TriggerStep *sqlite3TriggerInsertStep( 353c977f7f5Sdrh Token *pTableName, /* Name of the table into which we insert */ 354c977f7f5Sdrh IdList *pColumn, /* List of columns in pTableName to insert into */ 355c977f7f5Sdrh ExprList *pEList, /* The VALUE clause: a list of values to be inserted */ 356c977f7f5Sdrh Select *pSelect, /* A SELECT statement that supplies values */ 357c977f7f5Sdrh int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ 358633ed08dSdanielk1977 ){ 359633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 360c3f9bad2Sdanielk1977 361633ed08dSdanielk1977 assert(pEList == 0 || pSelect == 0); 362633ed08dSdanielk1977 assert(pEList != 0 || pSelect != 0); 363c3f9bad2Sdanielk1977 364d5d56523Sdanielk1977 if( pTriggerStep ){ 365633ed08dSdanielk1977 pTriggerStep->op = TK_INSERT; 366633ed08dSdanielk1977 pTriggerStep->pSelect = pSelect; 367633ed08dSdanielk1977 pTriggerStep->target = *pTableName; 368633ed08dSdanielk1977 pTriggerStep->pIdList = pColumn; 369633ed08dSdanielk1977 pTriggerStep->pExprList = pEList; 370633ed08dSdanielk1977 pTriggerStep->orconf = orconf; 3714b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 372d5d56523Sdanielk1977 }else{ 373d5d56523Sdanielk1977 sqlite3IdListDelete(pColumn); 374d5d56523Sdanielk1977 sqlite3ExprListDelete(pEList); 375d5d56523Sdanielk1977 sqlite3SelectDup(pSelect); 376d5d56523Sdanielk1977 } 377c3f9bad2Sdanielk1977 378633ed08dSdanielk1977 return pTriggerStep; 379c3f9bad2Sdanielk1977 } 380c3f9bad2Sdanielk1977 381c977f7f5Sdrh /* 382c977f7f5Sdrh ** Construct a trigger step that implements an UPDATE statement and return 383c977f7f5Sdrh ** a pointer to that trigger step. The parser calls this routine when it 384c977f7f5Sdrh ** sees an UPDATE statement inside the body of a CREATE TRIGGER. 385c977f7f5Sdrh */ 3864adee20fSdanielk1977 TriggerStep *sqlite3TriggerUpdateStep( 387c977f7f5Sdrh Token *pTableName, /* Name of the table to be updated */ 388c977f7f5Sdrh ExprList *pEList, /* The SET clause: list of column and new values */ 389c977f7f5Sdrh Expr *pWhere, /* The WHERE clause */ 390c977f7f5Sdrh int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ 391c977f7f5Sdrh ){ 392633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 3930e3a6f3fSdrh if( pTriggerStep==0 ){ 3940e3a6f3fSdrh sqlite3ExprListDelete(pEList); 3950e3a6f3fSdrh sqlite3ExprDelete(pWhere); 3960e3a6f3fSdrh return 0; 3970e3a6f3fSdrh } 398c3f9bad2Sdanielk1977 399633ed08dSdanielk1977 pTriggerStep->op = TK_UPDATE; 400633ed08dSdanielk1977 pTriggerStep->target = *pTableName; 401633ed08dSdanielk1977 pTriggerStep->pExprList = pEList; 402633ed08dSdanielk1977 pTriggerStep->pWhere = pWhere; 403633ed08dSdanielk1977 pTriggerStep->orconf = orconf; 4044b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 405c3f9bad2Sdanielk1977 406633ed08dSdanielk1977 return pTriggerStep; 407c3f9bad2Sdanielk1977 } 408c3f9bad2Sdanielk1977 409c977f7f5Sdrh /* 410c977f7f5Sdrh ** Construct a trigger step that implements a DELETE statement and return 411c977f7f5Sdrh ** a pointer to that trigger step. The parser calls this routine when it 412c977f7f5Sdrh ** sees a DELETE statement inside the body of a CREATE TRIGGER. 413c977f7f5Sdrh */ 4144adee20fSdanielk1977 TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){ 415633ed08dSdanielk1977 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep)); 416*b63a53dcSdrh if( pTriggerStep==0 ){ 417*b63a53dcSdrh sqlite3ExprDelete(pWhere); 418*b63a53dcSdrh return 0; 419*b63a53dcSdrh } 420c3f9bad2Sdanielk1977 421633ed08dSdanielk1977 pTriggerStep->op = TK_DELETE; 422633ed08dSdanielk1977 pTriggerStep->target = *pTableName; 423633ed08dSdanielk1977 pTriggerStep->pWhere = pWhere; 424633ed08dSdanielk1977 pTriggerStep->orconf = OE_Default; 4254b59ab5eSdrh sqlitePersistTriggerStep(pTriggerStep); 426c3f9bad2Sdanielk1977 427633ed08dSdanielk1977 return pTriggerStep; 428c3f9bad2Sdanielk1977 } 429c3f9bad2Sdanielk1977 430c3f9bad2Sdanielk1977 /* 431633ed08dSdanielk1977 ** Recursively delete a Trigger structure 432c3f9bad2Sdanielk1977 */ 4334adee20fSdanielk1977 void sqlite3DeleteTrigger(Trigger *pTrigger){ 434f0f258b1Sdrh if( pTrigger==0 ) return; 4354adee20fSdanielk1977 sqlite3DeleteTriggerStep(pTrigger->step_list); 436633ed08dSdanielk1977 sqliteFree(pTrigger->name); 437633ed08dSdanielk1977 sqliteFree(pTrigger->table); 4384adee20fSdanielk1977 sqlite3ExprDelete(pTrigger->pWhen); 4394adee20fSdanielk1977 sqlite3IdListDelete(pTrigger->pColumns); 4404312db55Sdrh if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z); 441633ed08dSdanielk1977 sqliteFree(pTrigger); 442633ed08dSdanielk1977 } 443633ed08dSdanielk1977 444633ed08dSdanielk1977 /* 4458a41449eSdanielk1977 ** This function is called to drop a trigger from the database schema. 4468a41449eSdanielk1977 ** 4478a41449eSdanielk1977 ** This may be called directly from the parser and therefore identifies 4488a41449eSdanielk1977 ** the trigger by name. The sqlite3DropTriggerPtr() routine does the 4498a41449eSdanielk1977 ** same job as this routine except it takes a pointer to the trigger 4508a41449eSdanielk1977 ** instead of the trigger name. 4518a41449eSdanielk1977 **/ 452fdd48a76Sdrh void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ 453742f947bSdanielk1977 Trigger *pTrigger = 0; 454d24cc427Sdrh int i; 455d24cc427Sdrh const char *zDb; 456d24cc427Sdrh const char *zName; 457d24cc427Sdrh int nName; 4589bb575fdSdrh sqlite3 *db = pParse->db; 459633ed08dSdanielk1977 4609e12800dSdanielk1977 if( sqlite3MallocFailed() ) goto drop_trigger_cleanup; 4618a41449eSdanielk1977 if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ 462c0391398Sdanielk1977 goto drop_trigger_cleanup; 463c0391398Sdanielk1977 } 4648e227875Sdanielk1977 465d24cc427Sdrh assert( pName->nSrc==1 ); 466d24cc427Sdrh zDb = pName->a[0].zDatabase; 467d24cc427Sdrh zName = pName->a[0].zName; 468d24cc427Sdrh nName = strlen(zName); 46953c0f748Sdanielk1977 for(i=OMIT_TEMPDB; i<db->nDb; i++){ 470812d7a21Sdrh int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ 4714adee20fSdanielk1977 if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; 472e4df0e74Sdrh pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName); 473d24cc427Sdrh if( pTrigger ) break; 474c3f9bad2Sdanielk1977 } 475d24cc427Sdrh if( !pTrigger ){ 476fdd48a76Sdrh if( !noErr ){ 4774adee20fSdanielk1977 sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0); 478fdd48a76Sdrh } 479d24cc427Sdrh goto drop_trigger_cleanup; 480d24cc427Sdrh } 48174161705Sdrh sqlite3DropTriggerPtr(pParse, pTrigger); 48279a519c0Sdrh 48379a519c0Sdrh drop_trigger_cleanup: 4844adee20fSdanielk1977 sqlite3SrcListDelete(pName); 48579a519c0Sdrh } 48679a519c0Sdrh 48779a519c0Sdrh /* 488956bc92cSdrh ** Return a pointer to the Table structure for the table that a trigger 489956bc92cSdrh ** is set on. 490956bc92cSdrh */ 49174161705Sdrh static Table *tableOfTrigger(Trigger *pTrigger){ 492aaf22685Sdanielk1977 int n = strlen(pTrigger->table) + 1; 493aaf22685Sdanielk1977 return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n); 494956bc92cSdrh } 495956bc92cSdrh 496956bc92cSdrh 497956bc92cSdrh /* 49874161705Sdrh ** Drop a trigger given a pointer to that trigger. 49979a519c0Sdrh */ 50074161705Sdrh void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ 50179a519c0Sdrh Table *pTable; 50279a519c0Sdrh Vdbe *v; 5039bb575fdSdrh sqlite3 *db = pParse->db; 504956bc92cSdrh int iDb; 50579a519c0Sdrh 506da184236Sdanielk1977 iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema); 507956bc92cSdrh assert( iDb>=0 && iDb<db->nDb ); 50874161705Sdrh pTable = tableOfTrigger(pTrigger); 509ed6c8671Sdrh assert( pTable ); 510da184236Sdanielk1977 assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); 511e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION 512e5f9c644Sdrh { 513e5f9c644Sdrh int code = SQLITE_DROP_TRIGGER; 514956bc92cSdrh const char *zDb = db->aDb[iDb].zName; 515956bc92cSdrh const char *zTab = SCHEMA_TABLE(iDb); 516956bc92cSdrh if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; 5174adee20fSdanielk1977 if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) || 5184adee20fSdanielk1977 sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ 51979a519c0Sdrh return; 520ed6c8671Sdrh } 521e5f9c644Sdrh } 522e5f9c644Sdrh #endif 523c3f9bad2Sdanielk1977 524f0f258b1Sdrh /* Generate code to destroy the database record of the trigger. 525f0f258b1Sdrh */ 52643617e9aSdrh assert( pTable!=0 ); 52743617e9aSdrh if( (v = sqlite3GetVdbe(pParse))!=0 ){ 528f0f258b1Sdrh int base; 5295719628aSdrh static const VdbeOpList dropTrigger[] = { 5309b1b01bbSdrh { OP_Rewind, 0, ADDR(9), 0}, 5310f69c1e3Sdanielk1977 { OP_String8, 0, 0, 0}, /* 1 */ 532f0f258b1Sdrh { OP_Column, 0, 1, 0}, 5339b1b01bbSdrh { OP_Ne, 0, ADDR(8), 0}, 5340f69c1e3Sdanielk1977 { OP_String8, 0, 0, "trigger"}, 5359b1b01bbSdrh { OP_Column, 0, 0, 0}, 5369b1b01bbSdrh { OP_Ne, 0, ADDR(8), 0}, 537f0f258b1Sdrh { OP_Delete, 0, 0, 0}, 5389b1b01bbSdrh { OP_Next, 0, ADDR(1), 0}, /* 8 */ 539f0f258b1Sdrh }; 540f0f258b1Sdrh 541956bc92cSdrh sqlite3BeginWriteOperation(pParse, 0, iDb); 542c00da105Sdanielk1977 sqlite3OpenMasterTable(pParse, iDb); 5434adee20fSdanielk1977 base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); 5444adee20fSdanielk1977 sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); 545956bc92cSdrh sqlite3ChangeCookie(db, v, iDb); 5464adee20fSdanielk1977 sqlite3VdbeAddOp(v, OP_Close, 0, 0); 547956bc92cSdrh sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0); 548956bc92cSdrh } 549f0f258b1Sdrh } 550f0f258b1Sdrh 551c3f9bad2Sdanielk1977 /* 552956bc92cSdrh ** Remove a trigger from the hash tables of the sqlite* pointer. 553c3f9bad2Sdanielk1977 */ 554956bc92cSdrh void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ 555956bc92cSdrh Trigger *pTrigger; 55679a519c0Sdrh int nName = strlen(zName); 557e4df0e74Sdrh pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash), 558e4df0e74Sdrh zName, nName, 0); 559956bc92cSdrh if( pTrigger ){ 56074161705Sdrh Table *pTable = tableOfTrigger(pTrigger); 561956bc92cSdrh assert( pTable!=0 ); 562633ed08dSdanielk1977 if( pTable->pTrigger == pTrigger ){ 563633ed08dSdanielk1977 pTable->pTrigger = pTrigger->pNext; 564633ed08dSdanielk1977 }else{ 565633ed08dSdanielk1977 Trigger *cc = pTable->pTrigger; 566c3f9bad2Sdanielk1977 while( cc ){ 567633ed08dSdanielk1977 if( cc->pNext == pTrigger ){ 568c3f9bad2Sdanielk1977 cc->pNext = cc->pNext->pNext; 569c3f9bad2Sdanielk1977 break; 570c3f9bad2Sdanielk1977 } 571c3f9bad2Sdanielk1977 cc = cc->pNext; 572c3f9bad2Sdanielk1977 } 573c3f9bad2Sdanielk1977 assert(cc); 574c3f9bad2Sdanielk1977 } 5754adee20fSdanielk1977 sqlite3DeleteTrigger(pTrigger); 576956bc92cSdrh db->flags |= SQLITE_InternChanges; 577c3f9bad2Sdanielk1977 } 578c3f9bad2Sdanielk1977 } 579c3f9bad2Sdanielk1977 580c977f7f5Sdrh /* 581c977f7f5Sdrh ** pEList is the SET clause of an UPDATE statement. Each entry 582c977f7f5Sdrh ** in pEList is of the format <id>=<expr>. If any of the entries 583c977f7f5Sdrh ** in pEList have an <id> which matches an identifier in pIdList, 584c977f7f5Sdrh ** then return TRUE. If pIdList==NULL, then it is considered a 585c977f7f5Sdrh ** wildcard that matches anything. Likewise if pEList==NULL then 586c977f7f5Sdrh ** it matches anything so always return true. Return false only 587c977f7f5Sdrh ** if there is no match. 588c977f7f5Sdrh */ 589c977f7f5Sdrh static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ 590ad2d8307Sdrh int e; 591ad2d8307Sdrh if( !pIdList || !pEList ) return 1; 592f29ce559Sdanielk1977 for(e=0; e<pEList->nExpr; e++){ 5934adee20fSdanielk1977 if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1; 594f29ce559Sdanielk1977 } 595c3f9bad2Sdanielk1977 return 0; 596c3f9bad2Sdanielk1977 } 597c3f9bad2Sdanielk1977 598c3f9bad2Sdanielk1977 /* 599dca76841Sdrh ** Return a bit vector to indicate what kind of triggers exist for operation 600dca76841Sdrh ** "op" on table pTab. If pChanges is not NULL then it is a list of columns 601dca76841Sdrh ** that are being updated. Triggers only match if the ON clause of the 602dca76841Sdrh ** trigger definition overlaps the set of columns being updated. 603dca76841Sdrh ** 604dca76841Sdrh ** The returned bit vector is some combination of TRIGGER_BEFORE and 605dca76841Sdrh ** TRIGGER_AFTER. 606c3f9bad2Sdanielk1977 */ 6074adee20fSdanielk1977 int sqlite3TriggersExist( 608c977f7f5Sdrh Parse *pParse, /* Used to check for recursive triggers */ 609dca76841Sdrh Table *pTab, /* The table the contains the triggers */ 610c3f9bad2Sdanielk1977 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ 611c977f7f5Sdrh ExprList *pChanges /* Columns that change in an UPDATE statement */ 612c977f7f5Sdrh ){ 6134cbdda9eSdrh Trigger *pTrigger; 614dca76841Sdrh int mask = 0; 615c3f9bad2Sdanielk1977 6164cbdda9eSdrh pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger; 617dca76841Sdrh while( pTrigger ){ 618dca76841Sdrh if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){ 619dca76841Sdrh mask |= pTrigger->tr_tm; 620c3f9bad2Sdanielk1977 } 621dca76841Sdrh pTrigger = pTrigger->pNext; 622dca76841Sdrh } 623dca76841Sdrh return mask; 624c3f9bad2Sdanielk1977 } 625c3f9bad2Sdanielk1977 626c977f7f5Sdrh /* 627f26e09c8Sdrh ** Convert the pStep->target token into a SrcList and return a pointer 628f26e09c8Sdrh ** to that SrcList. 629f26e09c8Sdrh ** 630f26e09c8Sdrh ** This routine adds a specific database name, if needed, to the target when 631f26e09c8Sdrh ** forming the SrcList. This prevents a trigger in one database from 632f26e09c8Sdrh ** referring to a target in another database. An exception is when the 633f26e09c8Sdrh ** trigger is in TEMP in which case it can refer to any other database it 634f26e09c8Sdrh ** wants. 635f26e09c8Sdrh */ 636f26e09c8Sdrh static SrcList *targetSrcList( 637f26e09c8Sdrh Parse *pParse, /* The parsing context */ 638f26e09c8Sdrh TriggerStep *pStep /* The trigger containing the target token */ 639f26e09c8Sdrh ){ 640f26e09c8Sdrh Token sDb; /* Dummy database name token */ 641f26e09c8Sdrh int iDb; /* Index of the database to use */ 642f26e09c8Sdrh SrcList *pSrc; /* SrcList to be returned */ 643f26e09c8Sdrh 644da184236Sdanielk1977 iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema); 645f26e09c8Sdrh if( iDb==0 || iDb>=2 ){ 646f26e09c8Sdrh assert( iDb<pParse->db->nDb ); 6472646da7eSdrh sDb.z = (u8*)pParse->db->aDb[iDb].zName; 6482646da7eSdrh sDb.n = strlen((char*)sDb.z); 6494adee20fSdanielk1977 pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target); 650f26e09c8Sdrh } else { 6514adee20fSdanielk1977 pSrc = sqlite3SrcListAppend(0, &pStep->target, 0); 652f26e09c8Sdrh } 653f26e09c8Sdrh return pSrc; 654f26e09c8Sdrh } 655f26e09c8Sdrh 656f26e09c8Sdrh /* 657c977f7f5Sdrh ** Generate VDBE code for zero or more statements inside the body of a 658c977f7f5Sdrh ** trigger. 659c977f7f5Sdrh */ 660c3f9bad2Sdanielk1977 static int codeTriggerProgram( 661c977f7f5Sdrh Parse *pParse, /* The parser context */ 662c977f7f5Sdrh TriggerStep *pStepList, /* List of statements inside the trigger body */ 663c977f7f5Sdrh int orconfin /* Conflict algorithm. (OE_Abort, etc) */ 664633ed08dSdanielk1977 ){ 665633ed08dSdanielk1977 TriggerStep * pTriggerStep = pStepList; 666c3f9bad2Sdanielk1977 int orconf; 667344737f6Sdrh Vdbe *v = pParse->pVdbe; 668c3f9bad2Sdanielk1977 669344737f6Sdrh assert( pTriggerStep!=0 ); 670344737f6Sdrh assert( v!=0 ); 671344737f6Sdrh sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0); 67267040462Sdrh VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name)); 673633ed08dSdanielk1977 while( pTriggerStep ){ 674633ed08dSdanielk1977 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; 675c3f9bad2Sdanielk1977 pParse->trigStack->orconf = orconf; 676633ed08dSdanielk1977 switch( pTriggerStep->op ){ 677c3f9bad2Sdanielk1977 case TK_SELECT: { 6784adee20fSdanielk1977 Select *ss = sqlite3SelectDup(pTriggerStep->pSelect); 67928f45914Sdrh if( ss ){ 680b3bce662Sdanielk1977 sqlite3SelectResolve(pParse, ss, 0); 681b3bce662Sdanielk1977 sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0); 6824adee20fSdanielk1977 sqlite3SelectDelete(ss); 68328f45914Sdrh } 684c3f9bad2Sdanielk1977 break; 685c3f9bad2Sdanielk1977 } 686c3f9bad2Sdanielk1977 case TK_UPDATE: { 687113088ecSdrh SrcList *pSrc; 688f26e09c8Sdrh pSrc = targetSrcList(pParse, pTriggerStep); 689344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); 6904adee20fSdanielk1977 sqlite3Update(pParse, pSrc, 6914adee20fSdanielk1977 sqlite3ExprListDup(pTriggerStep->pExprList), 6924adee20fSdanielk1977 sqlite3ExprDup(pTriggerStep->pWhere), orconf); 693344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); 694c3f9bad2Sdanielk1977 break; 695c3f9bad2Sdanielk1977 } 696c3f9bad2Sdanielk1977 case TK_INSERT: { 697113088ecSdrh SrcList *pSrc; 698f26e09c8Sdrh pSrc = targetSrcList(pParse, pTriggerStep); 699344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); 7004adee20fSdanielk1977 sqlite3Insert(pParse, pSrc, 7014adee20fSdanielk1977 sqlite3ExprListDup(pTriggerStep->pExprList), 7024adee20fSdanielk1977 sqlite3SelectDup(pTriggerStep->pSelect), 7034adee20fSdanielk1977 sqlite3IdListDup(pTriggerStep->pIdList), orconf); 704344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); 705c3f9bad2Sdanielk1977 break; 706c3f9bad2Sdanielk1977 } 707c3f9bad2Sdanielk1977 case TK_DELETE: { 708113088ecSdrh SrcList *pSrc; 709344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0); 710f26e09c8Sdrh pSrc = targetSrcList(pParse, pTriggerStep); 7114adee20fSdanielk1977 sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere)); 712344737f6Sdrh sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0); 713c3f9bad2Sdanielk1977 break; 714c3f9bad2Sdanielk1977 } 715c3f9bad2Sdanielk1977 default: 716c3f9bad2Sdanielk1977 assert(0); 717c3f9bad2Sdanielk1977 } 718633ed08dSdanielk1977 pTriggerStep = pTriggerStep->pNext; 719c3f9bad2Sdanielk1977 } 720344737f6Sdrh sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); 72167040462Sdrh VdbeComment((v, "# end trigger %s", pStepList->pTrig->name)); 722c3f9bad2Sdanielk1977 723c3f9bad2Sdanielk1977 return 0; 724c3f9bad2Sdanielk1977 } 725c3f9bad2Sdanielk1977 726633ed08dSdanielk1977 /* 727633ed08dSdanielk1977 ** This is called to code FOR EACH ROW triggers. 728633ed08dSdanielk1977 ** 729633ed08dSdanielk1977 ** When the code that this function generates is executed, the following 730633ed08dSdanielk1977 ** must be true: 731c977f7f5Sdrh ** 732c977f7f5Sdrh ** 1. No cursors may be open in the main database. (But newIdx and oldIdx 733c977f7f5Sdrh ** can be indices of cursors in temporary tables. See below.) 734c977f7f5Sdrh ** 735633ed08dSdanielk1977 ** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then 736633ed08dSdanielk1977 ** a temporary vdbe cursor (index newIdx) must be open and pointing at 737633ed08dSdanielk1977 ** a row containing values to be substituted for new.* expressions in the 738633ed08dSdanielk1977 ** trigger program(s). 739c977f7f5Sdrh ** 740633ed08dSdanielk1977 ** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then 741633ed08dSdanielk1977 ** a temporary vdbe cursor (index oldIdx) must be open and pointing at 742633ed08dSdanielk1977 ** a row containing values to be substituted for old.* expressions in the 743633ed08dSdanielk1977 ** trigger program(s). 744633ed08dSdanielk1977 ** 745633ed08dSdanielk1977 */ 7464adee20fSdanielk1977 int sqlite3CodeRowTrigger( 747c3f9bad2Sdanielk1977 Parse *pParse, /* Parse context */ 748c3f9bad2Sdanielk1977 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ 749633ed08dSdanielk1977 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ 750dca76841Sdrh int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ 751633ed08dSdanielk1977 Table *pTab, /* The table to code triggers from */ 752633ed08dSdanielk1977 int newIdx, /* The indice of the "new" row to access */ 753633ed08dSdanielk1977 int oldIdx, /* The indice of the "old" row to access */ 7546f34903eSdanielk1977 int orconf, /* ON CONFLICT policy */ 7556f34903eSdanielk1977 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */ 756c977f7f5Sdrh ){ 757eecfb3eeSdanielk1977 Trigger *p; 75867040462Sdrh TriggerStack trigStackEntry; 759c3f9bad2Sdanielk1977 760c3f9bad2Sdanielk1977 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); 761dca76841Sdrh assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); 762c3f9bad2Sdanielk1977 763633ed08dSdanielk1977 assert(newIdx != -1 || oldIdx != -1); 764c3f9bad2Sdanielk1977 765eecfb3eeSdanielk1977 for(p=pTab->pTrigger; p; p=p->pNext){ 766c3f9bad2Sdanielk1977 int fire_this = 0; 767c3f9bad2Sdanielk1977 768eecfb3eeSdanielk1977 /* Determine whether we should code this trigger */ 769eecfb3eeSdanielk1977 if( 770eecfb3eeSdanielk1977 p->op==op && 771eecfb3eeSdanielk1977 p->tr_tm==tr_tm && 772eecfb3eeSdanielk1977 (p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) && 773eecfb3eeSdanielk1977 (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges)) 774eecfb3eeSdanielk1977 ){ 775eecfb3eeSdanielk1977 TriggerStack *pS; /* Pointer to trigger-stack entry */ 77674161705Sdrh for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){} 777eecfb3eeSdanielk1977 if( !pS ){ 778c3f9bad2Sdanielk1977 fire_this = 1; 779c3f9bad2Sdanielk1977 } 780229caa36Sdrh #if 0 /* Give no warning for recursive triggers. Just do not do them */ 781229caa36Sdrh else{ 782229caa36Sdrh sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)", 783229caa36Sdrh p->name); 784229caa36Sdrh return SQLITE_ERROR; 785229caa36Sdrh } 786229caa36Sdrh #endif 787f29ce559Sdanielk1977 } 788c3f9bad2Sdanielk1977 78967040462Sdrh if( fire_this ){ 790c3f9bad2Sdanielk1977 int endTrigger; 791c3f9bad2Sdanielk1977 Expr * whenExpr; 79285e2096fSdrh AuthContext sContext; 793b3bce662Sdanielk1977 NameContext sNC; 794c3f9bad2Sdanielk1977 795b3bce662Sdanielk1977 memset(&sNC, 0, sizeof(sNC)); 796b3bce662Sdanielk1977 sNC.pParse = pParse; 797c3f9bad2Sdanielk1977 798c3f9bad2Sdanielk1977 /* Push an entry on to the trigger stack */ 799eecfb3eeSdanielk1977 trigStackEntry.pTrigger = p; 80067040462Sdrh trigStackEntry.newIdx = newIdx; 80167040462Sdrh trigStackEntry.oldIdx = oldIdx; 80267040462Sdrh trigStackEntry.pTab = pTab; 80367040462Sdrh trigStackEntry.pNext = pParse->trigStack; 80467040462Sdrh trigStackEntry.ignoreJump = ignoreJump; 80567040462Sdrh pParse->trigStack = &trigStackEntry; 806eecfb3eeSdanielk1977 sqlite3AuthContextPush(pParse, &sContext, p->name); 807c3f9bad2Sdanielk1977 808c3f9bad2Sdanielk1977 /* code the WHEN clause */ 8094adee20fSdanielk1977 endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); 810eecfb3eeSdanielk1977 whenExpr = sqlite3ExprDup(p->pWhen); 811b3bce662Sdanielk1977 if( sqlite3ExprResolveNames(&sNC, whenExpr) ){ 81267040462Sdrh pParse->trigStack = trigStackEntry.pNext; 8134adee20fSdanielk1977 sqlite3ExprDelete(whenExpr); 814c3f9bad2Sdanielk1977 return 1; 815c3f9bad2Sdanielk1977 } 8164adee20fSdanielk1977 sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1); 8174adee20fSdanielk1977 sqlite3ExprDelete(whenExpr); 818c3f9bad2Sdanielk1977 819eecfb3eeSdanielk1977 codeTriggerProgram(pParse, p->step_list, orconf); 820c3f9bad2Sdanielk1977 821c3f9bad2Sdanielk1977 /* Pop the entry off the trigger stack */ 82267040462Sdrh pParse->trigStack = trigStackEntry.pNext; 8234adee20fSdanielk1977 sqlite3AuthContextPop(&sContext); 824c3f9bad2Sdanielk1977 8254adee20fSdanielk1977 sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger); 826c3f9bad2Sdanielk1977 } 827c3f9bad2Sdanielk1977 } 828c3f9bad2Sdanielk1977 return 0; 829c3f9bad2Sdanielk1977 } 830b7f9164eSdrh #endif /* !defined(SQLITE_OMIT_TRIGGER) */ 831