blob: 82ba258a01fc44eb5f69e7c8dcc64a5769b8e1d2 [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){
drhad2d8302002-05-24 20:31:36 +0000391 int e;
392 if( !pIdList || !pEList ) return 1;
393 for(e=0; e<pEList->nExpr; e++){
394 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000395 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000396 return 0;
397}
398
399/* A global variable that is TRUE if we should always set up temp tables for
400 * for triggers, even if there are no triggers to code. This is used to test
401 * how much overhead the triggers algorithm is causing.
402 *
403 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
404 * The pragma is not documented since it is not really part of the interface
405 * to SQLite, just the test procedure.
406*/
407int always_code_trigger_setup = 0;
408
409/*
410 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
411 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
412 * found in the list specified as pTrigger.
413 */
414int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000415 Parse *pParse, /* Used to check for recursive triggers */
416 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000417 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
418 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
419 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000420 ExprList *pChanges /* Columns that change in an UPDATE statement */
421){
danielk1977633ed082002-05-17 00:05:58 +0000422 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000423
danielk1977633ed082002-05-17 00:05:58 +0000424 if( always_code_trigger_setup ){
425 return 1;
426 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000427
danielk1977633ed082002-05-17 00:05:58 +0000428 pTriggerCursor = pTrigger;
429 while( pTriggerCursor ){
430 if( pTriggerCursor->op == op &&
431 pTriggerCursor->tr_tm == tr_tm &&
432 pTriggerCursor->foreach == foreach &&
433 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000434 TriggerStack * ss;
435 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000436 while( ss && ss->pTrigger != pTrigger ){
437 ss = ss->pNext;
438 }
439 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000440 }
danielk1977633ed082002-05-17 00:05:58 +0000441 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000442 }
443
444 return 0;
445}
446
drhc977f7f2002-05-21 11:38:11 +0000447/*
448** Generate VDBE code for zero or more statements inside the body of a
449** trigger.
450*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000451static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000452 Parse *pParse, /* The parser context */
453 TriggerStep *pStepList, /* List of statements inside the trigger body */
454 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000455){
456 TriggerStep * pTriggerStep = pStepList;
457 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000458
danielk1977633ed082002-05-17 00:05:58 +0000459 while( pTriggerStep ){
460 int saveNTab = pParse->nTab;
461 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
462 pParse->trigStack->orconf = orconf;
463 switch( pTriggerStep->op ){
464 case TK_SELECT: {
465 int tmp_tbl = pParse->nTab++;
466 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenTemp, tmp_tbl, 0);
467 sqliteVdbeAddOp(pParse->pVdbe, OP_KeyAsData, tmp_tbl, 1);
468 sqliteSelect(pParse, pTriggerStep->pSelect, SRT_Union,
469 tmp_tbl, 0, 0, 0);
470 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, tmp_tbl, 0);
471 pParse->nTab--;
472 break;
473 }
474 case TK_UPDATE: {
drhbd5a4512002-05-23 22:07:02 +0000475 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000476 sqliteUpdate(pParse, &pTriggerStep->target,
477 sqliteExprListDup(pTriggerStep->pExprList),
478 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000479 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000480 break;
481 }
482 case TK_INSERT: {
483 sqliteInsert(pParse, &pTriggerStep->target,
484 sqliteExprListDup(pTriggerStep->pExprList),
485 sqliteSelectDup(pTriggerStep->pSelect),
486 sqliteIdListDup(pTriggerStep->pIdList), orconf);
487 break;
488 }
489 case TK_DELETE: {
drhbd5a4512002-05-23 22:07:02 +0000490 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000491 sqliteDeleteFrom(pParse, &pTriggerStep->target,
492 sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000493 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000494 break;
495 }
496 default:
497 assert(0);
498 }
499 pParse->nTab = saveNTab;
500 pTriggerStep = pTriggerStep->pNext;
501 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000502
danielk1977633ed082002-05-17 00:05:58 +0000503 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000504}
505
danielk1977633ed082002-05-17 00:05:58 +0000506/*
507** This is called to code FOR EACH ROW triggers.
508**
509** When the code that this function generates is executed, the following
510** must be true:
drhc977f7f2002-05-21 11:38:11 +0000511**
512** 1. No cursors may be open in the main database. (But newIdx and oldIdx
513** can be indices of cursors in temporary tables. See below.)
514**
danielk1977633ed082002-05-17 00:05:58 +0000515** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
516** a temporary vdbe cursor (index newIdx) must be open and pointing at
517** a row containing values to be substituted for new.* expressions in the
518** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000519**
danielk1977633ed082002-05-17 00:05:58 +0000520** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
521** a temporary vdbe cursor (index oldIdx) must be open and pointing at
522** a row containing values to be substituted for old.* expressions in the
523** trigger program(s).
524**
525*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000526int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000527 Parse *pParse, /* Parse context */
528 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
529 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
530 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
531 Table *pTab, /* The table to code triggers from */
532 int newIdx, /* The indice of the "new" row to access */
533 int oldIdx, /* The indice of the "old" row to access */
drhc977f7f2002-05-21 11:38:11 +0000534 int orconf /* ON CONFLICT policy */
535){
danielk1977c3f9bad2002-05-15 08:30:12 +0000536 Trigger * pTrigger;
537 TriggerStack * pTriggerStack;
538
danielk1977c3f9bad2002-05-15 08:30:12 +0000539 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
540 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
541
danielk1977633ed082002-05-17 00:05:58 +0000542 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000543
danielk1977633ed082002-05-17 00:05:58 +0000544 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000545 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000546 int fire_this = 0;
547
548 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000549 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
550 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000551 fire_this = 1;
552 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000553 while( pTriggerStack ){
554 if( pTriggerStack->pTrigger == pTrigger ){
555 fire_this = 0;
556 }
drh9adf9ac2002-05-15 11:44:13 +0000557 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000558 }
danielk1977f29ce552002-05-19 23:43:12 +0000559 if( op == TK_UPDATE && pTrigger->pColumns &&
560 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000561 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000562 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000563 }
564
drhe4697f52002-05-23 02:09:03 +0000565 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000566 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000567 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000568 Expr * whenExpr;
569
drhad3cab52002-05-24 02:04:32 +0000570 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000571 dummyTablist.a = 0;
572
573 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000574 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000575 pTriggerStack->newIdx = newIdx;
576 pTriggerStack->oldIdx = oldIdx;
577 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000578 pTriggerStack->pNext = pParse->trigStack;
579 pParse->trigStack = pTriggerStack;
580
581 /* code the WHEN clause */
582 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
583 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000584 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000585 pParse->trigStack = pParse->trigStack->pNext;
586 sqliteFree(pTriggerStack);
587 sqliteExprDelete(whenExpr);
588 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000589 }
drhf5905aa2002-05-26 20:54:33 +0000590 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000591 sqliteExprDelete(whenExpr);
592
danielk1977633ed082002-05-17 00:05:58 +0000593 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000594
595 /* Pop the entry off the trigger stack */
596 pParse->trigStack = pParse->trigStack->pNext;
597 sqliteFree(pTriggerStack);
598
599 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
600 }
601 pTrigger = pTrigger->pNext;
602 }
603
604 return 0;
605}
606
607/*
danielk1977633ed082002-05-17 00:05:58 +0000608 * This function is called to code ON UPDATE and ON DELETE triggers on
609 * views.
610 *
611 * This function deletes the data pointed at by the pWhere and pChanges
612 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000613 */
danielk1977633ed082002-05-17 00:05:58 +0000614void sqliteViewTriggers(
615 Parse *pParse,
616 Table *pTab, /* The view to code triggers on */
617 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
618 int orconf, /* The ON CONFLICT policy specified as part of the
619 statement causing these triggers */
620 ExprList *pChanges /* If this is an statement causing triggers to fire
621 is an UPDATE, then this list holds the columns
622 to update and the expressions to update them to.
623 See comments for sqliteUpdate(). */
624){
danielk1977c3f9bad2002-05-15 08:30:12 +0000625 int oldIdx = -1;
626 int newIdx = -1;
627 int *aXRef = 0;
628 Vdbe *v;
629 int endOfLoop;
630 int startOfLoop;
631 Select theSelect;
632 Token tblNameToken;
633
634 assert(pTab->pSelect);
635
636 tblNameToken.z = pTab->zName;
637 tblNameToken.n = strlen(pTab->zName);
638
639 theSelect.isDistinct = 0;
640 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drhad3cab52002-05-24 02:04:32 +0000641 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken);
danielk1977c3f9bad2002-05-15 08:30:12 +0000642 theSelect.pWhere = pWhere; pWhere = 0;
643 theSelect.pGroupBy = 0;
644 theSelect.pHaving = 0;
645 theSelect.pOrderBy = 0;
646 theSelect.op = TK_SELECT; /* ?? */
647 theSelect.pPrior = 0;
648 theSelect.nLimit = -1;
649 theSelect.nOffset = -1;
650 theSelect.zSelect = 0;
651 theSelect.base = 0;
652
653 v = sqliteGetVdbe(pParse);
654 assert(v);
drhc977f7f2002-05-21 11:38:11 +0000655 sqliteBeginWriteOperation(pParse, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000656
657 /* Allocate temp tables */
658 oldIdx = pParse->nTab++;
659 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000660 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000661 newIdx = pParse->nTab++;
662 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
663 }
664
665 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000666 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000667 goto trigger_cleanup;
668 }
669
670 /* loop thru the view snapshot, executing triggers for each row */
671 endOfLoop = sqliteVdbeMakeLabel(v);
672 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
673
674 /* Loop thru the view snapshot, executing triggers for each row */
675 startOfLoop = sqliteVdbeCurrentAddr(v);
676
677 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000678 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000679 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000680
681 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
682 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000683 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000684 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000685 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000686
687 for(ii=0; ii<pChanges->nExpr; ii++){
688 int jj;
689 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000690 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000691 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000692 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000693
694 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000695 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000696
697 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000698 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
699 aXRef[jj] = ii;
700 break;
701 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000702 }
703 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000704 sqliteSetString(&pParse->zErrMsg, "no such column: ",
705 pChanges->a[ii].zName, 0);
706 pParse->nErr++;
707 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000708 }
709 }
710
711 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
712
danielk1977633ed082002-05-17 00:05:58 +0000713 for(ii = 0; ii<pTab->nCol; ii++){
714 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000715 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000716 }else{
drh9adf9ac2002-05-15 11:44:13 +0000717 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000718 }
719 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000720
721 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
722 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
723 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
724
725 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk1977633ed082002-05-17 00:05:58 +0000726 pTab, newIdx, oldIdx, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000727 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk1977633ed082002-05-17 00:05:58 +0000728 pTab, newIdx, oldIdx, orconf);
danielk1977f29ce552002-05-19 23:43:12 +0000729 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000730 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000731 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000732 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000733 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000734 }
735
736 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
737
738 sqliteVdbeResolveLabel(v, endOfLoop);
739 sqliteEndWriteOperation(pParse);
740
741trigger_cleanup:
742 sqliteFree(aXRef);
743 sqliteExprListDelete(pChanges);
744 sqliteExprDelete(pWhere);
745 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000746 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000747 sqliteExprDelete(theSelect.pWhere);
748 return;
749}