xref: /sqlite-3.40.0/src/trigger.c (revision ea678832)
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*ea678832Sdrh ** $Id: trigger.c,v 1.132 2008/12/10 19:26:24 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 /*
37f0f258b1Sdrh ** This is called by the parser when it sees a CREATE TRIGGER statement
38f0f258b1Sdrh ** up to the point of the BEGIN before the trigger actions.  A Trigger
39f0f258b1Sdrh ** structure is generated based on the information available and stored
40f0f258b1Sdrh ** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
414adee20fSdanielk1977 ** sqlite3FinishTrigger() function is called to complete the trigger
42f0f258b1Sdrh ** construction process.
43c3f9bad2Sdanielk1977 */
444adee20fSdanielk1977 void sqlite3BeginTrigger(
45c3f9bad2Sdanielk1977   Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
46ef2cb63eSdanielk1977   Token *pName1,      /* The name of the trigger */
47ef2cb63eSdanielk1977   Token *pName2,      /* The name of the trigger */
48d702fccbSdanielk1977   int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
49c3f9bad2Sdanielk1977   int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
50633ed08dSdanielk1977   IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
51d24cc427Sdrh   SrcList *pTableName,/* The name of the table/view the trigger applies to */
52c3f9bad2Sdanielk1977   Expr *pWhen,        /* WHEN clause */
53fdd48a76Sdrh   int isTemp,         /* True if the TEMPORARY keyword is present */
54fdd48a76Sdrh   int noErr           /* Suppress errors if the trigger already exists */
559adf9ac4Sdrh ){
56d5d56523Sdanielk1977   Trigger *pTrigger = 0;
57ef2cb63eSdanielk1977   Table *pTab;
58e5f9c644Sdrh   char *zName = 0;        /* Name of the trigger */
599bb575fdSdrh   sqlite3 *db = pParse->db;
60ef2cb63eSdanielk1977   int iDb;                /* The database to store the trigger in */
61ef2cb63eSdanielk1977   Token *pName;           /* The unqualified db name */
624312db55Sdrh   DbFixer sFix;
63da184236Sdanielk1977   int iTabDb;
64ed6c8671Sdrh 
6543617e9aSdrh   assert( pName1!=0 );   /* pName1->z might be NULL, but not pName1 itself */
6643617e9aSdrh   assert( pName2!=0 );
67aa78bec9Sdrh   assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE );
68aa78bec9Sdrh   assert( op>0 && op<0xff );
69ef2cb63eSdanielk1977   if( isTemp ){
70ef2cb63eSdanielk1977     /* If TEMP was specified, then the trigger name may not be qualified. */
7143617e9aSdrh     if( pName2->n>0 ){
72ef2cb63eSdanielk1977       sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
73ef2cb63eSdanielk1977       goto trigger_cleanup;
74ef2cb63eSdanielk1977     }
75ef2cb63eSdanielk1977     iDb = 1;
76ef2cb63eSdanielk1977     pName = pName1;
77ef2cb63eSdanielk1977   }else{
78ef2cb63eSdanielk1977     /* Figure out the db that the the trigger will be created in */
79ef2cb63eSdanielk1977     iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
80ef2cb63eSdanielk1977     if( iDb<0 ){
81ef2cb63eSdanielk1977       goto trigger_cleanup;
82ef2cb63eSdanielk1977     }
83ef2cb63eSdanielk1977   }
84ef2cb63eSdanielk1977 
85ef2cb63eSdanielk1977   /* If the trigger name was unqualified, and the table is a temp table,
86ef2cb63eSdanielk1977   ** then set iDb to 1 to create the trigger in the temporary database.
87ef2cb63eSdanielk1977   ** If sqlite3SrcListLookup() returns 0, indicating the table does not
88ef2cb63eSdanielk1977   ** exist, the error is caught by the block below.
89c3f9bad2Sdanielk1977   */
9017435752Sdrh   if( !pTableName || db->mallocFailed ){
916f7adc8aSdrh     goto trigger_cleanup;
926f7adc8aSdrh   }
93ef2cb63eSdanielk1977   pTab = sqlite3SrcListLookup(pParse, pTableName);
94da184236Sdanielk1977   if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
95ef2cb63eSdanielk1977     iDb = 1;
96ef2cb63eSdanielk1977   }
97ef2cb63eSdanielk1977 
98ef2cb63eSdanielk1977   /* Ensure the table name matches database name and that the table exists */
9917435752Sdrh   if( db->mallocFailed ) goto trigger_cleanup;
100d24cc427Sdrh   assert( pTableName->nSrc==1 );
101ef2cb63eSdanielk1977   if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
102ef2cb63eSdanielk1977       sqlite3FixSrcList(&sFix, pTableName) ){
1034312db55Sdrh     goto trigger_cleanup;
104f26e09c8Sdrh   }
105ef2cb63eSdanielk1977   pTab = sqlite3SrcListLookup(pParse, pTableName);
106ef2cb63eSdanielk1977   if( !pTab ){
107ef2cb63eSdanielk1977     /* The table does not exist. */
108d24cc427Sdrh     goto trigger_cleanup;
109d24cc427Sdrh   }
1104cbdda9eSdrh   if( IsVirtual(pTab) ){
1114cbdda9eSdrh     sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
1124cbdda9eSdrh     goto trigger_cleanup;
1134cbdda9eSdrh   }
114d24cc427Sdrh 
115d8123366Sdanielk1977   /* Check that the trigger name is not reserved and that no trigger of the
116d8123366Sdanielk1977   ** specified name exists */
11717435752Sdrh   zName = sqlite3NameFromToken(db, pName);
118d8123366Sdanielk1977   if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
119d8123366Sdanielk1977     goto trigger_cleanup;
120d8123366Sdanielk1977   }
121aa78bec9Sdrh   if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
122*ea678832Sdrh                       zName, sqlite3Strlen30(zName)) ){
123fdd48a76Sdrh     if( !noErr ){
1244adee20fSdanielk1977       sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
125fdd48a76Sdrh     }
126c3f9bad2Sdanielk1977     goto trigger_cleanup;
127c3f9bad2Sdanielk1977   }
128ef2cb63eSdanielk1977 
129ef2cb63eSdanielk1977   /* Do not create a trigger on a system table */
130dca76841Sdrh   if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
1314adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
132e0bc4048Sdrh     pParse->nErr++;
133e0bc4048Sdrh     goto trigger_cleanup;
134e0bc4048Sdrh   }
135ef2cb63eSdanielk1977 
136ef2cb63eSdanielk1977   /* INSTEAD of triggers are only for views and views only support INSTEAD
137ef2cb63eSdanielk1977   ** of triggers.
138ef2cb63eSdanielk1977   */
139ef2cb63eSdanielk1977   if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
1404adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
141da93d238Sdrh         (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
142d702fccbSdanielk1977     goto trigger_cleanup;
143d702fccbSdanielk1977   }
144ef2cb63eSdanielk1977   if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
1454adee20fSdanielk1977     sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
146da93d238Sdrh         " trigger on table: %S", pTableName, 0);
147d702fccbSdanielk1977     goto trigger_cleanup;
148d702fccbSdanielk1977   }
149da184236Sdanielk1977   iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
150ef2cb63eSdanielk1977 
151e5f9c644Sdrh #ifndef SQLITE_OMIT_AUTHORIZATION
152e5f9c644Sdrh   {
153e5f9c644Sdrh     int code = SQLITE_CREATE_TRIGGER;
154da184236Sdanielk1977     const char *zDb = db->aDb[iTabDb].zName;
155e22a334bSdrh     const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
156da184236Sdanielk1977     if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
157ef2cb63eSdanielk1977     if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
158ed6c8671Sdrh       goto trigger_cleanup;
159ed6c8671Sdrh     }
160da184236Sdanielk1977     if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
16177ad4e41Sdrh       goto trigger_cleanup;
16277ad4e41Sdrh     }
163d702fccbSdanielk1977   }
164e5f9c644Sdrh #endif
165d702fccbSdanielk1977 
166ef2cb63eSdanielk1977   /* INSTEAD OF triggers can only appear on views and BEFORE triggers
1675cf590c1Sdrh   ** cannot appear on views.  So we might as well translate every
1685cf590c1Sdrh   ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code
1695cf590c1Sdrh   ** elsewhere.
1705cf590c1Sdrh   */
171d702fccbSdanielk1977   if (tr_tm == TK_INSTEAD){
172d702fccbSdanielk1977     tr_tm = TK_BEFORE;
173c3f9bad2Sdanielk1977   }
174c3f9bad2Sdanielk1977 
175c3f9bad2Sdanielk1977   /* Build the Trigger object */
17617435752Sdrh   pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
177ef2cb63eSdanielk1977   if( pTrigger==0 ) goto trigger_cleanup;
178ef2cb63eSdanielk1977   pTrigger->name = zName;
179e5f9c644Sdrh   zName = 0;
18017435752Sdrh   pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
181da184236Sdanielk1977   pTrigger->pSchema = db->aDb[iDb].pSchema;
182aaf22685Sdanielk1977   pTrigger->pTabSchema = pTab->pSchema;
183aa78bec9Sdrh   pTrigger->op = (u8)op;
184dca76841Sdrh   pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
18517435752Sdrh   pTrigger->pWhen = sqlite3ExprDup(db, pWhen);
18617435752Sdrh   pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
18717435752Sdrh   sqlite3TokenCopy(db, &pTrigger->nameToken,pName);
188f0f258b1Sdrh   assert( pParse->pNewTrigger==0 );
189ef2cb63eSdanielk1977   pParse->pNewTrigger = pTrigger;
190f0f258b1Sdrh 
191f0f258b1Sdrh trigger_cleanup:
192633e6d57Sdrh   sqlite3DbFree(db, zName);
193633e6d57Sdrh   sqlite3SrcListDelete(db, pTableName);
194633e6d57Sdrh   sqlite3IdListDelete(db, pColumns);
195633e6d57Sdrh   sqlite3ExprDelete(db, pWhen);
196d5d56523Sdanielk1977   if( !pParse->pNewTrigger ){
197633e6d57Sdrh     sqlite3DeleteTrigger(db, pTrigger);
198d5d56523Sdanielk1977   }else{
199d5d56523Sdanielk1977     assert( pParse->pNewTrigger==pTrigger );
200d5d56523Sdanielk1977   }
201f0f258b1Sdrh }
202f0f258b1Sdrh 
203f0f258b1Sdrh /*
204f0f258b1Sdrh ** This routine is called after all of the trigger actions have been parsed
205f0f258b1Sdrh ** in order to complete the process of building the trigger.
206f0f258b1Sdrh */
2074adee20fSdanielk1977 void sqlite3FinishTrigger(
208f0f258b1Sdrh   Parse *pParse,          /* Parser context */
209f0f258b1Sdrh   TriggerStep *pStepList, /* The triggered program */
210f0f258b1Sdrh   Token *pAll             /* Token that describes the complete CREATE TRIGGER */
211f0f258b1Sdrh ){
212bfb9e35bSdanielk1977   Trigger *pTrig = 0;     /* The trigger whose construction is finishing up */
2139bb575fdSdrh   sqlite3 *db = pParse->db;  /* The database */
214f26e09c8Sdrh   DbFixer sFix;
215da184236Sdanielk1977   int iDb;                   /* Database containing the trigger */
216f0f258b1Sdrh 
217bfb9e35bSdanielk1977   pTrig = pParse->pNewTrigger;
218f0f258b1Sdrh   pParse->pNewTrigger = 0;
2192e588c75Sdanielk1977   if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
220da184236Sdanielk1977   iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
221bfb9e35bSdanielk1977   pTrig->step_list = pStepList;
222a69d9168Sdrh   while( pStepList ){
223bfb9e35bSdanielk1977     pStepList->pTrig = pTrig;
224a69d9168Sdrh     pStepList = pStepList->pNext;
225a69d9168Sdrh   }
226da184236Sdanielk1977   if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
227bfb9e35bSdanielk1977           && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
228f26e09c8Sdrh     goto triggerfinish_cleanup;
229f26e09c8Sdrh   }
230c3f9bad2Sdanielk1977 
231c3f9bad2Sdanielk1977   /* if we are not initializing, and this trigger is not on a TEMP table,
2329adf9ac4Sdrh   ** build the sqlite_master entry
2339adf9ac4Sdrh   */
2341d85d931Sdrh   if( !db->init.busy ){
235c977f7f5Sdrh     Vdbe *v;
2362d401ab8Sdrh     char *z;
237c3f9bad2Sdanielk1977 
238c3f9bad2Sdanielk1977     /* Make an entry in the sqlite_master table */
2394adee20fSdanielk1977     v = sqlite3GetVdbe(pParse);
240f0f258b1Sdrh     if( v==0 ) goto triggerfinish_cleanup;
241da184236Sdanielk1977     sqlite3BeginWriteOperation(pParse, 0, iDb);
2422d401ab8Sdrh     z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
2432d401ab8Sdrh     sqlite3NestedParse(pParse,
2442d401ab8Sdrh        "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
2452d401ab8Sdrh        db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name,
2462d401ab8Sdrh        pTrig->table, z);
247633e6d57Sdrh     sqlite3DbFree(db, z);
2489cbf3425Sdrh     sqlite3ChangeCookie(pParse, iDb);
24966a5167bSdrh     sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
25066a5167bSdrh         db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
2511e536953Sdanielk1977     );
252c3f9bad2Sdanielk1977   }
253c3f9bad2Sdanielk1977 
254956bc92cSdrh   if( db->init.busy ){
255aaf22685Sdanielk1977     int n;
256f0f258b1Sdrh     Table *pTab;
257d5d56523Sdanielk1977     Trigger *pDel;
258da184236Sdanielk1977     pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
259*ea678832Sdrh                      pTrig->name, sqlite3Strlen30(pTrig->name), pTrig);
260d5d56523Sdanielk1977     if( pDel ){
261f3a65f7eSdrh       assert( pDel==pTrig );
262f3a65f7eSdrh       db->mallocFailed = 1;
263d5d56523Sdanielk1977       goto triggerfinish_cleanup;
264d5d56523Sdanielk1977     }
265*ea678832Sdrh     n = sqlite3Strlen30(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:
274633e6d57Sdrh   sqlite3DeleteTrigger(db, pTrig);
275bfb9e35bSdanielk1977   assert( !pParse->pNewTrigger );
276633e6d57Sdrh   sqlite3DeleteTriggerStep(db, 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
28217435752Sdrh ** from sqlite3_malloc().  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 */
28917435752Sdrh static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){
2904b59ab5eSdrh   if( p->target.z ){
29117435752Sdrh     p->target.z = (u8*)sqlite3DbStrNDup(db, (char*)p->target.z, p->target.n);
2924b59ab5eSdrh     p->target.dyn = 1;
2934b59ab5eSdrh   }
2944b59ab5eSdrh   if( p->pSelect ){
29517435752Sdrh     Select *pNew = sqlite3SelectDup(db, p->pSelect);
296633e6d57Sdrh     sqlite3SelectDelete(db, p->pSelect);
2974b59ab5eSdrh     p->pSelect = pNew;
2984b59ab5eSdrh   }
2994b59ab5eSdrh   if( p->pWhere ){
30017435752Sdrh     Expr *pNew = sqlite3ExprDup(db, p->pWhere);
301633e6d57Sdrh     sqlite3ExprDelete(db, p->pWhere);
3024b59ab5eSdrh     p->pWhere = pNew;
3034b59ab5eSdrh   }
3044b59ab5eSdrh   if( p->pExprList ){
30517435752Sdrh     ExprList *pNew = sqlite3ExprListDup(db, p->pExprList);
306633e6d57Sdrh     sqlite3ExprListDelete(db, p->pExprList);
3074b59ab5eSdrh     p->pExprList = pNew;
3084b59ab5eSdrh   }
3094b59ab5eSdrh   if( p->pIdList ){
31017435752Sdrh     IdList *pNew = sqlite3IdListDup(db, p->pIdList);
311633e6d57Sdrh     sqlite3IdListDelete(db, 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 */
32317435752Sdrh TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
32417435752Sdrh   TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
3252e588c75Sdanielk1977   if( pTriggerStep==0 ) {
326633e6d57Sdrh     sqlite3SelectDelete(db, pSelect);
3272e588c75Sdanielk1977     return 0;
3282e588c75Sdanielk1977   }
329c3f9bad2Sdanielk1977 
330633ed08dSdanielk1977   pTriggerStep->op = TK_SELECT;
331633ed08dSdanielk1977   pTriggerStep->pSelect = pSelect;
332633ed08dSdanielk1977   pTriggerStep->orconf = OE_Default;
33317435752Sdrh   sqlitePersistTriggerStep(db, 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(
34617435752Sdrh   sqlite3 *db,        /* The database connection */
347c977f7f5Sdrh   Token *pTableName,  /* Name of the table into which we insert */
348c977f7f5Sdrh   IdList *pColumn,    /* List of columns in pTableName to insert into */
349c977f7f5Sdrh   ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
350c977f7f5Sdrh   Select *pSelect,    /* A SELECT statement that supplies values */
351c977f7f5Sdrh   int orconf          /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
352633ed08dSdanielk1977 ){
353f3a65f7eSdrh   TriggerStep *pTriggerStep;
354c3f9bad2Sdanielk1977 
355633ed08dSdanielk1977   assert(pEList == 0 || pSelect == 0);
356f3a65f7eSdrh   assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
357c3f9bad2Sdanielk1977 
358f3a65f7eSdrh   pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
359d5d56523Sdanielk1977   if( pTriggerStep ){
360633ed08dSdanielk1977     pTriggerStep->op = TK_INSERT;
361633ed08dSdanielk1977     pTriggerStep->pSelect = pSelect;
362633ed08dSdanielk1977     pTriggerStep->target  = *pTableName;
363633ed08dSdanielk1977     pTriggerStep->pIdList = pColumn;
364633ed08dSdanielk1977     pTriggerStep->pExprList = pEList;
365633ed08dSdanielk1977     pTriggerStep->orconf = orconf;
36617435752Sdrh     sqlitePersistTriggerStep(db, pTriggerStep);
367d5d56523Sdanielk1977   }else{
368633e6d57Sdrh     sqlite3IdListDelete(db, pColumn);
369633e6d57Sdrh     sqlite3ExprListDelete(db, pEList);
370633e6d57Sdrh     sqlite3SelectDelete(db, pSelect);
371d5d56523Sdanielk1977   }
372c3f9bad2Sdanielk1977 
373633ed08dSdanielk1977   return pTriggerStep;
374c3f9bad2Sdanielk1977 }
375c3f9bad2Sdanielk1977 
376c977f7f5Sdrh /*
377c977f7f5Sdrh ** Construct a trigger step that implements an UPDATE statement and return
378c977f7f5Sdrh ** a pointer to that trigger step.  The parser calls this routine when it
379c977f7f5Sdrh ** sees an UPDATE statement inside the body of a CREATE TRIGGER.
380c977f7f5Sdrh */
3814adee20fSdanielk1977 TriggerStep *sqlite3TriggerUpdateStep(
38217435752Sdrh   sqlite3 *db,         /* The database connection */
383c977f7f5Sdrh   Token *pTableName,   /* Name of the table to be updated */
384c977f7f5Sdrh   ExprList *pEList,    /* The SET clause: list of column and new values */
385c977f7f5Sdrh   Expr *pWhere,        /* The WHERE clause */
386c977f7f5Sdrh   int orconf           /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
387c977f7f5Sdrh ){
38817435752Sdrh   TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
3890e3a6f3fSdrh   if( pTriggerStep==0 ){
390633e6d57Sdrh      sqlite3ExprListDelete(db, pEList);
391633e6d57Sdrh      sqlite3ExprDelete(db, pWhere);
3920e3a6f3fSdrh      return 0;
3930e3a6f3fSdrh   }
394c3f9bad2Sdanielk1977 
395633ed08dSdanielk1977   pTriggerStep->op = TK_UPDATE;
396633ed08dSdanielk1977   pTriggerStep->target  = *pTableName;
397633ed08dSdanielk1977   pTriggerStep->pExprList = pEList;
398633ed08dSdanielk1977   pTriggerStep->pWhere = pWhere;
399633ed08dSdanielk1977   pTriggerStep->orconf = orconf;
40017435752Sdrh   sqlitePersistTriggerStep(db, pTriggerStep);
401c3f9bad2Sdanielk1977 
402633ed08dSdanielk1977   return pTriggerStep;
403c3f9bad2Sdanielk1977 }
404c3f9bad2Sdanielk1977 
405c977f7f5Sdrh /*
406c977f7f5Sdrh ** Construct a trigger step that implements a DELETE statement and return
407c977f7f5Sdrh ** a pointer to that trigger step.  The parser calls this routine when it
408c977f7f5Sdrh ** sees a DELETE statement inside the body of a CREATE TRIGGER.
409c977f7f5Sdrh */
41017435752Sdrh TriggerStep *sqlite3TriggerDeleteStep(
41117435752Sdrh   sqlite3 *db,            /* Database connection */
41217435752Sdrh   Token *pTableName,      /* The table from which rows are deleted */
41317435752Sdrh   Expr *pWhere            /* The WHERE clause */
41417435752Sdrh ){
41517435752Sdrh   TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
416b63a53dcSdrh   if( pTriggerStep==0 ){
417633e6d57Sdrh     sqlite3ExprDelete(db, pWhere);
418b63a53dcSdrh     return 0;
419b63a53dcSdrh   }
420c3f9bad2Sdanielk1977 
421633ed08dSdanielk1977   pTriggerStep->op = TK_DELETE;
422633ed08dSdanielk1977   pTriggerStep->target  = *pTableName;
423633ed08dSdanielk1977   pTriggerStep->pWhere = pWhere;
424633ed08dSdanielk1977   pTriggerStep->orconf = OE_Default;
42517435752Sdrh   sqlitePersistTriggerStep(db, pTriggerStep);
426c3f9bad2Sdanielk1977 
427633ed08dSdanielk1977   return pTriggerStep;
428c3f9bad2Sdanielk1977 }
429c3f9bad2Sdanielk1977 
430c3f9bad2Sdanielk1977 /*
431633ed08dSdanielk1977 ** Recursively delete a Trigger structure
432c3f9bad2Sdanielk1977 */
433633e6d57Sdrh void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
434f0f258b1Sdrh   if( pTrigger==0 ) return;
435633e6d57Sdrh   sqlite3DeleteTriggerStep(db, pTrigger->step_list);
436633e6d57Sdrh   sqlite3DbFree(db, pTrigger->name);
437633e6d57Sdrh   sqlite3DbFree(db, pTrigger->table);
438633e6d57Sdrh   sqlite3ExprDelete(db, pTrigger->pWhen);
439633e6d57Sdrh   sqlite3IdListDelete(db, pTrigger->pColumns);
440633e6d57Sdrh   if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z);
441633e6d57Sdrh   sqlite3DbFree(db, 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 
46017435752Sdrh   if( db->mallocFailed ) 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;
468*ea678832Sdrh   nName = sqlite3Strlen30(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:
484633e6d57Sdrh   sqlite3SrcListDelete(db, 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){
492*ea678832Sdrh   int n = sqlite3Strlen30(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},
5311db639ceSdrh       { OP_String8,    0, 1,        0}, /* 1 */
5321db639ceSdrh       { OP_Column,     0, 1,        2},
5331db639ceSdrh       { OP_Ne,         2, ADDR(8),  1},
5341db639ceSdrh       { OP_String8,    0, 1,        0}, /* 4: "trigger" */
5351db639ceSdrh       { OP_Column,     0, 0,        2},
5361db639ceSdrh       { OP_Ne,         2, ADDR(8),  1},
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);
54466a5167bSdrh     sqlite3VdbeChangeP4(v, base+1, pTrigger->name, 0);
5452400345aSdrh     sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
5469cbf3425Sdrh     sqlite3ChangeCookie(pParse, iDb);
54766a5167bSdrh     sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
54866a5167bSdrh     sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0);
549956bc92cSdrh   }
550f0f258b1Sdrh }
551f0f258b1Sdrh 
552c3f9bad2Sdanielk1977 /*
553956bc92cSdrh ** Remove a trigger from the hash tables of the sqlite* pointer.
554c3f9bad2Sdanielk1977 */
555956bc92cSdrh void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
556956bc92cSdrh   Trigger *pTrigger;
557*ea678832Sdrh   int nName = sqlite3Strlen30(zName);
558e4df0e74Sdrh   pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash),
559e4df0e74Sdrh                                zName, nName, 0);
560956bc92cSdrh   if( pTrigger ){
56174161705Sdrh     Table *pTable = tableOfTrigger(pTrigger);
562956bc92cSdrh     assert( pTable!=0 );
563633ed08dSdanielk1977     if( pTable->pTrigger == pTrigger ){
564633ed08dSdanielk1977       pTable->pTrigger = pTrigger->pNext;
565633ed08dSdanielk1977     }else{
566633ed08dSdanielk1977       Trigger *cc = pTable->pTrigger;
567c3f9bad2Sdanielk1977       while( cc ){
568633ed08dSdanielk1977         if( cc->pNext == pTrigger ){
569c3f9bad2Sdanielk1977           cc->pNext = cc->pNext->pNext;
570c3f9bad2Sdanielk1977           break;
571c3f9bad2Sdanielk1977         }
572c3f9bad2Sdanielk1977         cc = cc->pNext;
573c3f9bad2Sdanielk1977       }
574c3f9bad2Sdanielk1977       assert(cc);
575c3f9bad2Sdanielk1977     }
576633e6d57Sdrh     sqlite3DeleteTrigger(db, pTrigger);
577956bc92cSdrh     db->flags |= SQLITE_InternChanges;
578c3f9bad2Sdanielk1977   }
579c3f9bad2Sdanielk1977 }
580c3f9bad2Sdanielk1977 
581c977f7f5Sdrh /*
582c977f7f5Sdrh ** pEList is the SET clause of an UPDATE statement.  Each entry
583c977f7f5Sdrh ** in pEList is of the format <id>=<expr>.  If any of the entries
584c977f7f5Sdrh ** in pEList have an <id> which matches an identifier in pIdList,
585c977f7f5Sdrh ** then return TRUE.  If pIdList==NULL, then it is considered a
586c977f7f5Sdrh ** wildcard that matches anything.  Likewise if pEList==NULL then
587c977f7f5Sdrh ** it matches anything so always return true.  Return false only
588c977f7f5Sdrh ** if there is no match.
589c977f7f5Sdrh */
590c977f7f5Sdrh static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
591ad2d8307Sdrh   int e;
592ad2d8307Sdrh   if( !pIdList || !pEList ) return 1;
593f29ce559Sdanielk1977   for(e=0; e<pEList->nExpr; e++){
5944adee20fSdanielk1977     if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
595f29ce559Sdanielk1977   }
596c3f9bad2Sdanielk1977   return 0;
597c3f9bad2Sdanielk1977 }
598c3f9bad2Sdanielk1977 
599c3f9bad2Sdanielk1977 /*
600dca76841Sdrh ** Return a bit vector to indicate what kind of triggers exist for operation
601dca76841Sdrh ** "op" on table pTab.  If pChanges is not NULL then it is a list of columns
602dca76841Sdrh ** that are being updated.  Triggers only match if the ON clause of the
603dca76841Sdrh ** trigger definition overlaps the set of columns being updated.
604dca76841Sdrh **
605dca76841Sdrh ** The returned bit vector is some combination of TRIGGER_BEFORE and
606dca76841Sdrh ** TRIGGER_AFTER.
607c3f9bad2Sdanielk1977 */
6084adee20fSdanielk1977 int sqlite3TriggersExist(
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;
648*ea678832Sdrh     sDb.n = sqlite3Strlen30((char*)sDb.z);
64917435752Sdrh     pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target);
650f26e09c8Sdrh   } else {
65117435752Sdrh     pSrc = sqlite3SrcListAppend(pParse->db, 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;
66817435752Sdrh   sqlite3 *db = pParse->db;
669c3f9bad2Sdanielk1977 
670344737f6Sdrh   assert( pTriggerStep!=0 );
671344737f6Sdrh   assert( v!=0 );
67266a5167bSdrh   sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0);
673d4e70ebdSdrh   VdbeComment((v, "begin trigger %s", pStepList->pTrig->name));
674633ed08dSdanielk1977   while( pTriggerStep ){
675633ed08dSdanielk1977     orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
676c3f9bad2Sdanielk1977     pParse->trigStack->orconf = orconf;
677633ed08dSdanielk1977     switch( pTriggerStep->op ){
678c3f9bad2Sdanielk1977       case TK_SELECT: {
67917435752Sdrh         Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect);
68028f45914Sdrh         if( ss ){
6811013c932Sdrh           SelectDest dest;
6821013c932Sdrh 
6831013c932Sdrh           sqlite3SelectDestInit(&dest, SRT_Discard, 0);
6847d10d5a6Sdrh           sqlite3Select(pParse, ss, &dest);
685633e6d57Sdrh           sqlite3SelectDelete(db, ss);
68628f45914Sdrh         }
687c3f9bad2Sdanielk1977         break;
688c3f9bad2Sdanielk1977       }
689c3f9bad2Sdanielk1977       case TK_UPDATE: {
690113088ecSdrh         SrcList *pSrc;
691f26e09c8Sdrh         pSrc = targetSrcList(pParse, pTriggerStep);
69266a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
6934adee20fSdanielk1977         sqlite3Update(pParse, pSrc,
69417435752Sdrh                 sqlite3ExprListDup(db, pTriggerStep->pExprList),
69517435752Sdrh                 sqlite3ExprDup(db, pTriggerStep->pWhere), orconf);
69666a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
697c3f9bad2Sdanielk1977         break;
698c3f9bad2Sdanielk1977       }
699c3f9bad2Sdanielk1977       case TK_INSERT: {
700113088ecSdrh         SrcList *pSrc;
701f26e09c8Sdrh         pSrc = targetSrcList(pParse, pTriggerStep);
70266a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
7034adee20fSdanielk1977         sqlite3Insert(pParse, pSrc,
70417435752Sdrh           sqlite3ExprListDup(db, pTriggerStep->pExprList),
70517435752Sdrh           sqlite3SelectDup(db, pTriggerStep->pSelect),
70617435752Sdrh           sqlite3IdListDup(db, pTriggerStep->pIdList), orconf);
70766a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
708c3f9bad2Sdanielk1977         break;
709c3f9bad2Sdanielk1977       }
710c3f9bad2Sdanielk1977       case TK_DELETE: {
711113088ecSdrh         SrcList *pSrc;
71266a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
713f26e09c8Sdrh         pSrc = targetSrcList(pParse, pTriggerStep);
71417435752Sdrh         sqlite3DeleteFrom(pParse, pSrc,
71517435752Sdrh                           sqlite3ExprDup(db, pTriggerStep->pWhere));
71666a5167bSdrh         sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
717c3f9bad2Sdanielk1977         break;
718c3f9bad2Sdanielk1977       }
719c3f9bad2Sdanielk1977       default:
720c3f9bad2Sdanielk1977         assert(0);
721c3f9bad2Sdanielk1977     }
722633ed08dSdanielk1977     pTriggerStep = pTriggerStep->pNext;
723c3f9bad2Sdanielk1977   }
72466a5167bSdrh   sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
725d4e70ebdSdrh   VdbeComment((v, "end trigger %s", pStepList->pTrig->name));
726c3f9bad2Sdanielk1977 
727c3f9bad2Sdanielk1977   return 0;
728c3f9bad2Sdanielk1977 }
729c3f9bad2Sdanielk1977 
730633ed08dSdanielk1977 /*
731633ed08dSdanielk1977 ** This is called to code FOR EACH ROW triggers.
732633ed08dSdanielk1977 **
733633ed08dSdanielk1977 ** When the code that this function generates is executed, the following
734633ed08dSdanielk1977 ** must be true:
735c977f7f5Sdrh **
736c977f7f5Sdrh ** 1. No cursors may be open in the main database.  (But newIdx and oldIdx
737c977f7f5Sdrh **    can be indices of cursors in temporary tables.  See below.)
738c977f7f5Sdrh **
739633ed08dSdanielk1977 ** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
740633ed08dSdanielk1977 **    a temporary vdbe cursor (index newIdx) must be open and pointing at
741633ed08dSdanielk1977 **    a row containing values to be substituted for new.* expressions in the
742633ed08dSdanielk1977 **    trigger program(s).
743c977f7f5Sdrh **
744633ed08dSdanielk1977 ** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
745633ed08dSdanielk1977 **    a temporary vdbe cursor (index oldIdx) must be open and pointing at
746633ed08dSdanielk1977 **    a row containing values to be substituted for old.* expressions in the
747633ed08dSdanielk1977 **    trigger program(s).
748633ed08dSdanielk1977 **
7498f2c54e6Sdanielk1977 ** If they are not NULL, the piOldColMask and piNewColMask output variables
7508f2c54e6Sdanielk1977 ** are set to values that describe the columns used by the trigger program
7518f2c54e6Sdanielk1977 ** in the OLD.* and NEW.* tables respectively. If column N of the
7528f2c54e6Sdanielk1977 ** pseudo-table is read at least once, the corresponding bit of the output
7538f2c54e6Sdanielk1977 ** mask is set. If a column with an index greater than 32 is read, the
7548f2c54e6Sdanielk1977 ** output mask is set to the special value 0xffffffff.
7558f2c54e6Sdanielk1977 **
756633ed08dSdanielk1977 */
7574adee20fSdanielk1977 int sqlite3CodeRowTrigger(
758c3f9bad2Sdanielk1977   Parse *pParse,       /* Parse context */
759c3f9bad2Sdanielk1977   int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
760633ed08dSdanielk1977   ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
761dca76841Sdrh   int tr_tm,           /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
762633ed08dSdanielk1977   Table *pTab,         /* The table to code triggers from */
763633ed08dSdanielk1977   int newIdx,          /* The indice of the "new" row to access */
764633ed08dSdanielk1977   int oldIdx,          /* The indice of the "old" row to access */
7656f34903eSdanielk1977   int orconf,          /* ON CONFLICT policy */
7668f2c54e6Sdanielk1977   int ignoreJump,      /* Instruction to jump to for RAISE(IGNORE) */
7678f2c54e6Sdanielk1977   u32 *piOldColMask,   /* OUT: Mask of columns used from the OLD.* table */
7688f2c54e6Sdanielk1977   u32 *piNewColMask    /* OUT: Mask of columns used from the NEW.* table */
769c977f7f5Sdrh ){
770eecfb3eeSdanielk1977   Trigger *p;
7710e359b30Sdrh   sqlite3 *db = pParse->db;
77267040462Sdrh   TriggerStack trigStackEntry;
773c3f9bad2Sdanielk1977 
7748f2c54e6Sdanielk1977   trigStackEntry.oldColMask = 0;
7758f2c54e6Sdanielk1977   trigStackEntry.newColMask = 0;
7768f2c54e6Sdanielk1977 
777c3f9bad2Sdanielk1977   assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
778dca76841Sdrh   assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
779c3f9bad2Sdanielk1977 
780633ed08dSdanielk1977   assert(newIdx != -1 || oldIdx != -1);
781c3f9bad2Sdanielk1977 
782eecfb3eeSdanielk1977   for(p=pTab->pTrigger; p; p=p->pNext){
783c3f9bad2Sdanielk1977     int fire_this = 0;
784c3f9bad2Sdanielk1977 
785eecfb3eeSdanielk1977     /* Determine whether we should code this trigger */
786eecfb3eeSdanielk1977     if(
787eecfb3eeSdanielk1977       p->op==op &&
788eecfb3eeSdanielk1977       p->tr_tm==tr_tm &&
789932083c6Sdanielk1977       (p->pSchema==p->pTabSchema || p->pSchema==db->aDb[1].pSchema) &&
790eecfb3eeSdanielk1977       (op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges))
791eecfb3eeSdanielk1977     ){
792eecfb3eeSdanielk1977       TriggerStack *pS;      /* Pointer to trigger-stack entry */
79374161705Sdrh       for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}
794eecfb3eeSdanielk1977       if( !pS ){
795c3f9bad2Sdanielk1977         fire_this = 1;
796c3f9bad2Sdanielk1977       }
797229caa36Sdrh #if 0    /* Give no warning for recursive triggers.  Just do not do them */
798229caa36Sdrh       else{
799229caa36Sdrh         sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)",
800229caa36Sdrh             p->name);
801229caa36Sdrh         return SQLITE_ERROR;
802229caa36Sdrh       }
803229caa36Sdrh #endif
804f29ce559Sdanielk1977     }
805c3f9bad2Sdanielk1977 
80667040462Sdrh     if( fire_this ){
807c3f9bad2Sdanielk1977       int endTrigger;
808c3f9bad2Sdanielk1977       Expr * whenExpr;
80985e2096fSdrh       AuthContext sContext;
810b3bce662Sdanielk1977       NameContext sNC;
811c3f9bad2Sdanielk1977 
812949f9cd5Sdrh #ifndef SQLITE_OMIT_TRACE
813949f9cd5Sdrh       sqlite3VdbeAddOp4(pParse->pVdbe, OP_Trace, 0, 0, 0,
8140e359b30Sdrh                         sqlite3MPrintf(db, "-- TRIGGER %s", p->name),
815949f9cd5Sdrh                         P4_DYNAMIC);
816949f9cd5Sdrh #endif
817b3bce662Sdanielk1977       memset(&sNC, 0, sizeof(sNC));
818b3bce662Sdanielk1977       sNC.pParse = pParse;
819c3f9bad2Sdanielk1977 
820c3f9bad2Sdanielk1977       /* Push an entry on to the trigger stack */
821eecfb3eeSdanielk1977       trigStackEntry.pTrigger = p;
82267040462Sdrh       trigStackEntry.newIdx = newIdx;
82367040462Sdrh       trigStackEntry.oldIdx = oldIdx;
82467040462Sdrh       trigStackEntry.pTab = pTab;
82567040462Sdrh       trigStackEntry.pNext = pParse->trigStack;
82667040462Sdrh       trigStackEntry.ignoreJump = ignoreJump;
82767040462Sdrh       pParse->trigStack = &trigStackEntry;
828eecfb3eeSdanielk1977       sqlite3AuthContextPush(pParse, &sContext, p->name);
829c3f9bad2Sdanielk1977 
830c3f9bad2Sdanielk1977       /* code the WHEN clause */
8314adee20fSdanielk1977       endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
832932083c6Sdanielk1977       whenExpr = sqlite3ExprDup(db, p->pWhen);
8337d10d5a6Sdrh       if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
83467040462Sdrh         pParse->trigStack = trigStackEntry.pNext;
835633e6d57Sdrh         sqlite3ExprDelete(db, whenExpr);
836c3f9bad2Sdanielk1977         return 1;
837c3f9bad2Sdanielk1977       }
83835573356Sdrh       sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL);
839633e6d57Sdrh       sqlite3ExprDelete(db, whenExpr);
840c3f9bad2Sdanielk1977 
841eecfb3eeSdanielk1977       codeTriggerProgram(pParse, p->step_list, orconf);
842c3f9bad2Sdanielk1977 
843c3f9bad2Sdanielk1977       /* Pop the entry off the trigger stack */
84467040462Sdrh       pParse->trigStack = trigStackEntry.pNext;
8454adee20fSdanielk1977       sqlite3AuthContextPop(&sContext);
846c3f9bad2Sdanielk1977 
8474adee20fSdanielk1977       sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
848c3f9bad2Sdanielk1977     }
849c3f9bad2Sdanielk1977   }
8508f2c54e6Sdanielk1977   if( piOldColMask ) *piOldColMask |= trigStackEntry.oldColMask;
8518f2c54e6Sdanielk1977   if( piNewColMask ) *piNewColMask |= trigStackEntry.newColMask;
852c3f9bad2Sdanielk1977   return 0;
853c3f9bad2Sdanielk1977 }
854b7f9164eSdrh #endif /* !defined(SQLITE_OMIT_TRIGGER) */
855