xref: /sqlite-3.40.0/src/trigger.c (revision ceea3321)
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 *************************************************************************
11822a5162Sdanielk1977 **
12822a5162Sdanielk1977 **
13*ceea3321Sdrh ** $Id: trigger.c,v 1.136 2009/04/23 13:22:44 drh Exp $
14c3f9bad2Sdanielk1977 */
15c3f9bad2Sdanielk1977 #include "sqliteInt.h"
169adf9ac4Sdrh 
17b7f9164eSdrh #ifndef SQLITE_OMIT_TRIGGER
18c3f9bad2Sdanielk1977 /*
194b59ab5eSdrh ** Delete a linked list of TriggerStep structures.
204b59ab5eSdrh */
21633e6d57Sdrh void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
224b59ab5eSdrh   while( pTriggerStep ){
234b59ab5eSdrh     TriggerStep * pTmp = pTriggerStep;
244b59ab5eSdrh     pTriggerStep = pTriggerStep->pNext;
254b59ab5eSdrh 
26633e6d57Sdrh     if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z);
27633e6d57Sdrh     sqlite3ExprDelete(db, pTmp->pWhere);
28633e6d57Sdrh     sqlite3ExprListDelete(db, pTmp->pExprList);
29633e6d57Sdrh     sqlite3SelectDelete(db, pTmp->pSelect);
30633e6d57Sdrh     sqlite3IdListDelete(db, pTmp->pIdList);
314b59ab5eSdrh 
32633e6d57Sdrh     sqlite3DbFree(db, pTmp);
334b59ab5eSdrh   }
344b59ab5eSdrh }
354b59ab5eSdrh 
364b59ab5eSdrh /*
372f886d1dSdanielk1977 ** Given table pTab, return a list of all the triggers attached to
382f886d1dSdanielk1977 ** the table. The list is connected by Trigger.pNext pointers.
392f886d1dSdanielk1977 */
402f886d1dSdanielk1977 Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
412f886d1dSdanielk1977   Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
422f886d1dSdanielk1977   Trigger *pList = 0;                  /* List of triggers to return */
432f886d1dSdanielk1977 
442f886d1dSdanielk1977   if( pTmpSchema!=pTab->pSchema ){
452f886d1dSdanielk1977     HashElem *p;
462f886d1dSdanielk1977     for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
472f886d1dSdanielk1977       Trigger *pTrig = (Trigger *)sqliteHashData(p);
482f886d1dSdanielk1977       if( pTrig->pTabSchema==pTab->pSchema
492f886d1dSdanielk1977        && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
502f886d1dSdanielk1977       ){
512f886d1dSdanielk1977         pTrig->pNext = (pList ? pList : pTab->pTrigger);
522f886d1dSdanielk1977         pList = pTrig;
532f886d1dSdanielk1977       }
542f886d1dSdanielk1977     }
552f886d1dSdanielk1977   }
562f886d1dSdanielk1977 
572f886d1dSdanielk1977   return (pList ? pList : pTab->pTrigger);
582f886d1dSdanielk1977 }
592f886d1dSdanielk1977 
602f886d1dSdanielk1977 /*
61f0f258b1Sdrh ** This is called by the parser when it sees a CREATE TRIGGER statement
62f0f258b1Sdrh ** up to the point of the BEGIN before the trigger actions.  A Trigger
63f0f258b1Sdrh ** structure is generated based on the information available and stored
64f0f258b1Sdrh ** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
654adee20fSdanielk1977 ** sqlite3FinishTrigger() function is called to complete the trigger
66f0f258b1Sdrh ** construction process.
67c3f9bad2Sdanielk1977 */
684adee20fSdanielk1977 void sqlite3BeginTrigger(
69c3f9bad2Sdanielk1977   Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
70ef2cb63eSdanielk1977   Token *pName1,      /* The name of the trigger */
71ef2cb63eSdanielk1977   Token *pName2,      /* The name of the trigger */
72d702fccbSdanielk1977   int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
73c3f9bad2Sdanielk1977   int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
74633ed08dSdanielk1977   IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
75d24cc427Sdrh   SrcList *pTableName,/* The name of the table/view the trigger applies to */
76c3f9bad2Sdanielk1977   Expr *pWhen,        /* WHEN clause */
77fdd48a76Sdrh   int isTemp,         /* True if the TEMPORARY keyword is present */
78fdd48a76Sdrh   int noErr           /* Suppress errors if the trigger already exists */
799adf9ac4Sdrh ){
80d5d56523Sdanielk1977   Trigger *pTrigger = 0;
81ef2cb63eSdanielk1977   Table *pTab;
82e5f9c644Sdrh   char *zName = 0;        /* Name of the trigger */
839bb575fdSdrh   sqlite3 *db = pParse->db;
84ef2cb63eSdanielk1977   int iDb;                /* The database to store the trigger in */
85ef2cb63eSdanielk1977   Token *pName;           /* The unqualified db name */
864312db55Sdrh   DbFixer sFix;
87da184236Sdanielk1977   int iTabDb;
88ed6c8671Sdrh 
8943617e9aSdrh   assert( pName1!=0 );   /* pName1->z might be NULL, but not pName1 itself */
9043617e9aSdrh   assert( pName2!=0 );
91aa78bec9Sdrh   assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE );
92aa78bec9Sdrh   assert( op>0 && op<0xff );
93ef2cb63eSdanielk1977   if( isTemp ){
94ef2cb63eSdanielk1977     /* If TEMP was specified, then the trigger name may not be qualified. */
9543617e9aSdrh     if( pName2->n>0 ){
96ef2cb63eSdanielk1977       sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
97ef2cb63eSdanielk1977       goto trigger_cleanup;
98ef2cb63eSdanielk1977     }
99ef2cb63eSdanielk1977     iDb = 1;
100ef2cb63eSdanielk1977     pName = pName1;
101ef2cb63eSdanielk1977   }else{
102ef2cb63eSdanielk1977     /* Figure out the db that the the trigger will be created in */
103ef2cb63eSdanielk1977     iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
104ef2cb63eSdanielk1977     if( iDb<0 ){
105ef2cb63eSdanielk1977       goto trigger_cleanup;
106ef2cb63eSdanielk1977     }
107ef2cb63eSdanielk1977   }
108ef2cb63eSdanielk1977 
109ef2cb63eSdanielk1977   /* If the trigger name was unqualified, and the table is a temp table,
110ef2cb63eSdanielk1977   ** then set iDb to 1 to create the trigger in the temporary database.
111ef2cb63eSdanielk1977   ** If sqlite3SrcListLookup() returns 0, indicating the table does not
112ef2cb63eSdanielk1977   ** exist, the error is caught by the block below.
113c3f9bad2Sdanielk1977   */
11417435752Sdrh   if( !pTableName || db->mallocFailed ){
1156f7adc8aSdrh     goto trigger_cleanup;
1166f7adc8aSdrh   }
117ef2cb63eSdanielk1977   pTab = sqlite3SrcListLookup(pParse, pTableName);
118da184236Sdanielk1977   if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
119ef2cb63eSdanielk1977     iDb = 1;
120ef2cb63eSdanielk1977   }
121ef2cb63eSdanielk1977 
122ef2cb63eSdanielk1977   /* Ensure the table name matches database name and that the table exists */
12317435752Sdrh   if( db->mallocFailed ) goto trigger_cleanup;
124d24cc427Sdrh   assert( pTableName->nSrc==1 );
125ef2cb63eSdanielk1977   if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
126ef2cb63eSdanielk1977       sqlite3FixSrcList(&sFix, pTableName) ){
1274312db55Sdrh     goto trigger_cleanup;
128f26e09c8Sdrh   }
129ef2cb63eSdanielk1977   pTab = sqlite3SrcListLookup(pParse, pTableName);
130ef2cb63eSdanielk1977   if( !pTab ){
131ef2cb63eSdanielk1977     /* The table does not exist. */
132d24cc427Sdrh     goto trigger_cleanup;
133d24cc427Sdrh   }
1344cbdda9eSdrh   if( IsVirtual(pTab) ){
1354cbdda9eSdrh     sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
1364cbdda9eSdrh     goto trigger_cleanup;
1374cbdda9eSdrh   }
138d24cc427Sdrh 
139d8123366Sdanielk1977   /* Check that the trigger name is not reserved and that no trigger of the
140d8123366Sdanielk1977   ** specified name exists */
14117435752Sdrh   zName = sqlite3NameFromToken(db, pName);
142d8123366Sdanielk1977   if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
143d8123366Sdanielk1977     goto trigger_cleanup;
144d8123366Sdanielk1977   }
145aa78bec9Sdrh   if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
146ea678832Sdrh                       zName, sqlite3Strlen30(zName)) ){
147fdd48a76Sdrh     if( !noErr ){
1484adee20fSdanielk1977       sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
149fdd48a76Sdrh     }
150c3f9bad2Sdanielk1977     goto trigger_cleanup;
151c3f9bad2Sdanielk1977   }
152ef2cb63eSdanielk1977 
153ef2cb63eSdanielk1977   /* Do not create a trigger on a system table */
154dca76841Sdrh   if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
1554adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
156e0bc4048Sdrh     pParse->nErr++;
157e0bc4048Sdrh     goto trigger_cleanup;
158e0bc4048Sdrh   }
159ef2cb63eSdanielk1977 
160ef2cb63eSdanielk1977   /* INSTEAD of triggers are only for views and views only support INSTEAD
161ef2cb63eSdanielk1977   ** of triggers.
162ef2cb63eSdanielk1977   */
163ef2cb63eSdanielk1977   if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
1644adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
165da93d238Sdrh         (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
166d702fccbSdanielk1977     goto trigger_cleanup;
167d702fccbSdanielk1977   }
168ef2cb63eSdanielk1977   if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
1694adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
170da93d238Sdrh         " trigger on table: %S", pTableName, 0);
171d702fccbSdanielk1977     goto trigger_cleanup;
172d702fccbSdanielk1977   }
173da184236Sdanielk1977   iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
174ef2cb63eSdanielk1977 
175e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION
176e5f9c644Sdrh   {
177e5f9c644Sdrh     int code = SQLITE_CREATE_TRIGGER;
178da184236Sdanielk1977     const char *zDb = db->aDb[iTabDb].zName;
179e22a334bSdrh     const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
180da184236Sdanielk1977     if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
181ef2cb63eSdanielk1977     if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
182ed6c8671Sdrh       goto trigger_cleanup;
183ed6c8671Sdrh     }
184da184236Sdanielk1977     if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
18577ad4e41Sdrh       goto trigger_cleanup;
18677ad4e41Sdrh     }
187d702fccbSdanielk1977   }
188e5f9c644Sdrh #endif
189d702fccbSdanielk1977 
190ef2cb63eSdanielk1977   /* INSTEAD OF triggers can only appear on views and BEFORE triggers
1915cf590c1Sdrh   ** cannot appear on views.  So we might as well translate every
1925cf590c1Sdrh   ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code
1935cf590c1Sdrh   ** elsewhere.
1945cf590c1Sdrh   */
195d702fccbSdanielk1977   if (tr_tm == TK_INSTEAD){
196d702fccbSdanielk1977     tr_tm = TK_BEFORE;
197c3f9bad2Sdanielk1977   }
198c3f9bad2Sdanielk1977 
199c3f9bad2Sdanielk1977   /* Build the Trigger object */
20017435752Sdrh   pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
201ef2cb63eSdanielk1977   if( pTrigger==0 ) goto trigger_cleanup;
202ef2cb63eSdanielk1977   pTrigger->name = zName;
203e5f9c644Sdrh   zName = 0;
20417435752Sdrh   pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
205da184236Sdanielk1977   pTrigger->pSchema = db->aDb[iDb].pSchema;
206aaf22685Sdanielk1977   pTrigger->pTabSchema = pTab->pSchema;
207aa78bec9Sdrh   pTrigger->op = (u8)op;
208dca76841Sdrh   pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
2096ab3a2ecSdanielk1977   pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
21017435752Sdrh   pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
21117435752Sdrh   sqlite3TokenCopy(db, &pTrigger->nameToken,pName);
212f0f258b1Sdrh   assert( pParse->pNewTrigger==0 );
213ef2cb63eSdanielk1977   pParse->pNewTrigger = pTrigger;
214f0f258b1Sdrh 
215f0f258b1Sdrh trigger_cleanup:
216633e6d57Sdrh   sqlite3DbFree(db, zName);
217633e6d57Sdrh   sqlite3SrcListDelete(db, pTableName);
218633e6d57Sdrh   sqlite3IdListDelete(db, pColumns);
219633e6d57Sdrh   sqlite3ExprDelete(db, pWhen);
220d5d56523Sdanielk1977   if( !pParse->pNewTrigger ){
221633e6d57Sdrh     sqlite3DeleteTrigger(db, pTrigger);
222d5d56523Sdanielk1977   }else{
223d5d56523Sdanielk1977     assert( pParse->pNewTrigger==pTrigger );
224d5d56523Sdanielk1977   }
225f0f258b1Sdrh }
226f0f258b1Sdrh 
227f0f258b1Sdrh /*
228f0f258b1Sdrh ** This routine is called after all of the trigger actions have been parsed
229f0f258b1Sdrh ** in order to complete the process of building the trigger.
230f0f258b1Sdrh */
2314adee20fSdanielk1977 void sqlite3FinishTrigger(
232f0f258b1Sdrh   Parse *pParse,          /* Parser context */
233f0f258b1Sdrh   TriggerStep *pStepList, /* The triggered program */
234f0f258b1Sdrh   Token *pAll             /* Token that describes the complete CREATE TRIGGER */
235f0f258b1Sdrh ){
2362f886d1dSdanielk1977   Trigger *pTrig = pParse->pNewTrigger;    /* Trigger being finished */
2372f886d1dSdanielk1977   char *zName;                             /* Name of trigger */
2389bb575fdSdrh   sqlite3 *db = pParse->db;                /* The database */
239f26e09c8Sdrh   DbFixer sFix;
240da184236Sdanielk1977   int iDb;                                 /* Database containing the trigger */
241f0f258b1Sdrh 
242bfb9e35bSdanielk1977   pTrig = pParse->pNewTrigger;
243f0f258b1Sdrh   pParse->pNewTrigger = 0;
2442e588c75Sdanielk1977   if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
2452f886d1dSdanielk1977   zName = pTrig->name;
246da184236Sdanielk1977   iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
247bfb9e35bSdanielk1977   pTrig->step_list = pStepList;
248a69d9168Sdrh   while( pStepList ){
249bfb9e35bSdanielk1977     pStepList->pTrig = pTrig;
250a69d9168Sdrh     pStepList = pStepList->pNext;
251a69d9168Sdrh   }
252da184236Sdanielk1977   if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
253bfb9e35bSdanielk1977           && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
254f26e09c8Sdrh     goto triggerfinish_cleanup;
255f26e09c8Sdrh   }
256c3f9bad2Sdanielk1977 
257c3f9bad2Sdanielk1977   /* if we are not initializing, and this trigger is not on a TEMP table,
2589adf9ac4Sdrh   ** build the sqlite_master entry
2599adf9ac4Sdrh   */
2601d85d931Sdrh   if( !db->init.busy ){
261c977f7f5Sdrh     Vdbe *v;
2622d401ab8Sdrh     char *z;
263c3f9bad2Sdanielk1977 
264c3f9bad2Sdanielk1977     /* Make an entry in the sqlite_master table */
2654adee20fSdanielk1977     v = sqlite3GetVdbe(pParse);
266f0f258b1Sdrh     if( v==0 ) goto triggerfinish_cleanup;
267da184236Sdanielk1977     sqlite3BeginWriteOperation(pParse, 0, iDb);
2682d401ab8Sdrh     z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
2692d401ab8Sdrh     sqlite3NestedParse(pParse,
2702d401ab8Sdrh        "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
2712f886d1dSdanielk1977        db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
2722d401ab8Sdrh        pTrig->table, z);
273633e6d57Sdrh     sqlite3DbFree(db, z);
2749cbf3425Sdrh     sqlite3ChangeCookie(pParse, iDb);
27566a5167bSdrh     sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
2762f886d1dSdanielk1977         db, "type='trigger' AND name='%q'", zName), P4_DYNAMIC
2771e536953Sdanielk1977     );
278c3f9bad2Sdanielk1977   }
279c3f9bad2Sdanielk1977 
280956bc92cSdrh   if( db->init.busy ){
2812f886d1dSdanielk1977     Trigger *pLink = pTrig;
2822f886d1dSdanielk1977     Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
2832f886d1dSdanielk1977     pTrig = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), pTrig);
2842f886d1dSdanielk1977     if( pTrig ){
285f3a65f7eSdrh       db->mallocFailed = 1;
2862f886d1dSdanielk1977     }else if( pLink->pSchema==pLink->pTabSchema ){
2872f886d1dSdanielk1977       Table *pTab;
2882f886d1dSdanielk1977       int n = sqlite3Strlen30(pLink->table) + 1;
2892f886d1dSdanielk1977       pTab = sqlite3HashFind(&pLink->pTabSchema->tblHash, pLink->table, n);
290f0f258b1Sdrh       assert( pTab!=0 );
2912f886d1dSdanielk1977       pLink->pNext = pTab->pTrigger;
2922f886d1dSdanielk1977       pTab->pTrigger = pLink;
2932f886d1dSdanielk1977     }
294c3f9bad2Sdanielk1977   }
295c3f9bad2Sdanielk1977 
296f0f258b1Sdrh triggerfinish_cleanup:
297633e6d57Sdrh   sqlite3DeleteTrigger(db, pTrig);
298bfb9e35bSdanielk1977   assert( !pParse->pNewTrigger );
299633e6d57Sdrh   sqlite3DeleteTriggerStep(db, pStepList);
300c3f9bad2Sdanielk1977 }
3014b59ab5eSdrh 
3024b59ab5eSdrh /*
3034b59ab5eSdrh ** Make a copy of all components of the given trigger step.  This has
3044b59ab5eSdrh ** the effect of copying all Expr.token.z values into memory obtained
30517435752Sdrh ** from sqlite3_malloc().  As initially created, the Expr.token.z values
3064b59ab5eSdrh ** all point to the input string that was fed to the parser.  But that
3076f8a503dSdanielk1977 ** string is ephemeral - it will go away as soon as the sqlite3_exec()
3084b59ab5eSdrh ** call that started the parser exits.  This routine makes a persistent
3094b59ab5eSdrh ** copy of all the Expr.token.z strings so that the TriggerStep structure
3106f8a503dSdanielk1977 ** will be valid even after the sqlite3_exec() call returns.
3114b59ab5eSdrh */
31217435752Sdrh static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){
3134b59ab5eSdrh   if( p->target.z ){
31417435752Sdrh     p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n);
3154b59ab5eSdrh     p->target.dyn = 1;
3164b59ab5eSdrh   }
3174b59ab5eSdrh   if( p->pSelect ){
3186ab3a2ecSdanielk1977     Select *pNew = sqlite3SelectDup(db, p->pSelect, 1);
319633e6d57Sdrh     sqlite3SelectDelete(db, p->pSelect);
3204b59ab5eSdrh     p->pSelect = pNew;
3214b59ab5eSdrh   }
3224b59ab5eSdrh   if( p->pWhere ){
3236ab3a2ecSdanielk1977     Expr *pNew = sqlite3ExprDup(db, p->pWhere, EXPRDUP_REDUCE);
324633e6d57Sdrh     sqlite3ExprDelete(db, p->pWhere);
3254b59ab5eSdrh     p->pWhere = pNew;
3264b59ab5eSdrh   }
3274b59ab5eSdrh   if( p->pExprList ){
3286ab3a2ecSdanielk1977     ExprList *pNew = sqlite3ExprListDup(db, p->pExprList, 1);
329633e6d57Sdrh     sqlite3ExprListDelete(db, p->pExprList);
3304b59ab5eSdrh     p->pExprList = pNew;
3314b59ab5eSdrh   }
3324b59ab5eSdrh   if( p->pIdList ){
33317435752Sdrh     IdList *pNew = sqlite3IdListDup(db, p->pIdList);
334633e6d57Sdrh     sqlite3IdListDelete(db, p->pIdList);
3354b59ab5eSdrh     p->pIdList = pNew;
336c3f9bad2Sdanielk1977   }
337c3f9bad2Sdanielk1977 }
338c3f9bad2Sdanielk1977 
339c977f7f5Sdrh /*
340c977f7f5Sdrh ** Turn a SELECT statement (that the pSelect parameter points to) into
341c977f7f5Sdrh ** a trigger step.  Return a pointer to a TriggerStep structure.
342c977f7f5Sdrh **
343c977f7f5Sdrh ** The parser calls this routine when it finds a SELECT statement in
344c977f7f5Sdrh ** body of a TRIGGER.
345c977f7f5Sdrh */
34617435752Sdrh TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
34717435752Sdrh   TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
3482e588c75Sdanielk1977   if( pTriggerStep==0 ) {
349633e6d57Sdrh     sqlite3SelectDelete(db, pSelect);
3502e588c75Sdanielk1977     return 0;
3512e588c75Sdanielk1977   }
352c3f9bad2Sdanielk1977 
353633ed08dSdanielk1977   pTriggerStep->op = TK_SELECT;
354633ed08dSdanielk1977   pTriggerStep->pSelect = pSelect;
355633ed08dSdanielk1977   pTriggerStep->orconf = OE_Default;
35617435752Sdrh   sqlitePersistTriggerStep(db, pTriggerStep);
357c3f9bad2Sdanielk1977 
358633ed08dSdanielk1977   return pTriggerStep;
359c3f9bad2Sdanielk1977 }
360c3f9bad2Sdanielk1977 
361c977f7f5Sdrh /*
362c977f7f5Sdrh ** Build a trigger step out of an INSERT statement.  Return a pointer
363c977f7f5Sdrh ** to the new trigger step.
364c977f7f5Sdrh **
365c977f7f5Sdrh ** The parser calls this routine when it sees an INSERT inside the
366c977f7f5Sdrh ** body of a trigger.
367c977f7f5Sdrh */
3684adee20fSdanielk1977 TriggerStep *sqlite3TriggerInsertStep(
36917435752Sdrh   sqlite3 *db,        /* The database connection */
370c977f7f5Sdrh   Token *pTableName,  /* Name of the table into which we insert */
371c977f7f5Sdrh   IdList *pColumn,    /* List of columns in pTableName to insert into */
372c977f7f5Sdrh   ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
373c977f7f5Sdrh   Select *pSelect,    /* A SELECT statement that supplies values */
374c977f7f5Sdrh   int orconf          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
375633ed08dSdanielk1977 ){
376f3a65f7eSdrh   TriggerStep *pTriggerStep;
377c3f9bad2Sdanielk1977 
378633ed08dSdanielk1977   assert(pEList == 0 || pSelect == 0);
379f3a65f7eSdrh   assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
380c3f9bad2Sdanielk1977 
381f3a65f7eSdrh   pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
382d5d56523Sdanielk1977   if( pTriggerStep ){
383633ed08dSdanielk1977     pTriggerStep->op = TK_INSERT;
384633ed08dSdanielk1977     pTriggerStep->pSelect = pSelect;
385633ed08dSdanielk1977     pTriggerStep->target  = *pTableName;
386633ed08dSdanielk1977     pTriggerStep->pIdList = pColumn;
387633ed08dSdanielk1977     pTriggerStep->pExprList = pEList;
388633ed08dSdanielk1977     pTriggerStep->orconf = orconf;
38917435752Sdrh     sqlitePersistTriggerStep(db, pTriggerStep);
390d5d56523Sdanielk1977   }else{
391633e6d57Sdrh     sqlite3IdListDelete(db, pColumn);
392633e6d57Sdrh     sqlite3ExprListDelete(db, pEList);
393633e6d57Sdrh     sqlite3SelectDelete(db, pSelect);
394d5d56523Sdanielk1977   }
395c3f9bad2Sdanielk1977 
396633ed08dSdanielk1977   return pTriggerStep;
397c3f9bad2Sdanielk1977 }
398c3f9bad2Sdanielk1977 
399c977f7f5Sdrh /*
400c977f7f5Sdrh ** Construct a trigger step that implements an UPDATE statement and return
401c977f7f5Sdrh ** a pointer to that trigger step.  The parser calls this routine when it
402c977f7f5Sdrh ** sees an UPDATE statement inside the body of a CREATE TRIGGER.
403c977f7f5Sdrh */
4044adee20fSdanielk1977 TriggerStep *sqlite3TriggerUpdateStep(
40517435752Sdrh   sqlite3 *db,         /* The database connection */
406c977f7f5Sdrh   Token *pTableName,   /* Name of the table to be updated */
407c977f7f5Sdrh   ExprList *pEList,    /* The SET clause: list of column and new values */
408c977f7f5Sdrh   Expr *pWhere,        /* The WHERE clause */
409c977f7f5Sdrh   int orconf           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
410c977f7f5Sdrh ){
41117435752Sdrh   TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
4120e3a6f3fSdrh   if( pTriggerStep==0 ){
413633e6d57Sdrh      sqlite3ExprListDelete(db, pEList);
414633e6d57Sdrh      sqlite3ExprDelete(db, pWhere);
4150e3a6f3fSdrh      return 0;
4160e3a6f3fSdrh   }
417c3f9bad2Sdanielk1977 
418633ed08dSdanielk1977   pTriggerStep->op = TK_UPDATE;
419633ed08dSdanielk1977   pTriggerStep->target  = *pTableName;
420633ed08dSdanielk1977   pTriggerStep->pExprList = pEList;
421633ed08dSdanielk1977   pTriggerStep->pWhere = pWhere;
422633ed08dSdanielk1977   pTriggerStep->orconf = orconf;
42317435752Sdrh   sqlitePersistTriggerStep(db, pTriggerStep);
424c3f9bad2Sdanielk1977 
425633ed08dSdanielk1977   return pTriggerStep;
426c3f9bad2Sdanielk1977 }
427c3f9bad2Sdanielk1977 
428c977f7f5Sdrh /*
429c977f7f5Sdrh ** Construct a trigger step that implements a DELETE statement and return
430c977f7f5Sdrh ** a pointer to that trigger step.  The parser calls this routine when it
431c977f7f5Sdrh ** sees a DELETE statement inside the body of a CREATE TRIGGER.
432c977f7f5Sdrh */
43317435752Sdrh TriggerStep *sqlite3TriggerDeleteStep(
43417435752Sdrh   sqlite3 *db,            /* Database connection */
43517435752Sdrh   Token *pTableName,      /* The table from which rows are deleted */
43617435752Sdrh   Expr *pWhere            /* The WHERE clause */
43717435752Sdrh ){
43817435752Sdrh   TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
439b63a53dcSdrh   if( pTriggerStep==0 ){
440633e6d57Sdrh     sqlite3ExprDelete(db, pWhere);
441b63a53dcSdrh     return 0;
442b63a53dcSdrh   }
443c3f9bad2Sdanielk1977 
444633ed08dSdanielk1977   pTriggerStep->op = TK_DELETE;
445633ed08dSdanielk1977   pTriggerStep->target  = *pTableName;
446633ed08dSdanielk1977   pTriggerStep->pWhere = pWhere;
447633ed08dSdanielk1977   pTriggerStep->orconf = OE_Default;
44817435752Sdrh   sqlitePersistTriggerStep(db, pTriggerStep);
449c3f9bad2Sdanielk1977 
450633ed08dSdanielk1977   return pTriggerStep;
451c3f9bad2Sdanielk1977 }
452c3f9bad2Sdanielk1977 
453c3f9bad2Sdanielk1977 /*
454633ed08dSdanielk1977 ** Recursively delete a Trigger structure
455c3f9bad2Sdanielk1977 */
456633e6d57Sdrh void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
457f0f258b1Sdrh   if( pTrigger==0 ) return;
458633e6d57Sdrh   sqlite3DeleteTriggerStep(db, pTrigger->step_list);
459633e6d57Sdrh   sqlite3DbFree(db, pTrigger->name);
460633e6d57Sdrh   sqlite3DbFree(db, pTrigger->table);
461633e6d57Sdrh   sqlite3ExprDelete(db, pTrigger->pWhen);
462633e6d57Sdrh   sqlite3IdListDelete(db, pTrigger->pColumns);
463633e6d57Sdrh   if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z);
464633e6d57Sdrh   sqlite3DbFree(db, pTrigger);
465633ed08dSdanielk1977 }
466633ed08dSdanielk1977 
467633ed08dSdanielk1977 /*
4688a41449eSdanielk1977 ** This function is called to drop a trigger from the database schema.
4698a41449eSdanielk1977 **
4708a41449eSdanielk1977 ** This may be called directly from the parser and therefore identifies
4718a41449eSdanielk1977 ** the trigger by name.  The sqlite3DropTriggerPtr() routine does the
4728a41449eSdanielk1977 ** same job as this routine except it takes a pointer to the trigger
4738a41449eSdanielk1977 ** instead of the trigger name.
4748a41449eSdanielk1977 **/
475fdd48a76Sdrh void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
476742f947bSdanielk1977   Trigger *pTrigger = 0;
477d24cc427Sdrh   int i;
478d24cc427Sdrh   const char *zDb;
479d24cc427Sdrh   const char *zName;
480d24cc427Sdrh   int nName;
4819bb575fdSdrh   sqlite3 *db = pParse->db;
482633ed08dSdanielk1977 
48317435752Sdrh   if( db->mallocFailed ) goto drop_trigger_cleanup;
4848a41449eSdanielk1977   if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
485c0391398Sdanielk1977     goto drop_trigger_cleanup;
486c0391398Sdanielk1977   }
4878e227875Sdanielk1977 
488d24cc427Sdrh   assert( pName->nSrc==1 );
489d24cc427Sdrh   zDb = pName->a[0].zDatabase;
490d24cc427Sdrh   zName = pName->a[0].zName;
491ea678832Sdrh   nName = sqlite3Strlen30(zName);
49253c0f748Sdanielk1977   for(i=OMIT_TEMPDB; i<db->nDb; i++){
493812d7a21Sdrh     int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
4944adee20fSdanielk1977     if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
495e4df0e74Sdrh     pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
496d24cc427Sdrh     if( pTrigger ) break;
497c3f9bad2Sdanielk1977   }
498d24cc427Sdrh   if( !pTrigger ){
499fdd48a76Sdrh     if( !noErr ){
5004adee20fSdanielk1977       sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
501fdd48a76Sdrh     }
502d24cc427Sdrh     goto drop_trigger_cleanup;
503d24cc427Sdrh   }
50474161705Sdrh   sqlite3DropTriggerPtr(pParse, pTrigger);
50579a519c0Sdrh 
50679a519c0Sdrh drop_trigger_cleanup:
507633e6d57Sdrh   sqlite3SrcListDelete(db, pName);
50879a519c0Sdrh }
50979a519c0Sdrh 
51079a519c0Sdrh /*
511956bc92cSdrh ** Return a pointer to the Table structure for the table that a trigger
512956bc92cSdrh ** is set on.
513956bc92cSdrh */
51474161705Sdrh static Table *tableOfTrigger(Trigger *pTrigger){
515ea678832Sdrh   int n = sqlite3Strlen30(pTrigger->table) + 1;
516aaf22685Sdanielk1977   return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
517956bc92cSdrh }
518956bc92cSdrh 
519956bc92cSdrh 
520956bc92cSdrh /*
52174161705Sdrh ** Drop a trigger given a pointer to that trigger.
52279a519c0Sdrh */
52374161705Sdrh void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
52479a519c0Sdrh   Table   *pTable;
52579a519c0Sdrh   Vdbe *v;
5269bb575fdSdrh   sqlite3 *db = pParse->db;
527956bc92cSdrh   int iDb;
52879a519c0Sdrh 
529da184236Sdanielk1977   iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
530956bc92cSdrh   assert( iDb>=0 && iDb<db->nDb );
53174161705Sdrh   pTable = tableOfTrigger(pTrigger);
532ed6c8671Sdrh   assert( pTable );
533da184236Sdanielk1977   assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
534e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION
535e5f9c644Sdrh   {
536e5f9c644Sdrh     int code = SQLITE_DROP_TRIGGER;
537956bc92cSdrh     const char *zDb = db->aDb[iDb].zName;
538956bc92cSdrh     const char *zTab = SCHEMA_TABLE(iDb);
539956bc92cSdrh     if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
5404adee20fSdanielk1977     if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
5414adee20fSdanielk1977       sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
54279a519c0Sdrh       return;
543ed6c8671Sdrh     }
544e5f9c644Sdrh   }
545e5f9c644Sdrh #endif
546c3f9bad2Sdanielk1977 
547f0f258b1Sdrh   /* Generate code to destroy the database record of the trigger.
548f0f258b1Sdrh   */
54943617e9aSdrh   assert( pTable!=0 );
55043617e9aSdrh   if( (v = sqlite3GetVdbe(pParse))!=0 ){
551f0f258b1Sdrh     int base;
5525719628aSdrh     static const VdbeOpList dropTrigger[] = {
5539b1b01bbSdrh       { OP_Rewind,     0, ADDR(9),  0},
5541db639ceSdrh       { OP_String8,    0, 1,        0}, /* 1 */
5551db639ceSdrh       { OP_Column,     0, 1,        2},
5561db639ceSdrh       { OP_Ne,         2, ADDR(8),  1},
5571db639ceSdrh       { OP_String8,    0, 1,        0}, /* 4: "trigger" */
5581db639ceSdrh       { OP_Column,     0, 0,        2},
5591db639ceSdrh       { OP_Ne,         2, ADDR(8),  1},
560f0f258b1Sdrh       { OP_Delete,     0, 0,        0},
5619b1b01bbSdrh       { OP_Next,       0, ADDR(1),  0}, /* 8 */
562f0f258b1Sdrh     };
563f0f258b1Sdrh 
564956bc92cSdrh     sqlite3BeginWriteOperation(pParse, 0, iDb);
565c00da105Sdanielk1977     sqlite3OpenMasterTable(pParse, iDb);
5664adee20fSdanielk1977     base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
56766a5167bSdrh     sqlite3VdbeChangeP4(v, base+1, pTrigger->name, 0);
5682400345aSdrh     sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
5699cbf3425Sdrh     sqlite3ChangeCookie(pParse, iDb);
57066a5167bSdrh     sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
57166a5167bSdrh     sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0);
5726ab3a2ecSdanielk1977     if( pParse->nMem<3 ){
5736ab3a2ecSdanielk1977       pParse->nMem = 3;
5746ab3a2ecSdanielk1977     }
575956bc92cSdrh   }
576f0f258b1Sdrh }
577f0f258b1Sdrh 
578c3f9bad2Sdanielk1977 /*
579956bc92cSdrh ** Remove a trigger from the hash tables of the sqlite* pointer.
580c3f9bad2Sdanielk1977 */
581956bc92cSdrh void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
5822f886d1dSdanielk1977   Hash *pHash = &(db->aDb[iDb].pSchema->trigHash);
583956bc92cSdrh   Trigger *pTrigger;
5842f886d1dSdanielk1977   pTrigger = sqlite3HashInsert(pHash, zName, sqlite3Strlen30(zName), 0);
585956bc92cSdrh   if( pTrigger ){
5862f886d1dSdanielk1977     if( pTrigger->pSchema==pTrigger->pTabSchema ){
5872f886d1dSdanielk1977       Table *pTab = tableOfTrigger(pTrigger);
5882f886d1dSdanielk1977       Trigger **pp;
5892f886d1dSdanielk1977       for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
5902f886d1dSdanielk1977       *pp = (*pp)->pNext;
591c3f9bad2Sdanielk1977     }
592633e6d57Sdrh     sqlite3DeleteTrigger(db, pTrigger);
593956bc92cSdrh     db->flags |= SQLITE_InternChanges;
594c3f9bad2Sdanielk1977   }
595c3f9bad2Sdanielk1977 }
596c3f9bad2Sdanielk1977 
597c977f7f5Sdrh /*
598c977f7f5Sdrh ** pEList is the SET clause of an UPDATE statement.  Each entry
599c977f7f5Sdrh ** in pEList is of the format <id>=<expr>.  If any of the entries
600c977f7f5Sdrh ** in pEList have an <id> which matches an identifier in pIdList,
601c977f7f5Sdrh ** then return TRUE.  If pIdList==NULL, then it is considered a
602c977f7f5Sdrh ** wildcard that matches anything.  Likewise if pEList==NULL then
603c977f7f5Sdrh ** it matches anything so always return true.  Return false only
604c977f7f5Sdrh ** if there is no match.
605c977f7f5Sdrh */
606c977f7f5Sdrh static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
607ad2d8307Sdrh   int e;
608ad2d8307Sdrh   if( !pIdList || !pEList ) return 1;
609f29ce559Sdanielk1977   for(e=0; e<pEList->nExpr; e++){
6104adee20fSdanielk1977     if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
611f29ce559Sdanielk1977   }
612c3f9bad2Sdanielk1977   return 0;
613c3f9bad2Sdanielk1977 }
614c3f9bad2Sdanielk1977 
615c3f9bad2Sdanielk1977 /*
6162f886d1dSdanielk1977 ** Return a list of all triggers on table pTab if there exists at least
6172f886d1dSdanielk1977 ** one trigger that must be fired when an operation of type 'op' is
6182f886d1dSdanielk1977 ** performed on the table, and, if that operation is an UPDATE, if at
6192f886d1dSdanielk1977 ** least one of the columns in pChanges is being modified.
620c3f9bad2Sdanielk1977 */
6212f886d1dSdanielk1977 Trigger *sqlite3TriggersExist(
6222f886d1dSdanielk1977   Parse *pParse,          /* Parse context */
623dca76841Sdrh   Table *pTab,            /* The table the contains the triggers */
624c3f9bad2Sdanielk1977   int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
6252f886d1dSdanielk1977   ExprList *pChanges,     /* Columns that change in an UPDATE statement */
6262f886d1dSdanielk1977   int *pMask              /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
627c977f7f5Sdrh ){
628dca76841Sdrh   int mask = 0;
6292f886d1dSdanielk1977   Trigger *pList = sqlite3TriggerList(pParse, pTab);
6302f886d1dSdanielk1977   Trigger *p;
6312f886d1dSdanielk1977   assert( pList==0 || IsVirtual(pTab)==0 );
6322f886d1dSdanielk1977   for(p=pList; p; p=p->pNext){
6332f886d1dSdanielk1977     if( p->op==op && checkColumnOverLap(p->pColumns, pChanges) ){
6342f886d1dSdanielk1977       mask |= p->tr_tm;
635c3f9bad2Sdanielk1977     }
636dca76841Sdrh   }
6372f886d1dSdanielk1977   if( pMask ){
6382f886d1dSdanielk1977     *pMask = mask;
6392f886d1dSdanielk1977   }
6402f886d1dSdanielk1977   return (mask ? pList : 0);
641c3f9bad2Sdanielk1977 }
642c3f9bad2Sdanielk1977 
643c977f7f5Sdrh /*
644f26e09c8Sdrh ** Convert the pStep->target token into a SrcList and return a pointer
645f26e09c8Sdrh ** to that SrcList.
646f26e09c8Sdrh **
647f26e09c8Sdrh ** This routine adds a specific database name, if needed, to the target when
648f26e09c8Sdrh ** forming the SrcList.  This prevents a trigger in one database from
649f26e09c8Sdrh ** referring to a target in another database.  An exception is when the
650f26e09c8Sdrh ** trigger is in TEMP in which case it can refer to any other database it
651f26e09c8Sdrh ** wants.
652f26e09c8Sdrh */
653f26e09c8Sdrh static SrcList *targetSrcList(
654f26e09c8Sdrh   Parse *pParse,       /* The parsing context */
655f26e09c8Sdrh   TriggerStep *pStep   /* The trigger containing the target token */
656f26e09c8Sdrh ){
657f26e09c8Sdrh   Token sDb;           /* Dummy database name token */
658f26e09c8Sdrh   int iDb;             /* Index of the database to use */
659f26e09c8Sdrh   SrcList *pSrc;       /* SrcList to be returned */
660f26e09c8Sdrh 
661da184236Sdanielk1977   iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
662f26e09c8Sdrh   if( iDb==0 || iDb>=2 ){
663f26e09c8Sdrh     assert( iDb<pParse->db->nDb );
6642646da7eSdrh     sDb.z = (u8*)pParse->db->aDb[iDb].zName;
665ea678832Sdrh     sDb.n = sqlite3Strlen30((char*)sDb.z);
66617435752Sdrh     pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target);
667f26e09c8Sdrh   } else {
66817435752Sdrh     pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
669f26e09c8Sdrh   }
670f26e09c8Sdrh   return pSrc;
671f26e09c8Sdrh }
672f26e09c8Sdrh 
673f26e09c8Sdrh /*
674c977f7f5Sdrh ** Generate VDBE code for zero or more statements inside the body of a
675c977f7f5Sdrh ** trigger.
676c977f7f5Sdrh */
677c3f9bad2Sdanielk1977 static int codeTriggerProgram(
678c977f7f5Sdrh   Parse *pParse,            /* The parser context */
679c977f7f5Sdrh   TriggerStep *pStepList,   /* List of statements inside the trigger body */
680c977f7f5Sdrh   int orconfin              /* Conflict algorithm. (OE_Abort, etc) */
681633ed08dSdanielk1977 ){
682633ed08dSdanielk1977   TriggerStep * pTriggerStep = pStepList;
683c3f9bad2Sdanielk1977   int orconf;
684344737f6Sdrh   Vdbe *v = pParse->pVdbe;
68517435752Sdrh   sqlite3 *db = pParse->db;
686c3f9bad2Sdanielk1977 
687344737f6Sdrh   assert( pTriggerStep!=0 );
688344737f6Sdrh   assert( v!=0 );
68966a5167bSdrh   sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0);
690d4e70ebdSdrh   VdbeComment((v, "begin trigger %s", pStepList->pTrig->name));
691633ed08dSdanielk1977   while( pTriggerStep ){
692*ceea3321Sdrh     sqlite3ExprCacheClear(pParse);
693633ed08dSdanielk1977     orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
694c3f9bad2Sdanielk1977     pParse->trigStack->orconf = orconf;
695633ed08dSdanielk1977     switch( pTriggerStep->op ){
696c3f9bad2Sdanielk1977       case TK_SELECT: {
6976ab3a2ecSdanielk1977         Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect, 0);
69828f45914Sdrh         if( ss ){
6991013c932Sdrh           SelectDest dest;
7001013c932Sdrh 
7011013c932Sdrh           sqlite3SelectDestInit(&dest, SRT_Discard, 0);
7027d10d5a6Sdrh           sqlite3Select(pParse, ss, &dest);
703633e6d57Sdrh           sqlite3SelectDelete(db, ss);
70428f45914Sdrh         }
705c3f9bad2Sdanielk1977         break;
706c3f9bad2Sdanielk1977       }
707c3f9bad2Sdanielk1977       case TK_UPDATE: {
708113088ecSdrh         SrcList *pSrc;
709f26e09c8Sdrh         pSrc = targetSrcList(pParse, pTriggerStep);
71066a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
7114adee20fSdanielk1977         sqlite3Update(pParse, pSrc,
7126ab3a2ecSdanielk1977                 sqlite3ExprListDup(db, pTriggerStep->pExprList, 0),
7136ab3a2ecSdanielk1977                 sqlite3ExprDup(db, pTriggerStep->pWhere, 0), orconf);
71466a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
715c3f9bad2Sdanielk1977         break;
716c3f9bad2Sdanielk1977       }
717c3f9bad2Sdanielk1977       case TK_INSERT: {
718113088ecSdrh         SrcList *pSrc;
719f26e09c8Sdrh         pSrc = targetSrcList(pParse, pTriggerStep);
72066a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
7214adee20fSdanielk1977         sqlite3Insert(pParse, pSrc,
7226ab3a2ecSdanielk1977           sqlite3ExprListDup(db, pTriggerStep->pExprList, 0),
7236ab3a2ecSdanielk1977           sqlite3SelectDup(db, pTriggerStep->pSelect, 0),
72417435752Sdrh           sqlite3IdListDup(db, pTriggerStep->pIdList), orconf);
72566a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
726c3f9bad2Sdanielk1977         break;
727c3f9bad2Sdanielk1977       }
728c3f9bad2Sdanielk1977       case TK_DELETE: {
729113088ecSdrh         SrcList *pSrc;
73066a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
731f26e09c8Sdrh         pSrc = targetSrcList(pParse, pTriggerStep);
73217435752Sdrh         sqlite3DeleteFrom(pParse, pSrc,
7336ab3a2ecSdanielk1977                           sqlite3ExprDup(db, pTriggerStep->pWhere, 0));
73466a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
735c3f9bad2Sdanielk1977         break;
736c3f9bad2Sdanielk1977       }
737c3f9bad2Sdanielk1977       default:
738c3f9bad2Sdanielk1977         assert(0);
739c3f9bad2Sdanielk1977     }
740633ed08dSdanielk1977     pTriggerStep = pTriggerStep->pNext;
741c3f9bad2Sdanielk1977   }
74266a5167bSdrh   sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
743d4e70ebdSdrh   VdbeComment((v, "end trigger %s", pStepList->pTrig->name));
744c3f9bad2Sdanielk1977 
745c3f9bad2Sdanielk1977   return 0;
746c3f9bad2Sdanielk1977 }
747c3f9bad2Sdanielk1977 
748633ed08dSdanielk1977 /*
749633ed08dSdanielk1977 ** This is called to code FOR EACH ROW triggers.
750633ed08dSdanielk1977 **
751633ed08dSdanielk1977 ** When the code that this function generates is executed, the following
752633ed08dSdanielk1977 ** must be true:
753c977f7f5Sdrh **
754c977f7f5Sdrh ** 1. No cursors may be open in the main database.  (But newIdx and oldIdx
755c977f7f5Sdrh **    can be indices of cursors in temporary tables.  See below.)
756c977f7f5Sdrh **
757633ed08dSdanielk1977 ** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
758633ed08dSdanielk1977 **    a temporary vdbe cursor (index newIdx) must be open and pointing at
759633ed08dSdanielk1977 **    a row containing values to be substituted for new.* expressions in the
760633ed08dSdanielk1977 **    trigger program(s).
761c977f7f5Sdrh **
762633ed08dSdanielk1977 ** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
763633ed08dSdanielk1977 **    a temporary vdbe cursor (index oldIdx) must be open and pointing at
764633ed08dSdanielk1977 **    a row containing values to be substituted for old.* expressions in the
765633ed08dSdanielk1977 **    trigger program(s).
766633ed08dSdanielk1977 **
7678f2c54e6Sdanielk1977 ** If they are not NULL, the piOldColMask and piNewColMask output variables
7688f2c54e6Sdanielk1977 ** are set to values that describe the columns used by the trigger program
7698f2c54e6Sdanielk1977 ** in the OLD.* and NEW.* tables respectively. If column N of the
7708f2c54e6Sdanielk1977 ** pseudo-table is read at least once, the corresponding bit of the output
7718f2c54e6Sdanielk1977 ** mask is set. If a column with an index greater than 32 is read, the
7728f2c54e6Sdanielk1977 ** output mask is set to the special value 0xffffffff.
7738f2c54e6Sdanielk1977 **
774633ed08dSdanielk1977 */
7754adee20fSdanielk1977 int sqlite3CodeRowTrigger(
776c3f9bad2Sdanielk1977   Parse *pParse,       /* Parse context */
7772f886d1dSdanielk1977   Trigger *pTrigger,   /* List of triggers on table pTab */
778c3f9bad2Sdanielk1977   int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
779633ed08dSdanielk1977   ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
780dca76841Sdrh   int tr_tm,           /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
781633ed08dSdanielk1977   Table *pTab,         /* The table to code triggers from */
782633ed08dSdanielk1977   int newIdx,          /* The indice of the "new" row to access */
783633ed08dSdanielk1977   int oldIdx,          /* The indice of the "old" row to access */
7846f34903eSdanielk1977   int orconf,          /* ON CONFLICT policy */
7858f2c54e6Sdanielk1977   int ignoreJump,      /* Instruction to jump to for RAISE(IGNORE) */
7868f2c54e6Sdanielk1977   u32 *piOldColMask,   /* OUT: Mask of columns used from the OLD.* table */
7878f2c54e6Sdanielk1977   u32 *piNewColMask    /* OUT: Mask of columns used from the NEW.* table */
788c977f7f5Sdrh ){
789eecfb3eeSdanielk1977   Trigger *p;
7900e359b30Sdrh   sqlite3 *db = pParse->db;
79167040462Sdrh   TriggerStack trigStackEntry;
792c3f9bad2Sdanielk1977 
7938f2c54e6Sdanielk1977   trigStackEntry.oldColMask = 0;
7948f2c54e6Sdanielk1977   trigStackEntry.newColMask = 0;
7958f2c54e6Sdanielk1977 
796c3f9bad2Sdanielk1977   assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
797dca76841Sdrh   assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
798c3f9bad2Sdanielk1977 
799633ed08dSdanielk1977   assert(newIdx != -1 || oldIdx != -1);
800c3f9bad2Sdanielk1977 
8012f886d1dSdanielk1977   for(p=pTrigger; p; p=p->pNext){
802c3f9bad2Sdanielk1977     int fire_this = 0;
803c3f9bad2Sdanielk1977 
804eecfb3eeSdanielk1977     /* Determine whether we should code this trigger */
805eecfb3eeSdanielk1977     if(
806eecfb3eeSdanielk1977       p->op==op &&
807eecfb3eeSdanielk1977       p->tr_tm==tr_tm &&
808932083c6Sdanielk1977       (p->pSchema==p->pTabSchema || p->pSchema==db->aDb[1].pSchema) &&
809eecfb3eeSdanielk1977       (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges))
810eecfb3eeSdanielk1977     ){
811eecfb3eeSdanielk1977       TriggerStack *pS;      /* Pointer to trigger-stack entry */
81274161705Sdrh       for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}
813eecfb3eeSdanielk1977       if( !pS ){
814c3f9bad2Sdanielk1977         fire_this = 1;
815c3f9bad2Sdanielk1977       }
816229caa36Sdrh #if 0    /* Give no warning for recursive triggers.  Just do not do them */
817229caa36Sdrh       else{
818229caa36Sdrh         sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)",
819229caa36Sdrh             p->name);
820229caa36Sdrh         return SQLITE_ERROR;
821229caa36Sdrh       }
822229caa36Sdrh #endif
823f29ce559Sdanielk1977     }
824c3f9bad2Sdanielk1977 
82567040462Sdrh     if( fire_this ){
826c3f9bad2Sdanielk1977       int endTrigger;
827c3f9bad2Sdanielk1977       Expr * whenExpr;
82885e2096fSdrh       AuthContext sContext;
829b3bce662Sdanielk1977       NameContext sNC;
830c3f9bad2Sdanielk1977 
831949f9cd5Sdrh #ifndef SQLITE_OMIT_TRACE
832949f9cd5Sdrh       sqlite3VdbeAddOp4(pParse->pVdbe, OP_Trace, 0, 0, 0,
8330e359b30Sdrh                         sqlite3MPrintf(db, "-- TRIGGER %s", p->name),
834949f9cd5Sdrh                         P4_DYNAMIC);
835949f9cd5Sdrh #endif
836b3bce662Sdanielk1977       memset(&sNC, 0, sizeof(sNC));
837b3bce662Sdanielk1977       sNC.pParse = pParse;
838c3f9bad2Sdanielk1977 
839c3f9bad2Sdanielk1977       /* Push an entry on to the trigger stack */
840eecfb3eeSdanielk1977       trigStackEntry.pTrigger = p;
84167040462Sdrh       trigStackEntry.newIdx = newIdx;
84267040462Sdrh       trigStackEntry.oldIdx = oldIdx;
84367040462Sdrh       trigStackEntry.pTab = pTab;
84467040462Sdrh       trigStackEntry.pNext = pParse->trigStack;
84567040462Sdrh       trigStackEntry.ignoreJump = ignoreJump;
84667040462Sdrh       pParse->trigStack = &trigStackEntry;
847eecfb3eeSdanielk1977       sqlite3AuthContextPush(pParse, &sContext, p->name);
848c3f9bad2Sdanielk1977 
849c3f9bad2Sdanielk1977       /* code the WHEN clause */
8504adee20fSdanielk1977       endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
8516ab3a2ecSdanielk1977       whenExpr = sqlite3ExprDup(db, p->pWhen, 0);
8527d10d5a6Sdrh       if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
85367040462Sdrh         pParse->trigStack = trigStackEntry.pNext;
854633e6d57Sdrh         sqlite3ExprDelete(db, whenExpr);
855c3f9bad2Sdanielk1977         return 1;
856c3f9bad2Sdanielk1977       }
85735573356Sdrh       sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL);
858633e6d57Sdrh       sqlite3ExprDelete(db, whenExpr);
859c3f9bad2Sdanielk1977 
860eecfb3eeSdanielk1977       codeTriggerProgram(pParse, p->step_list, orconf);
861c3f9bad2Sdanielk1977 
862c3f9bad2Sdanielk1977       /* Pop the entry off the trigger stack */
86367040462Sdrh       pParse->trigStack = trigStackEntry.pNext;
8644adee20fSdanielk1977       sqlite3AuthContextPop(&sContext);
865c3f9bad2Sdanielk1977 
8664adee20fSdanielk1977       sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
867c3f9bad2Sdanielk1977     }
868c3f9bad2Sdanielk1977   }
8698f2c54e6Sdanielk1977   if( piOldColMask ) *piOldColMask |= trigStackEntry.oldColMask;
8708f2c54e6Sdanielk1977   if( piNewColMask ) *piNewColMask |= trigStackEntry.newColMask;
871c3f9bad2Sdanielk1977   return 0;
872c3f9bad2Sdanielk1977 }
873b7f9164eSdrh #endif /* !defined(SQLITE_OMIT_TRIGGER) */
874