blob: aedf08873bd3d78019fc8d94ad8e4ca0e62912cc [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/*
danielk1977633ed082002-05-17 00:05:58 +000016** This is called by the parser when it sees a CREATE TRIGGER statement. See
17** comments surrounding struct Trigger in sqliteInt.h for a description of
18** how triggers are stored.
drh9adf9ac2002-05-15 11:44:13 +000019*/
20void sqliteCreateTrigger(
21 Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
danielk1977633ed082002-05-17 00:05:58 +000022 Token *pName, /* The name of the trigger */
drh9adf9ac2002-05-15 11:44:13 +000023 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
24 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
danielk1977633ed082002-05-17 00:05:58 +000025 IdList *pColumns, /* column list if this is an UPDATE OF trigger */
26 Token *pTableName, /* The name of the table/view the trigger applies to */
drh9adf9ac2002-05-15 11:44:13 +000027 int foreach, /* One of TK_ROW or TK_STATEMENT */
28 Expr *pWhen, /* WHEN clause */
danielk1977633ed082002-05-17 00:05:58 +000029 TriggerStep *pStepList, /* The triggered program */
30 char const *zData, /* The string data to make persistent */
31 int zDataLen
drh9adf9ac2002-05-15 11:44:13 +000032){
33 Trigger *nt;
34 Table *tab;
danielk1977c3f9bad2002-05-15 08:30:12 +000035 int offset;
drh9adf9ac2002-05-15 11:44:13 +000036 TriggerStep *ss;
danielk1977c3f9bad2002-05-15 08:30:12 +000037
38 /* Check that:
drh9adf9ac2002-05-15 11:44:13 +000039 ** 1. the trigger name does not already exist.
40 ** 2. the table (or view) does exist.
41 */
danielk1977c3f9bad2002-05-15 08:30:12 +000042 {
danielk1977633ed082002-05-17 00:05:58 +000043 char *tmp_str = sqliteStrNDup(pName->z, pName->n);
44 if( sqliteHashFind(&(pParse->db->trigHash), tmp_str, pName->n + 1) ){
danielk1977c3f9bad2002-05-15 08:30:12 +000045 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
danielk1977633ed082002-05-17 00:05:58 +000046 pName->z, pName->n, " already exists", -1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000047 sqliteFree(tmp_str);
48 pParse->nErr++;
49 goto trigger_cleanup;
50 }
51 sqliteFree(tmp_str);
52 }
53 {
danielk1977633ed082002-05-17 00:05:58 +000054 char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +000055 if( tmp_str==0 ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000056 tab = sqliteFindTable(pParse->db, tmp_str);
57 sqliteFree(tmp_str);
drh9adf9ac2002-05-15 11:44:13 +000058 if( !tab ){
danielk1977c3f9bad2002-05-15 08:30:12 +000059 sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
danielk1977633ed082002-05-17 00:05:58 +000060 pTableName->z, pTableName->n, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000061 pParse->nErr++;
62 goto trigger_cleanup;
63 }
drh1873cd52002-05-23 00:30:31 +000064 if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
65 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
66 "table: " MASTER_NAME, 0);
67 pParse->nErr++;
68 goto trigger_cleanup;
69 }
danielk1977c3f9bad2002-05-15 08:30:12 +000070 }
71
72 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +000073 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +000074 if( nt==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +000075 nt->name = sqliteStrNDup(pName->z, pName->n);
76 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +000077 nt->strings = sqliteStrNDup(zData, zDataLen);
78 if( sqlite_malloc_failed ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000079 nt->op = op;
80 nt->tr_tm = tr_tm;
81 nt->pWhen = pWhen;
danielk1977633ed082002-05-17 00:05:58 +000082 nt->pColumns = pColumns;
danielk1977c3f9bad2002-05-15 08:30:12 +000083 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +000084 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +000085 nt->isCommit = 0;
danielk1977633ed082002-05-17 00:05:58 +000086 offset = (int)(nt->strings - zData);
danielk1977c3f9bad2002-05-15 08:30:12 +000087 sqliteExprMoveStrings(nt->pWhen, offset);
88
89 ss = nt->step_list;
danielk1977f29ce552002-05-19 23:43:12 +000090 while( ss ){
danielk1977c3f9bad2002-05-15 08:30:12 +000091 sqliteSelectMoveStrings(ss->pSelect, offset);
danielk1977f29ce552002-05-19 23:43:12 +000092 if( ss->target.z ){
93 ss->target.z += offset;
94 }
danielk1977c3f9bad2002-05-15 08:30:12 +000095 sqliteExprMoveStrings(ss->pWhere, offset);
96 sqliteExprListMoveStrings(ss->pExprList, offset);
97
98 ss = ss->pNext;
99 }
100
101 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000102 ** build the sqlite_master entry
103 */
104 if( !pParse->initFlag && !tab->isTemp ){
drhc977f7f2002-05-21 11:38:11 +0000105 static VdbeOp insertTrig[] = {
106 { OP_OpenWrite, 0, 2, MASTER_NAME},
107 { OP_NewRecno, 0, 0, 0 },
108 { OP_String, 0, 0, "trigger" },
109 { OP_String, 0, 0, 0 }, /* 3: trigger name */
110 { OP_String, 0, 0, 0 }, /* 4: table name */
111 { OP_Integer, 0, 0, 0 },
112 { OP_String, 0, 0, 0 }, /* 6: SQL */
113 { OP_MakeRecord, 5, 0, 0 },
114 { OP_PutIntKey, 0, 0, 0 },
115 { OP_Integer, 0, 0, 0 }, /* 9: Next cookie */
116 { OP_SetCookie, 0, 0, 0 },
117 { OP_Close, 0, 0, 0 },
118 };
119 int addr;
120 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000121
122 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000123 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000124 if( v==0 ) goto trigger_cleanup;
drhc977f7f2002-05-21 11:38:11 +0000125 sqliteBeginWriteOperation(pParse, 0);
126 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
127 sqliteVdbeChangeP3(v, addr+3, nt->name, 0);
128 sqliteVdbeChangeP3(v, addr+4, nt->table, 0);
129 sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);
drhdc379452002-05-15 12:45:43 +0000130 sqliteChangeCookie(pParse->db);
drhc977f7f2002-05-21 11:38:11 +0000131 sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);
danielk1977c3f9bad2002-05-15 08:30:12 +0000132 sqliteEndWriteOperation(pParse);
133 }
134
danielk1977633ed082002-05-17 00:05:58 +0000135 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000136 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000137 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000138
139 /* Attach it to the table object */
140 nt->pNext = tab->pTrigger;
141 tab->pTrigger = nt;
142 return;
danielk1977f29ce552002-05-19 23:43:12 +0000143 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000144 sqliteFree(nt->strings);
145 sqliteFree(nt->name);
146 sqliteFree(nt->table);
147 sqliteFree(nt);
148 }
149
150trigger_cleanup:
151
danielk1977633ed082002-05-17 00:05:58 +0000152 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000153 sqliteExprDelete(pWhen);
154 {
155 TriggerStep * pp;
156 TriggerStep * nn;
157
danielk1977633ed082002-05-17 00:05:58 +0000158 pp = pStepList;
danielk1977f29ce552002-05-19 23:43:12 +0000159 while( pp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000160 nn = pp->pNext;
161 sqliteExprDelete(pp->pWhere);
162 sqliteExprListDelete(pp->pExprList);
163 sqliteSelectDelete(pp->pSelect);
164 sqliteIdListDelete(pp->pIdList);
165 sqliteFree(pp);
166 pp = nn;
167 }
168 }
169}
170
drhc977f7f2002-05-21 11:38:11 +0000171/*
172** Turn a SELECT statement (that the pSelect parameter points to) into
173** a trigger step. Return a pointer to a TriggerStep structure.
174**
175** The parser calls this routine when it finds a SELECT statement in
176** body of a TRIGGER.
177*/
178TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000179 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000180 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000181
danielk1977633ed082002-05-17 00:05:58 +0000182 pTriggerStep->op = TK_SELECT;
183 pTriggerStep->pSelect = pSelect;
184 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000185
danielk1977633ed082002-05-17 00:05:58 +0000186 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000187}
188
drhc977f7f2002-05-21 11:38:11 +0000189/*
190** Build a trigger step out of an INSERT statement. Return a pointer
191** to the new trigger step.
192**
193** The parser calls this routine when it sees an INSERT inside the
194** body of a trigger.
195*/
danielk1977633ed082002-05-17 00:05:58 +0000196TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000197 Token *pTableName, /* Name of the table into which we insert */
198 IdList *pColumn, /* List of columns in pTableName to insert into */
199 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
200 Select *pSelect, /* A SELECT statement that supplies values */
201 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000202){
203 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000204 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000205
danielk1977633ed082002-05-17 00:05:58 +0000206 assert(pEList == 0 || pSelect == 0);
207 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000208
danielk1977633ed082002-05-17 00:05:58 +0000209 pTriggerStep->op = TK_INSERT;
210 pTriggerStep->pSelect = pSelect;
211 pTriggerStep->target = *pTableName;
212 pTriggerStep->pIdList = pColumn;
213 pTriggerStep->pExprList = pEList;
214 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000215
danielk1977633ed082002-05-17 00:05:58 +0000216 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000217}
218
drhc977f7f2002-05-21 11:38:11 +0000219/*
220** Construct a trigger step that implements an UPDATE statement and return
221** a pointer to that trigger step. The parser calls this routine when it
222** sees an UPDATE statement inside the body of a CREATE TRIGGER.
223*/
danielk1977633ed082002-05-17 00:05:58 +0000224TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000225 Token *pTableName, /* Name of the table to be updated */
226 ExprList *pEList, /* The SET clause: list of column and new values */
227 Expr *pWhere, /* The WHERE clause */
228 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
229){
danielk1977633ed082002-05-17 00:05:58 +0000230 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000231 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000232
danielk1977633ed082002-05-17 00:05:58 +0000233 pTriggerStep->op = TK_UPDATE;
234 pTriggerStep->target = *pTableName;
235 pTriggerStep->pExprList = pEList;
236 pTriggerStep->pWhere = pWhere;
237 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000238
danielk1977633ed082002-05-17 00:05:58 +0000239 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000240}
241
drhc977f7f2002-05-21 11:38:11 +0000242/*
243** Construct a trigger step that implements a DELETE statement and return
244** a pointer to that trigger step. The parser calls this routine when it
245** sees a DELETE statement inside the body of a CREATE TRIGGER.
246*/
247TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000248 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
249 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000250
danielk1977633ed082002-05-17 00:05:58 +0000251 pTriggerStep->op = TK_DELETE;
252 pTriggerStep->target = *pTableName;
253 pTriggerStep->pWhere = pWhere;
254 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000255
danielk1977633ed082002-05-17 00:05:58 +0000256 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000257}
258
danielk1977633ed082002-05-17 00:05:58 +0000259/*
260** Recursively delete a Trigger structure
261*/
drh1d1f3052002-05-21 13:18:25 +0000262void sqliteDeleteTrigger(Trigger *pTrigger){
danielk1977633ed082002-05-17 00:05:58 +0000263 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000264
danielk1977633ed082002-05-17 00:05:58 +0000265 pTriggerStep = pTrigger->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000266 while( pTriggerStep ){
danielk1977633ed082002-05-17 00:05:58 +0000267 TriggerStep * pTmp = pTriggerStep;
268 pTriggerStep = pTriggerStep->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000269
danielk1977633ed082002-05-17 00:05:58 +0000270 sqliteExprDelete(pTmp->pWhere);
271 sqliteExprListDelete(pTmp->pExprList);
272 sqliteSelectDelete(pTmp->pSelect);
273 sqliteIdListDelete(pTmp->pIdList);
danielk1977c3f9bad2002-05-15 08:30:12 +0000274
danielk1977633ed082002-05-17 00:05:58 +0000275 sqliteFree(pTmp);
danielk1977c3f9bad2002-05-15 08:30:12 +0000276 }
277
danielk1977633ed082002-05-17 00:05:58 +0000278 sqliteFree(pTrigger->name);
279 sqliteFree(pTrigger->table);
280 sqliteExprDelete(pTrigger->pWhen);
281 sqliteIdListDelete(pTrigger->pColumns);
282 sqliteFree(pTrigger->strings);
283 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000284}
285
286/*
danielk1977633ed082002-05-17 00:05:58 +0000287 * This function is called to drop a trigger from the database schema.
288 *
289 * This may be called directly from the parser, or from within
290 * sqliteDropTable(). In the latter case the "nested" argument is true.
291 *
292 * Note that this function does not delete the trigger entirely. Instead it
293 * removes it from the internal schema and places it in the trigDrop hash
294 * table. This is so that the trigger can be restored into the database schema
295 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000296 */
danielk1977633ed082002-05-17 00:05:58 +0000297void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
danielk1977c3f9bad2002-05-15 08:30:12 +0000298{
danielk1977633ed082002-05-17 00:05:58 +0000299 char *zName;
300 Trigger *pTrigger;
301 Table *pTable;
danielk1977c3f9bad2002-05-15 08:30:12 +0000302
danielk1977633ed082002-05-17 00:05:58 +0000303 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000304
305 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000306 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
307 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000308 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000309 zName, -1, 0);
310 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000311 return;
312 }
313
314 /*
315 * If this is not an "explain", do the following:
316 * 1. Remove the trigger from its associated table structure
317 * 2. Move the trigger from the trigHash hash to trigDrop
318 */
danielk1977633ed082002-05-17 00:05:58 +0000319 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000320 /* 1 */
danielk1977633ed082002-05-17 00:05:58 +0000321 pTable = sqliteFindTable(pParse->db, pTrigger->table);
322 assert(pTable);
323 if( pTable->pTrigger == pTrigger ){
324 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000325 }else{
danielk1977633ed082002-05-17 00:05:58 +0000326 Trigger *cc = pTable->pTrigger;
327 while( cc ){
328 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000329 cc->pNext = cc->pNext->pNext;
330 break;
331 }
332 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000333 }
334 assert(cc);
335 }
336
337 /* 2 */
danielk1977633ed082002-05-17 00:05:58 +0000338 sqliteHashInsert(&(pParse->db->trigHash), zName,
339 pName->n + 1, NULL);
340 sqliteHashInsert(&(pParse->db->trigDrop), pTrigger->name,
341 pName->n + 1, pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000342 }
343
344 /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
345 * database record of the trigger */
danielk1977633ed082002-05-17 00:05:58 +0000346 if( !pTable->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000347 int base;
348 static VdbeOp dropTrigger[] = {
349 { OP_OpenWrite, 0, 2, MASTER_NAME},
350 { OP_Rewind, 0, ADDR(9), 0},
351 { OP_String, 0, 0, 0}, /* 2 */
352 { OP_MemStore, 1, 1, 0},
353 { OP_MemLoad, 1, 0, 0}, /* 4 */
354 { OP_Column, 0, 1, 0},
355 { OP_Ne, 0, ADDR(8), 0},
356 { OP_Delete, 0, 0, 0},
357 { OP_Next, 0, ADDR(4), 0}, /* 8 */
358 { OP_Integer, 0, 0, 0}, /* 9 */
359 { OP_SetCookie, 0, 0, 0},
360 { OP_Close, 0, 0, 0},
361 };
362
drhdc379452002-05-15 12:45:43 +0000363 if( !nested ){
drhc977f7f2002-05-21 11:38:11 +0000364 sqliteBeginWriteOperation(pParse, 0);
drhdc379452002-05-15 12:45:43 +0000365 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000366 base = sqliteVdbeAddOpList(pParse->pVdbe,
drh9adf9ac2002-05-15 11:44:13 +0000367 ArraySize(dropTrigger), dropTrigger);
danielk1977633ed082002-05-17 00:05:58 +0000368 sqliteVdbeChangeP3(pParse->pVdbe, base+2, zName, 0);
drhdc379452002-05-15 12:45:43 +0000369 if( !nested ){
370 sqliteChangeCookie(pParse->db);
371 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000372 sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
drhdc379452002-05-15 12:45:43 +0000373 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000374 sqliteEndWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000375 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000376 }
377
danielk1977633ed082002-05-17 00:05:58 +0000378 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000379}
380
drhc977f7f2002-05-21 11:38:11 +0000381/*
382** pEList is the SET clause of an UPDATE statement. Each entry
383** in pEList is of the format <id>=<expr>. If any of the entries
384** in pEList have an <id> which matches an identifier in pIdList,
385** then return TRUE. If pIdList==NULL, then it is considered a
386** wildcard that matches anything. Likewise if pEList==NULL then
387** it matches anything so always return true. Return false only
388** if there is no match.
389*/
390static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
danielk1977c3f9bad2002-05-15 08:30:12 +0000391 int i, e;
danielk1977f29ce552002-05-19 23:43:12 +0000392 if( !pIdList )return 1;
393 if( !pEList )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000394
danielk1977f29ce552002-05-19 23:43:12 +0000395 for(i = 0; i < pIdList->nId; i++){
396 for(e = 0; e < pEList->nExpr; e++){
397 if( !sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName) ){
drh9adf9ac2002-05-15 11:44:13 +0000398 return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000399 }
400 }
401 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000402
403 return 0;
404}
405
406/* A global variable that is TRUE if we should always set up temp tables for
407 * for triggers, even if there are no triggers to code. This is used to test
408 * how much overhead the triggers algorithm is causing.
409 *
410 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
411 * The pragma is not documented since it is not really part of the interface
412 * to SQLite, just the test procedure.
413*/
414int always_code_trigger_setup = 0;
415
416/*
417 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
418 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
419 * found in the list specified as pTrigger.
420 */
421int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000422 Parse *pParse, /* Used to check for recursive triggers */
423 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000424 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
425 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
426 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000427 ExprList *pChanges /* Columns that change in an UPDATE statement */
428){
danielk1977633ed082002-05-17 00:05:58 +0000429 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000430
danielk1977633ed082002-05-17 00:05:58 +0000431 if( always_code_trigger_setup ){
432 return 1;
433 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000434
danielk1977633ed082002-05-17 00:05:58 +0000435 pTriggerCursor = pTrigger;
436 while( pTriggerCursor ){
437 if( pTriggerCursor->op == op &&
438 pTriggerCursor->tr_tm == tr_tm &&
439 pTriggerCursor->foreach == foreach &&
440 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000441 TriggerStack * ss;
442 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000443 while( ss && ss->pTrigger != pTrigger ){
444 ss = ss->pNext;
445 }
446 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000447 }
danielk1977633ed082002-05-17 00:05:58 +0000448 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000449 }
450
451 return 0;
452}
453
drhc977f7f2002-05-21 11:38:11 +0000454/*
455** Generate VDBE code for zero or more statements inside the body of a
456** trigger.
457*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000458static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000459 Parse *pParse, /* The parser context */
460 TriggerStep *pStepList, /* List of statements inside the trigger body */
461 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000462){
463 TriggerStep * pTriggerStep = pStepList;
464 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000465
danielk1977633ed082002-05-17 00:05:58 +0000466 while( pTriggerStep ){
467 int saveNTab = pParse->nTab;
468 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
469 pParse->trigStack->orconf = orconf;
470 switch( pTriggerStep->op ){
471 case TK_SELECT: {
472 int tmp_tbl = pParse->nTab++;
473 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenTemp, tmp_tbl, 0);
474 sqliteVdbeAddOp(pParse->pVdbe, OP_KeyAsData, tmp_tbl, 1);
475 sqliteSelect(pParse, pTriggerStep->pSelect, SRT_Union,
476 tmp_tbl, 0, 0, 0);
477 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, tmp_tbl, 0);
478 pParse->nTab--;
479 break;
480 }
481 case TK_UPDATE: {
drhbd5a4512002-05-23 22:07:02 +0000482 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000483 sqliteUpdate(pParse, &pTriggerStep->target,
484 sqliteExprListDup(pTriggerStep->pExprList),
485 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000486 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000487 break;
488 }
489 case TK_INSERT: {
490 sqliteInsert(pParse, &pTriggerStep->target,
491 sqliteExprListDup(pTriggerStep->pExprList),
492 sqliteSelectDup(pTriggerStep->pSelect),
493 sqliteIdListDup(pTriggerStep->pIdList), orconf);
494 break;
495 }
496 case TK_DELETE: {
drhbd5a4512002-05-23 22:07:02 +0000497 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000498 sqliteDeleteFrom(pParse, &pTriggerStep->target,
499 sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000500 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000501 break;
502 }
503 default:
504 assert(0);
505 }
506 pParse->nTab = saveNTab;
507 pTriggerStep = pTriggerStep->pNext;
508 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000509
danielk1977633ed082002-05-17 00:05:58 +0000510 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000511}
512
danielk1977633ed082002-05-17 00:05:58 +0000513/*
514** This is called to code FOR EACH ROW triggers.
515**
516** When the code that this function generates is executed, the following
517** must be true:
drhc977f7f2002-05-21 11:38:11 +0000518**
519** 1. No cursors may be open in the main database. (But newIdx and oldIdx
520** can be indices of cursors in temporary tables. See below.)
521**
danielk1977633ed082002-05-17 00:05:58 +0000522** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
523** a temporary vdbe cursor (index newIdx) must be open and pointing at
524** a row containing values to be substituted for new.* expressions in the
525** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000526**
danielk1977633ed082002-05-17 00:05:58 +0000527** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
528** a temporary vdbe cursor (index oldIdx) must be open and pointing at
529** a row containing values to be substituted for old.* expressions in the
530** trigger program(s).
531**
532*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000533int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000534 Parse *pParse, /* Parse context */
535 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
536 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
537 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
538 Table *pTab, /* The table to code triggers from */
539 int newIdx, /* The indice of the "new" row to access */
540 int oldIdx, /* The indice of the "old" row to access */
drhc977f7f2002-05-21 11:38:11 +0000541 int orconf /* ON CONFLICT policy */
542){
danielk1977c3f9bad2002-05-15 08:30:12 +0000543 Trigger * pTrigger;
544 TriggerStack * pTriggerStack;
545
danielk1977c3f9bad2002-05-15 08:30:12 +0000546 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
547 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
548
danielk1977633ed082002-05-17 00:05:58 +0000549 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000550
danielk1977633ed082002-05-17 00:05:58 +0000551 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000552 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000553 int fire_this = 0;
554
555 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000556 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
557 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000558 fire_this = 1;
559 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000560 while( pTriggerStack ){
561 if( pTriggerStack->pTrigger == pTrigger ){
562 fire_this = 0;
563 }
drh9adf9ac2002-05-15 11:44:13 +0000564 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000565 }
danielk1977f29ce552002-05-19 23:43:12 +0000566 if( op == TK_UPDATE && pTrigger->pColumns &&
567 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000568 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000569 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000570 }
571
drhe4697f52002-05-23 02:09:03 +0000572 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000573 int endTrigger;
574 IdList dummyTablist;
575 Expr * whenExpr;
576
577 dummyTablist.nId = 0;
578 dummyTablist.a = 0;
579
580 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000581 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000582 pTriggerStack->newIdx = newIdx;
583 pTriggerStack->oldIdx = oldIdx;
584 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000585 pTriggerStack->pNext = pParse->trigStack;
586 pParse->trigStack = pTriggerStack;
587
588 /* code the WHEN clause */
589 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
590 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000591 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000592 pParse->trigStack = pParse->trigStack->pNext;
593 sqliteFree(pTriggerStack);
594 sqliteExprDelete(whenExpr);
595 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000596 }
597 sqliteExprIfFalse(pParse, whenExpr, endTrigger);
598 sqliteExprDelete(whenExpr);
599
danielk1977633ed082002-05-17 00:05:58 +0000600 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000601
602 /* Pop the entry off the trigger stack */
603 pParse->trigStack = pParse->trigStack->pNext;
604 sqliteFree(pTriggerStack);
605
606 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
607 }
608 pTrigger = pTrigger->pNext;
609 }
610
611 return 0;
612}
613
614/*
danielk1977633ed082002-05-17 00:05:58 +0000615 * This function is called to code ON UPDATE and ON DELETE triggers on
616 * views.
617 *
618 * This function deletes the data pointed at by the pWhere and pChanges
619 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000620 */
danielk1977633ed082002-05-17 00:05:58 +0000621void sqliteViewTriggers(
622 Parse *pParse,
623 Table *pTab, /* The view to code triggers on */
624 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
625 int orconf, /* The ON CONFLICT policy specified as part of the
626 statement causing these triggers */
627 ExprList *pChanges /* If this is an statement causing triggers to fire
628 is an UPDATE, then this list holds the columns
629 to update and the expressions to update them to.
630 See comments for sqliteUpdate(). */
631){
danielk1977c3f9bad2002-05-15 08:30:12 +0000632 int oldIdx = -1;
633 int newIdx = -1;
634 int *aXRef = 0;
635 Vdbe *v;
636 int endOfLoop;
637 int startOfLoop;
638 Select theSelect;
639 Token tblNameToken;
640
641 assert(pTab->pSelect);
642
643 tblNameToken.z = pTab->zName;
644 tblNameToken.n = strlen(pTab->zName);
645
646 theSelect.isDistinct = 0;
647 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
648 theSelect.pSrc = sqliteIdListAppend(0, &tblNameToken);
649 theSelect.pWhere = pWhere; pWhere = 0;
650 theSelect.pGroupBy = 0;
651 theSelect.pHaving = 0;
652 theSelect.pOrderBy = 0;
653 theSelect.op = TK_SELECT; /* ?? */
654 theSelect.pPrior = 0;
655 theSelect.nLimit = -1;
656 theSelect.nOffset = -1;
657 theSelect.zSelect = 0;
658 theSelect.base = 0;
659
660 v = sqliteGetVdbe(pParse);
661 assert(v);
drhc977f7f2002-05-21 11:38:11 +0000662 sqliteBeginWriteOperation(pParse, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000663
664 /* Allocate temp tables */
665 oldIdx = pParse->nTab++;
666 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000667 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000668 newIdx = pParse->nTab++;
669 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
670 }
671
672 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000673 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000674 goto trigger_cleanup;
675 }
676
677 /* loop thru the view snapshot, executing triggers for each row */
678 endOfLoop = sqliteVdbeMakeLabel(v);
679 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
680
681 /* Loop thru the view snapshot, executing triggers for each row */
682 startOfLoop = sqliteVdbeCurrentAddr(v);
683
684 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000685 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000686 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000687
688 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
689 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000690 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000691 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000692 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000693
694 for(ii=0; ii<pChanges->nExpr; ii++){
695 int jj;
696 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000697 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000698 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000699 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000700
701 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000702 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000703
704 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000705 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
706 aXRef[jj] = ii;
707 break;
708 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000709 }
710 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000711 sqliteSetString(&pParse->zErrMsg, "no such column: ",
712 pChanges->a[ii].zName, 0);
713 pParse->nErr++;
714 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000715 }
716 }
717
718 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
719
danielk1977633ed082002-05-17 00:05:58 +0000720 for(ii = 0; ii<pTab->nCol; ii++){
721 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000722 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000723 }else{
drh9adf9ac2002-05-15 11:44:13 +0000724 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000725 }
726 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000727
728 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
729 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
730 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
731
732 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk1977633ed082002-05-17 00:05:58 +0000733 pTab, newIdx, oldIdx, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000734 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk1977633ed082002-05-17 00:05:58 +0000735 pTab, newIdx, oldIdx, orconf);
danielk1977f29ce552002-05-19 23:43:12 +0000736 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000737 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000738 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000739 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000740 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000741 }
742
743 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
744
745 sqliteVdbeResolveLabel(v, endOfLoop);
746 sqliteEndWriteOperation(pParse);
747
748trigger_cleanup:
749 sqliteFree(aXRef);
750 sqliteExprListDelete(pChanges);
751 sqliteExprDelete(pWhere);
752 sqliteExprListDelete(theSelect.pEList);
753 sqliteIdListDelete(theSelect.pSrc);
754 sqliteExprDelete(theSelect.pWhere);
755 return;
756}