blob: 24bd74888e4b9f49d74c6677cce4dc76f342f2e8 [file] [log] [blame]
danielk1977c3f9bad2002-05-15 08:30:12 +00001/*
danielk1977633ed082002-05-17 00:05:58 +00002**
3** The author disclaims copyright to this source code. In place of
4** a legal notice, here is a blessing:
5**
6** May you do good and not evil.
7** May you find forgiveness for yourself and forgive others.
8** May you share freely, never taking more than you give.
9**
10*************************************************************************
11*
drh9adf9ac2002-05-15 11:44:13 +000012*/
danielk1977c3f9bad2002-05-15 08:30:12 +000013#include "sqliteInt.h"
drh9adf9ac2002-05-15 11:44:13 +000014
danielk1977c3f9bad2002-05-15 08:30:12 +000015/*
drh4b59ab52002-08-24 18:24:51 +000016** Delete a linked list of TriggerStep structures.
17*/
18static void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
19 while( pTriggerStep ){
20 TriggerStep * pTmp = pTriggerStep;
21 pTriggerStep = pTriggerStep->pNext;
22
23 if( pTmp->target.dyn ) sqliteFree(pTmp->target.z);
24 sqliteExprDelete(pTmp->pWhere);
25 sqliteExprListDelete(pTmp->pExprList);
26 sqliteSelectDelete(pTmp->pSelect);
27 sqliteIdListDelete(pTmp->pIdList);
28
29 sqliteFree(pTmp);
30 }
31}
32
33/*
danielk1977633ed082002-05-17 00:05:58 +000034** This is called by the parser when it sees a CREATE TRIGGER statement. See
35** comments surrounding struct Trigger in sqliteInt.h for a description of
36** how triggers are stored.
drh9adf9ac2002-05-15 11:44:13 +000037*/
38void sqliteCreateTrigger(
39 Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
danielk1977633ed082002-05-17 00:05:58 +000040 Token *pName, /* The name of the trigger */
danielk1977d702fcc2002-05-26 23:24:40 +000041 int tr_tm, /* One of TK_BEFORE, TK_AFTER , TK_INSTEAD */
drh9adf9ac2002-05-15 11:44:13 +000042 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
danielk1977633ed082002-05-17 00:05:58 +000043 IdList *pColumns, /* column list if this is an UPDATE OF trigger */
44 Token *pTableName, /* The name of the table/view the trigger applies to */
drh9adf9ac2002-05-15 11:44:13 +000045 int foreach, /* One of TK_ROW or TK_STATEMENT */
46 Expr *pWhen, /* WHEN clause */
danielk1977633ed082002-05-17 00:05:58 +000047 TriggerStep *pStepList, /* The triggered program */
drh4b59ab52002-08-24 18:24:51 +000048 Token *pAll /* Token that describes the complete CREATE TRIGGER */
drh9adf9ac2002-05-15 11:44:13 +000049){
50 Trigger *nt;
51 Table *tab;
danielk1977c3f9bad2002-05-15 08:30:12 +000052
53 /* Check that:
drh9adf9ac2002-05-15 11:44:13 +000054 ** 1. the trigger name does not already exist.
55 ** 2. the table (or view) does exist.
danielk1977d702fcc2002-05-26 23:24:40 +000056 ** 3. that we are not trying to create a trigger on the sqlite_master table
57 ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
58 ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
drh9adf9ac2002-05-15 11:44:13 +000059 */
danielk1977c3f9bad2002-05-15 08:30:12 +000060 {
danielk1977633ed082002-05-17 00:05:58 +000061 char *tmp_str = sqliteStrNDup(pName->z, pName->n);
62 if( sqliteHashFind(&(pParse->db->trigHash), tmp_str, pName->n + 1) ){
danielk1977c3f9bad2002-05-15 08:30:12 +000063 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
danielk1977633ed082002-05-17 00:05:58 +000064 pName->z, pName->n, " already exists", -1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000065 sqliteFree(tmp_str);
66 pParse->nErr++;
67 goto trigger_cleanup;
68 }
69 sqliteFree(tmp_str);
70 }
71 {
danielk1977633ed082002-05-17 00:05:58 +000072 char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +000073 if( tmp_str==0 ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000074 tab = sqliteFindTable(pParse->db, tmp_str);
75 sqliteFree(tmp_str);
drh9adf9ac2002-05-15 11:44:13 +000076 if( !tab ){
danielk1977c3f9bad2002-05-15 08:30:12 +000077 sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
danielk1977633ed082002-05-17 00:05:58 +000078 pTableName->z, pTableName->n, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000079 pParse->nErr++;
80 goto trigger_cleanup;
81 }
drh1873cd52002-05-23 00:30:31 +000082 if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
83 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
84 "table: " MASTER_NAME, 0);
85 pParse->nErr++;
86 goto trigger_cleanup;
87 }
drhe0bc4042002-06-25 01:09:11 +000088 if( sqliteStrICmp(tab->zName, TEMP_MASTER_NAME)==0 ){
89 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
90 "table: " TEMP_MASTER_NAME, 0);
91 pParse->nErr++;
92 goto trigger_cleanup;
93 }
danielk1977d702fcc2002-05-26 23:24:40 +000094 if( tab->pSelect && tr_tm != TK_INSTEAD ){
95 sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
96 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
97 , pTableName->z, pTableName->n, 0);
98 goto trigger_cleanup;
99 }
100 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
101 sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1,
102 " trigger on table: ", -1, pTableName->z, pTableName->n, 0);
103 goto trigger_cleanup;
104 }
105 }
106
107 if (tr_tm == TK_INSTEAD){
108 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +0000109 }
110
111 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +0000112 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +0000113 if( nt==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000114 nt->name = sqliteStrNDup(pName->z, pName->n);
115 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +0000116 if( sqlite_malloc_failed ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000117 nt->op = op;
118 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000119 nt->pWhen = sqliteExprDup(pWhen);
120 sqliteExprDelete(pWhen);
121 nt->pColumns = sqliteIdListDup(pColumns);
122 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000123 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000124 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000125
126 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000127 ** build the sqlite_master entry
128 */
drhe0bc4042002-06-25 01:09:11 +0000129 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000130 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000131 { OP_NewRecno, 0, 0, 0 },
132 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000133 { OP_String, 0, 0, 0 }, /* 2: trigger name */
134 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000135 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000136 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000137 { OP_MakeRecord, 5, 0, 0 },
138 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000139 };
140 int addr;
141 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000142
143 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000144 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000145 if( v==0 ) goto trigger_cleanup;
drhc977f7f2002-05-21 11:38:11 +0000146 sqliteBeginWriteOperation(pParse, 0);
drhe0bc4042002-06-25 01:09:11 +0000147 sqliteOpenMasterTable(v, tab->isTemp);
drhc977f7f2002-05-21 11:38:11 +0000148 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhe0bc4042002-06-25 01:09:11 +0000149 sqliteVdbeChangeP3(v, addr, tab->isTemp ? TEMP_MASTER_NAME : MASTER_NAME,
150 P3_STATIC);
151 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
152 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000153 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhe0bc4042002-06-25 01:09:11 +0000154 if( !tab->isTemp ){
155 sqliteChangeCookie(pParse->db, v);
156 }
157 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000158 sqliteEndWriteOperation(pParse);
159 }
160
danielk1977633ed082002-05-17 00:05:58 +0000161 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000162 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000163 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000164
165 /* Attach it to the table object */
166 nt->pNext = tab->pTrigger;
167 tab->pTrigger = nt;
168 return;
danielk1977f29ce552002-05-19 23:43:12 +0000169 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000170 sqliteFree(nt->name);
171 sqliteFree(nt->table);
172 sqliteFree(nt);
173 }
174
175trigger_cleanup:
176
danielk1977633ed082002-05-17 00:05:58 +0000177 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000178 sqliteExprDelete(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000179 sqliteDeleteTriggerStep(pStepList);
180}
danielk1977c3f9bad2002-05-15 08:30:12 +0000181
drh4b59ab52002-08-24 18:24:51 +0000182/*
183** Make a copy of all components of the given trigger step. This has
184** the effect of copying all Expr.token.z values into memory obtained
185** from sqliteMalloc(). As initially created, the Expr.token.z values
186** all point to the input string that was fed to the parser. But that
187** string is ephemeral - it will go away as soon as the sqlite_exec()
188** call that started the parser exits. This routine makes a persistent
189** copy of all the Expr.token.z strings so that the TriggerStep structure
190** will be valid even after the sqlite_exec() call returns.
191*/
192static void sqlitePersistTriggerStep(TriggerStep *p){
193 if( p->target.z ){
194 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
195 p->target.dyn = 1;
196 }
197 if( p->pSelect ){
198 Select *pNew = sqliteSelectDup(p->pSelect);
199 sqliteSelectDelete(p->pSelect);
200 p->pSelect = pNew;
201 }
202 if( p->pWhere ){
203 Expr *pNew = sqliteExprDup(p->pWhere);
204 sqliteExprDelete(p->pWhere);
205 p->pWhere = pNew;
206 }
207 if( p->pExprList ){
208 ExprList *pNew = sqliteExprListDup(p->pExprList);
209 sqliteExprListDelete(p->pExprList);
210 p->pExprList = pNew;
211 }
212 if( p->pIdList ){
213 IdList *pNew = sqliteIdListDup(p->pIdList);
214 sqliteIdListDelete(p->pIdList);
215 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000216 }
217}
218
drhc977f7f2002-05-21 11:38:11 +0000219/*
220** Turn a SELECT statement (that the pSelect parameter points to) into
221** a trigger step. Return a pointer to a TriggerStep structure.
222**
223** The parser calls this routine when it finds a SELECT statement in
224** body of a TRIGGER.
225*/
226TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000227 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000228 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000229
danielk1977633ed082002-05-17 00:05:58 +0000230 pTriggerStep->op = TK_SELECT;
231 pTriggerStep->pSelect = pSelect;
232 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000233 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000234
danielk1977633ed082002-05-17 00:05:58 +0000235 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000236}
237
drhc977f7f2002-05-21 11:38:11 +0000238/*
239** Build a trigger step out of an INSERT statement. Return a pointer
240** to the new trigger step.
241**
242** The parser calls this routine when it sees an INSERT inside the
243** body of a trigger.
244*/
danielk1977633ed082002-05-17 00:05:58 +0000245TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000246 Token *pTableName, /* Name of the table into which we insert */
247 IdList *pColumn, /* List of columns in pTableName to insert into */
248 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
249 Select *pSelect, /* A SELECT statement that supplies values */
250 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000251){
252 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000253 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000254
danielk1977633ed082002-05-17 00:05:58 +0000255 assert(pEList == 0 || pSelect == 0);
256 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000257
danielk1977633ed082002-05-17 00:05:58 +0000258 pTriggerStep->op = TK_INSERT;
259 pTriggerStep->pSelect = pSelect;
260 pTriggerStep->target = *pTableName;
261 pTriggerStep->pIdList = pColumn;
262 pTriggerStep->pExprList = pEList;
263 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000264 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000265
danielk1977633ed082002-05-17 00:05:58 +0000266 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000267}
268
drhc977f7f2002-05-21 11:38:11 +0000269/*
270** Construct a trigger step that implements an UPDATE statement and return
271** a pointer to that trigger step. The parser calls this routine when it
272** sees an UPDATE statement inside the body of a CREATE TRIGGER.
273*/
danielk1977633ed082002-05-17 00:05:58 +0000274TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000275 Token *pTableName, /* Name of the table to be updated */
276 ExprList *pEList, /* The SET clause: list of column and new values */
277 Expr *pWhere, /* The WHERE clause */
278 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
279){
danielk1977633ed082002-05-17 00:05:58 +0000280 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000281 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000282
danielk1977633ed082002-05-17 00:05:58 +0000283 pTriggerStep->op = TK_UPDATE;
284 pTriggerStep->target = *pTableName;
285 pTriggerStep->pExprList = pEList;
286 pTriggerStep->pWhere = pWhere;
287 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000288 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000289
danielk1977633ed082002-05-17 00:05:58 +0000290 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000291}
292
drhc977f7f2002-05-21 11:38:11 +0000293/*
294** Construct a trigger step that implements a DELETE statement and return
295** a pointer to that trigger step. The parser calls this routine when it
296** sees a DELETE statement inside the body of a CREATE TRIGGER.
297*/
298TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000299 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
300 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000301
danielk1977633ed082002-05-17 00:05:58 +0000302 pTriggerStep->op = TK_DELETE;
303 pTriggerStep->target = *pTableName;
304 pTriggerStep->pWhere = pWhere;
305 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000306 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000307
danielk1977633ed082002-05-17 00:05:58 +0000308 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000309}
310
danielk1977633ed082002-05-17 00:05:58 +0000311/*
312** Recursively delete a Trigger structure
313*/
drh1d1f3052002-05-21 13:18:25 +0000314void sqliteDeleteTrigger(Trigger *pTrigger){
danielk1977633ed082002-05-17 00:05:58 +0000315 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000316
drh4b59ab52002-08-24 18:24:51 +0000317 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000318 sqliteFree(pTrigger->name);
319 sqliteFree(pTrigger->table);
320 sqliteExprDelete(pTrigger->pWhen);
321 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000322 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000323}
324
325/*
danielk1977633ed082002-05-17 00:05:58 +0000326 * This function is called to drop a trigger from the database schema.
327 *
328 * This may be called directly from the parser, or from within
329 * sqliteDropTable(). In the latter case the "nested" argument is true.
330 *
331 * Note that this function does not delete the trigger entirely. Instead it
332 * removes it from the internal schema and places it in the trigDrop hash
333 * table. This is so that the trigger can be restored into the database schema
334 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000335 */
drhe0bc4042002-06-25 01:09:11 +0000336void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000337 char *zName;
338 Trigger *pTrigger;
339 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000340 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000341
danielk1977633ed082002-05-17 00:05:58 +0000342 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000343
344 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000345 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
346 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000347 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000348 zName, -1, 0);
349 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000350 return;
351 }
352
353 /*
drhe0bc4042002-06-25 01:09:11 +0000354 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000355 */
danielk1977633ed082002-05-17 00:05:58 +0000356 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000357 pTable = sqliteFindTable(pParse->db, pTrigger->table);
358 assert(pTable);
359 if( pTable->pTrigger == pTrigger ){
360 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000361 }else{
danielk1977633ed082002-05-17 00:05:58 +0000362 Trigger *cc = pTable->pTrigger;
363 while( cc ){
364 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000365 cc->pNext = cc->pNext->pNext;
366 break;
367 }
368 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000369 }
370 assert(cc);
371 }
drhe0bc4042002-06-25 01:09:11 +0000372 sqliteHashInsert(&(pParse->db->trigHash), zName, pName->n + 1, NULL);
373 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000374 }
375
drhe0bc4042002-06-25 01:09:11 +0000376 /* Generate code to destroy the database record of the trigger.
377 */
378 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000379 int base;
380 static VdbeOp dropTrigger[] = {
drhe0bc4042002-06-25 01:09:11 +0000381 { OP_Rewind, 0, ADDR(8), 0},
382 { OP_String, 0, 0, 0}, /* 1 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000383 { OP_MemStore, 1, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000384 { OP_MemLoad, 1, 0, 0}, /* 3 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000385 { OP_Column, 0, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000386 { OP_Ne, 0, ADDR(7), 0},
danielk1977c3f9bad2002-05-15 08:30:12 +0000387 { OP_Delete, 0, 0, 0},
drhe0bc4042002-06-25 01:09:11 +0000388 { OP_Next, 0, ADDR(3), 0}, /* 7 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000389 };
390
drhe0bc4042002-06-25 01:09:11 +0000391 sqliteBeginWriteOperation(pParse, 0);
392 sqliteOpenMasterTable(v, pTable->isTemp);
393 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
394 sqliteVdbeChangeP3(v, base+1, zName, 0);
395 if( !pTable->isTemp ){
396 sqliteChangeCookie(pParse->db, v);
drhdc379452002-05-15 12:45:43 +0000397 }
drhe0bc4042002-06-25 01:09:11 +0000398 sqliteVdbeAddOp(v, OP_Close, 0, 0);
399 sqliteEndWriteOperation(pParse);
danielk1977c3f9bad2002-05-15 08:30:12 +0000400 }
401
danielk1977633ed082002-05-17 00:05:58 +0000402 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000403}
404
drhc977f7f2002-05-21 11:38:11 +0000405/*
406** pEList is the SET clause of an UPDATE statement. Each entry
407** in pEList is of the format <id>=<expr>. If any of the entries
408** in pEList have an <id> which matches an identifier in pIdList,
409** then return TRUE. If pIdList==NULL, then it is considered a
410** wildcard that matches anything. Likewise if pEList==NULL then
411** it matches anything so always return true. Return false only
412** if there is no match.
413*/
414static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000415 int e;
416 if( !pIdList || !pEList ) return 1;
417 for(e=0; e<pEList->nExpr; e++){
418 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000419 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000420 return 0;
421}
422
423/* A global variable that is TRUE if we should always set up temp tables for
424 * for triggers, even if there are no triggers to code. This is used to test
425 * how much overhead the triggers algorithm is causing.
426 *
427 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
428 * The pragma is not documented since it is not really part of the interface
429 * to SQLite, just the test procedure.
430*/
431int always_code_trigger_setup = 0;
432
433/*
434 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
435 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
436 * found in the list specified as pTrigger.
437 */
438int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000439 Parse *pParse, /* Used to check for recursive triggers */
440 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000441 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
442 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
443 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000444 ExprList *pChanges /* Columns that change in an UPDATE statement */
445){
danielk1977633ed082002-05-17 00:05:58 +0000446 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000447
danielk1977633ed082002-05-17 00:05:58 +0000448 if( always_code_trigger_setup ){
449 return 1;
450 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000451
danielk1977633ed082002-05-17 00:05:58 +0000452 pTriggerCursor = pTrigger;
453 while( pTriggerCursor ){
454 if( pTriggerCursor->op == op &&
455 pTriggerCursor->tr_tm == tr_tm &&
456 pTriggerCursor->foreach == foreach &&
457 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000458 TriggerStack * ss;
459 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000460 while( ss && ss->pTrigger != pTrigger ){
461 ss = ss->pNext;
462 }
463 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000464 }
danielk1977633ed082002-05-17 00:05:58 +0000465 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000466 }
467
468 return 0;
469}
470
drhc977f7f2002-05-21 11:38:11 +0000471/*
472** Generate VDBE code for zero or more statements inside the body of a
473** trigger.
474*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000475static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000476 Parse *pParse, /* The parser context */
477 TriggerStep *pStepList, /* List of statements inside the trigger body */
478 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000479){
480 TriggerStep * pTriggerStep = pStepList;
481 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000482
danielk1977633ed082002-05-17 00:05:58 +0000483 while( pTriggerStep ){
484 int saveNTab = pParse->nTab;
485 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
486 pParse->trigStack->orconf = orconf;
487 switch( pTriggerStep->op ){
488 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000489 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
490 assert(ss);
491 assert(ss->pSrc);
492 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
493 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000494 break;
495 }
496 case TK_UPDATE: {
drhbd5a4512002-05-23 22:07:02 +0000497 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000498 sqliteUpdate(pParse, &pTriggerStep->target,
danielk19776f349032002-06-11 02:25:40 +0000499 sqliteExprListDup(pTriggerStep->pExprList),
500 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000501 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000502 break;
503 }
504 case TK_INSERT: {
505 sqliteInsert(pParse, &pTriggerStep->target,
506 sqliteExprListDup(pTriggerStep->pExprList),
507 sqliteSelectDup(pTriggerStep->pSelect),
508 sqliteIdListDup(pTriggerStep->pIdList), orconf);
509 break;
510 }
511 case TK_DELETE: {
drhbd5a4512002-05-23 22:07:02 +0000512 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000513 sqliteDeleteFrom(pParse, &pTriggerStep->target,
514 sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000515 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000516 break;
517 }
518 default:
519 assert(0);
520 }
521 pParse->nTab = saveNTab;
522 pTriggerStep = pTriggerStep->pNext;
523 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000524
danielk1977633ed082002-05-17 00:05:58 +0000525 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000526}
527
danielk1977633ed082002-05-17 00:05:58 +0000528/*
529** This is called to code FOR EACH ROW triggers.
530**
531** When the code that this function generates is executed, the following
532** must be true:
drhc977f7f2002-05-21 11:38:11 +0000533**
534** 1. No cursors may be open in the main database. (But newIdx and oldIdx
535** can be indices of cursors in temporary tables. See below.)
536**
danielk1977633ed082002-05-17 00:05:58 +0000537** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
538** a temporary vdbe cursor (index newIdx) must be open and pointing at
539** a row containing values to be substituted for new.* expressions in the
540** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000541**
danielk1977633ed082002-05-17 00:05:58 +0000542** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
543** a temporary vdbe cursor (index oldIdx) must be open and pointing at
544** a row containing values to be substituted for old.* expressions in the
545** trigger program(s).
546**
547*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000548int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000549 Parse *pParse, /* Parse context */
550 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
551 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
552 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
553 Table *pTab, /* The table to code triggers from */
554 int newIdx, /* The indice of the "new" row to access */
555 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000556 int orconf, /* ON CONFLICT policy */
557 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000558){
danielk1977c3f9bad2002-05-15 08:30:12 +0000559 Trigger * pTrigger;
560 TriggerStack * pTriggerStack;
561
danielk1977c3f9bad2002-05-15 08:30:12 +0000562 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
563 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
564
danielk1977633ed082002-05-17 00:05:58 +0000565 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000566
danielk1977633ed082002-05-17 00:05:58 +0000567 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000568 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000569 int fire_this = 0;
570
571 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000572 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
573 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000574 fire_this = 1;
575 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000576 while( pTriggerStack ){
577 if( pTriggerStack->pTrigger == pTrigger ){
578 fire_this = 0;
579 }
drh9adf9ac2002-05-15 11:44:13 +0000580 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000581 }
danielk1977f29ce552002-05-19 23:43:12 +0000582 if( op == TK_UPDATE && pTrigger->pColumns &&
583 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000584 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000585 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000586 }
587
drhe4697f52002-05-23 02:09:03 +0000588 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000589 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000590 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000591 Expr * whenExpr;
592
drhad3cab52002-05-24 02:04:32 +0000593 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000594 dummyTablist.a = 0;
595
596 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000597 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000598 pTriggerStack->newIdx = newIdx;
599 pTriggerStack->oldIdx = oldIdx;
600 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000601 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000602 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000603 pParse->trigStack = pTriggerStack;
604
605 /* code the WHEN clause */
606 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
607 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000608 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000609 pParse->trigStack = pParse->trigStack->pNext;
610 sqliteFree(pTriggerStack);
611 sqliteExprDelete(whenExpr);
612 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000613 }
drhf5905aa2002-05-26 20:54:33 +0000614 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000615 sqliteExprDelete(whenExpr);
616
danielk1977633ed082002-05-17 00:05:58 +0000617 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000618
619 /* Pop the entry off the trigger stack */
620 pParse->trigStack = pParse->trigStack->pNext;
621 sqliteFree(pTriggerStack);
622
623 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
624 }
625 pTrigger = pTrigger->pNext;
626 }
627
628 return 0;
629}
630
631/*
danielk1977633ed082002-05-17 00:05:58 +0000632 * This function is called to code ON UPDATE and ON DELETE triggers on
633 * views.
634 *
635 * This function deletes the data pointed at by the pWhere and pChanges
636 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000637 */
danielk1977633ed082002-05-17 00:05:58 +0000638void sqliteViewTriggers(
639 Parse *pParse,
640 Table *pTab, /* The view to code triggers on */
641 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
642 int orconf, /* The ON CONFLICT policy specified as part of the
643 statement causing these triggers */
644 ExprList *pChanges /* If this is an statement causing triggers to fire
645 is an UPDATE, then this list holds the columns
646 to update and the expressions to update them to.
647 See comments for sqliteUpdate(). */
648){
danielk1977c3f9bad2002-05-15 08:30:12 +0000649 int oldIdx = -1;
650 int newIdx = -1;
651 int *aXRef = 0;
652 Vdbe *v;
653 int endOfLoop;
654 int startOfLoop;
655 Select theSelect;
656 Token tblNameToken;
657
658 assert(pTab->pSelect);
659
660 tblNameToken.z = pTab->zName;
661 tblNameToken.n = strlen(pTab->zName);
662
663 theSelect.isDistinct = 0;
664 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drhad3cab52002-05-24 02:04:32 +0000665 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken);
danielk1977c3f9bad2002-05-15 08:30:12 +0000666 theSelect.pWhere = pWhere; pWhere = 0;
667 theSelect.pGroupBy = 0;
668 theSelect.pHaving = 0;
669 theSelect.pOrderBy = 0;
670 theSelect.op = TK_SELECT; /* ?? */
671 theSelect.pPrior = 0;
672 theSelect.nLimit = -1;
673 theSelect.nOffset = -1;
674 theSelect.zSelect = 0;
675 theSelect.base = 0;
676
677 v = sqliteGetVdbe(pParse);
678 assert(v);
drhc977f7f2002-05-21 11:38:11 +0000679 sqliteBeginWriteOperation(pParse, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000680
681 /* Allocate temp tables */
682 oldIdx = pParse->nTab++;
683 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000684 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000685 newIdx = pParse->nTab++;
686 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
687 }
688
689 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000690 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000691 goto trigger_cleanup;
692 }
693
694 /* loop thru the view snapshot, executing triggers for each row */
695 endOfLoop = sqliteVdbeMakeLabel(v);
696 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
697
698 /* Loop thru the view snapshot, executing triggers for each row */
699 startOfLoop = sqliteVdbeCurrentAddr(v);
700
701 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000702 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000703 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000704
705 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
706 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000707 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000708 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000709 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000710
711 for(ii=0; ii<pChanges->nExpr; ii++){
712 int jj;
713 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000714 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000715 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000716 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000717
718 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000719 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000720
721 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000722 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
723 aXRef[jj] = ii;
724 break;
725 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000726 }
727 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000728 sqliteSetString(&pParse->zErrMsg, "no such column: ",
729 pChanges->a[ii].zName, 0);
730 pParse->nErr++;
731 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000732 }
733 }
734
735 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
736
danielk1977633ed082002-05-17 00:05:58 +0000737 for(ii = 0; ii<pTab->nCol; ii++){
738 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000739 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000740 }else{
drh9adf9ac2002-05-15 11:44:13 +0000741 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000742 }
743 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000744
745 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
746 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
747 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
748
749 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000750 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000751 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000752 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000753 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000754 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000755 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000756 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000757 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000758 }
759
760 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
761
762 sqliteVdbeResolveLabel(v, endOfLoop);
763 sqliteEndWriteOperation(pParse);
764
765trigger_cleanup:
766 sqliteFree(aXRef);
767 sqliteExprListDelete(pChanges);
768 sqliteExprDelete(pWhere);
769 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000770 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000771 sqliteExprDelete(theSelect.pWhere);
772 return;
773}