blob: 50aa23b4601bdeab6aefc855f50fb7b2974c8846 [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);
danielk1977c3f9bad2002-05-15 08:30:12 +000055 tab = sqliteFindTable(pParse->db, tmp_str);
56 sqliteFree(tmp_str);
drh9adf9ac2002-05-15 11:44:13 +000057 if( !tab ){
danielk1977c3f9bad2002-05-15 08:30:12 +000058 sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
danielk1977633ed082002-05-17 00:05:58 +000059 pTableName->z, pTableName->n, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000060 pParse->nErr++;
61 goto trigger_cleanup;
62 }
63 }
64
65 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +000066 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
danielk1977633ed082002-05-17 00:05:58 +000067 nt->name = sqliteStrNDup(pName->z, pName->n);
68 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +000069 nt->op = op;
70 nt->tr_tm = tr_tm;
71 nt->pWhen = pWhen;
danielk1977633ed082002-05-17 00:05:58 +000072 nt->pColumns = pColumns;
danielk1977c3f9bad2002-05-15 08:30:12 +000073 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +000074 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +000075 nt->isCommit = 0;
76
danielk1977633ed082002-05-17 00:05:58 +000077 nt->strings = sqliteStrNDup(zData, zDataLen);
78 offset = (int)(nt->strings - zData);
danielk1977c3f9bad2002-05-15 08:30:12 +000079
80 sqliteExprMoveStrings(nt->pWhen, offset);
81
82 ss = nt->step_list;
83 while (ss) {
84 sqliteSelectMoveStrings(ss->pSelect, offset);
85 if (ss->target.z) ss->target.z += offset;
86 sqliteExprMoveStrings(ss->pWhere, offset);
87 sqliteExprListMoveStrings(ss->pExprList, offset);
88
89 ss = ss->pNext;
90 }
91
92 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +000093 ** build the sqlite_master entry
94 */
95 if( !pParse->initFlag && !tab->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +000096
97 /* Make an entry in the sqlite_master table */
98 sqliteBeginWriteOperation(pParse);
99
100 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenWrite, 0, 2);
101 sqliteVdbeChangeP3(pParse->pVdbe, -1, MASTER_NAME, P3_STATIC);
102 sqliteVdbeAddOp(pParse->pVdbe, OP_NewRecno, 0, 0);
103 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
104 sqliteVdbeChangeP3(pParse->pVdbe, -1, "trigger", P3_STATIC);
105 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
106 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->name, 0);
107 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
108 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->table, 0);
109 sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, 0, 0);
110 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
111 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->strings, 0);
112 sqliteVdbeAddOp(pParse->pVdbe, OP_MakeRecord, 5, 0);
113 sqliteVdbeAddOp(pParse->pVdbe, OP_PutIntKey, 0, 1);
114
115 /* Change the cookie, since the schema is changed */
drhdc379452002-05-15 12:45:43 +0000116 sqliteChangeCookie(pParse->db);
danielk1977c3f9bad2002-05-15 08:30:12 +0000117 sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, pParse->db->next_cookie, 0);
118 sqliteVdbeAddOp(pParse->pVdbe, OP_SetCookie, 0, 0);
119
120 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, 0, 0);
121
122 sqliteEndWriteOperation(pParse);
123 }
124
danielk1977633ed082002-05-17 00:05:58 +0000125 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000126 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000127 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000128
129 /* Attach it to the table object */
130 nt->pNext = tab->pTrigger;
131 tab->pTrigger = nt;
132 return;
133 } else {
134 sqliteFree(nt->strings);
135 sqliteFree(nt->name);
136 sqliteFree(nt->table);
137 sqliteFree(nt);
138 }
139
140trigger_cleanup:
141
danielk1977633ed082002-05-17 00:05:58 +0000142 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000143 sqliteExprDelete(pWhen);
144 {
145 TriggerStep * pp;
146 TriggerStep * nn;
147
danielk1977633ed082002-05-17 00:05:58 +0000148 pp = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000149 while (pp) {
150 nn = pp->pNext;
151 sqliteExprDelete(pp->pWhere);
152 sqliteExprListDelete(pp->pExprList);
153 sqliteSelectDelete(pp->pSelect);
154 sqliteIdListDelete(pp->pIdList);
155 sqliteFree(pp);
156 pp = nn;
157 }
158 }
159}
160
danielk1977633ed082002-05-17 00:05:58 +0000161TriggerStep *sqliteTriggerSelectStep(Select * pSelect)
danielk1977c3f9bad2002-05-15 08:30:12 +0000162{
danielk1977633ed082002-05-17 00:05:58 +0000163 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000164
danielk1977633ed082002-05-17 00:05:58 +0000165 pTriggerStep->op = TK_SELECT;
166 pTriggerStep->pSelect = pSelect;
167 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000168
danielk1977633ed082002-05-17 00:05:58 +0000169 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000170}
171
danielk1977633ed082002-05-17 00:05:58 +0000172TriggerStep *sqliteTriggerInsertStep(
173 Token *pTableName,
174 IdList *pColumn,
175 ExprList *pEList,
176 Select *pSelect,
177 int orconf
178){
179 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000180
danielk1977633ed082002-05-17 00:05:58 +0000181 assert(pEList == 0 || pSelect == 0);
182 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000183
danielk1977633ed082002-05-17 00:05:58 +0000184 pTriggerStep->op = TK_INSERT;
185 pTriggerStep->pSelect = pSelect;
186 pTriggerStep->target = *pTableName;
187 pTriggerStep->pIdList = pColumn;
188 pTriggerStep->pExprList = pEList;
189 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000190
danielk1977633ed082002-05-17 00:05:58 +0000191 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000192}
193
danielk1977633ed082002-05-17 00:05:58 +0000194TriggerStep *sqliteTriggerUpdateStep(
195 Token *pTableName,
196 ExprList *pEList,
197 Expr *pWhere,
198 int orconf)
danielk1977c3f9bad2002-05-15 08:30:12 +0000199{
danielk1977633ed082002-05-17 00:05:58 +0000200 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000201
danielk1977633ed082002-05-17 00:05:58 +0000202 pTriggerStep->op = TK_UPDATE;
203 pTriggerStep->target = *pTableName;
204 pTriggerStep->pExprList = pEList;
205 pTriggerStep->pWhere = pWhere;
206 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000207
danielk1977633ed082002-05-17 00:05:58 +0000208 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000209}
210
danielk1977633ed082002-05-17 00:05:58 +0000211TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere)
danielk1977c3f9bad2002-05-15 08:30:12 +0000212{
danielk1977633ed082002-05-17 00:05:58 +0000213 TriggerStep * pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000214
danielk1977633ed082002-05-17 00:05:58 +0000215 pTriggerStep->op = TK_DELETE;
216 pTriggerStep->target = *pTableName;
217 pTriggerStep->pWhere = pWhere;
218 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000219
danielk1977633ed082002-05-17 00:05:58 +0000220 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000221}
222
danielk1977633ed082002-05-17 00:05:58 +0000223/*
224** Recursively delete a Trigger structure
225*/
226void sqliteDeleteTrigger(Trigger *pTrigger)
danielk1977c3f9bad2002-05-15 08:30:12 +0000227{
danielk1977633ed082002-05-17 00:05:58 +0000228 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000229
danielk1977633ed082002-05-17 00:05:58 +0000230 pTriggerStep = pTrigger->step_list;
231 while (pTriggerStep) {
232 TriggerStep * pTmp = pTriggerStep;
233 pTriggerStep = pTriggerStep->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000234
danielk1977633ed082002-05-17 00:05:58 +0000235 sqliteExprDelete(pTmp->pWhere);
236 sqliteExprListDelete(pTmp->pExprList);
237 sqliteSelectDelete(pTmp->pSelect);
238 sqliteIdListDelete(pTmp->pIdList);
danielk1977c3f9bad2002-05-15 08:30:12 +0000239
danielk1977633ed082002-05-17 00:05:58 +0000240 sqliteFree(pTmp);
danielk1977c3f9bad2002-05-15 08:30:12 +0000241 }
242
danielk1977633ed082002-05-17 00:05:58 +0000243 sqliteFree(pTrigger->name);
244 sqliteFree(pTrigger->table);
245 sqliteExprDelete(pTrigger->pWhen);
246 sqliteIdListDelete(pTrigger->pColumns);
247 sqliteFree(pTrigger->strings);
248 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000249}
250
251/*
danielk1977633ed082002-05-17 00:05:58 +0000252 * This function is called to drop a trigger from the database schema.
253 *
254 * This may be called directly from the parser, or from within
255 * sqliteDropTable(). In the latter case the "nested" argument is true.
256 *
257 * Note that this function does not delete the trigger entirely. Instead it
258 * removes it from the internal schema and places it in the trigDrop hash
259 * table. This is so that the trigger can be restored into the database schema
260 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000261 */
danielk1977633ed082002-05-17 00:05:58 +0000262void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
danielk1977c3f9bad2002-05-15 08:30:12 +0000263{
danielk1977633ed082002-05-17 00:05:58 +0000264 char *zName;
265 Trigger *pTrigger;
266 Table *pTable;
danielk1977c3f9bad2002-05-15 08:30:12 +0000267
danielk1977633ed082002-05-17 00:05:58 +0000268 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000269
270 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000271 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
272 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000273 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000274 zName, -1, 0);
275 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000276 return;
277 }
278
279 /*
280 * If this is not an "explain", do the following:
281 * 1. Remove the trigger from its associated table structure
282 * 2. Move the trigger from the trigHash hash to trigDrop
283 */
danielk1977633ed082002-05-17 00:05:58 +0000284 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000285 /* 1 */
danielk1977633ed082002-05-17 00:05:58 +0000286 pTable = sqliteFindTable(pParse->db, pTrigger->table);
287 assert(pTable);
288 if( pTable->pTrigger == pTrigger ){
289 pTable->pTrigger = pTrigger->pNext;
290 } else {
291 Trigger *cc = pTable->pTrigger;
292 while( cc ){
293 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000294 cc->pNext = cc->pNext->pNext;
295 break;
296 }
297 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000298 }
299 assert(cc);
300 }
301
302 /* 2 */
danielk1977633ed082002-05-17 00:05:58 +0000303 sqliteHashInsert(&(pParse->db->trigHash), zName,
304 pName->n + 1, NULL);
305 sqliteHashInsert(&(pParse->db->trigDrop), pTrigger->name,
306 pName->n + 1, pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000307 }
308
309 /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
310 * database record of the trigger */
danielk1977633ed082002-05-17 00:05:58 +0000311 if( !pTable->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000312 int base;
313 static VdbeOp dropTrigger[] = {
314 { OP_OpenWrite, 0, 2, MASTER_NAME},
315 { OP_Rewind, 0, ADDR(9), 0},
316 { OP_String, 0, 0, 0}, /* 2 */
317 { OP_MemStore, 1, 1, 0},
318 { OP_MemLoad, 1, 0, 0}, /* 4 */
319 { OP_Column, 0, 1, 0},
320 { OP_Ne, 0, ADDR(8), 0},
321 { OP_Delete, 0, 0, 0},
322 { OP_Next, 0, ADDR(4), 0}, /* 8 */
323 { OP_Integer, 0, 0, 0}, /* 9 */
324 { OP_SetCookie, 0, 0, 0},
325 { OP_Close, 0, 0, 0},
326 };
327
drhdc379452002-05-15 12:45:43 +0000328 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000329 sqliteBeginWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000330 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000331 base = sqliteVdbeAddOpList(pParse->pVdbe,
drh9adf9ac2002-05-15 11:44:13 +0000332 ArraySize(dropTrigger), dropTrigger);
danielk1977633ed082002-05-17 00:05:58 +0000333 sqliteVdbeChangeP3(pParse->pVdbe, base+2, zName, 0);
drhdc379452002-05-15 12:45:43 +0000334 if( !nested ){
335 sqliteChangeCookie(pParse->db);
336 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000337 sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
drhdc379452002-05-15 12:45:43 +0000338 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000339 sqliteEndWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000340 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000341 }
342
danielk1977633ed082002-05-17 00:05:58 +0000343 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000344}
345
danielk1977633ed082002-05-17 00:05:58 +0000346static int checkColumnOverLap(IdList * pIdList, ExprList * pEList)
danielk1977c3f9bad2002-05-15 08:30:12 +0000347{
348 int i, e;
danielk1977633ed082002-05-17 00:05:58 +0000349 if (!pIdList) return 1;
350 if (!pEList) return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000351
danielk1977633ed082002-05-17 00:05:58 +0000352 for (i = 0; i < pIdList->nId; i++)
353 for (e = 0; e < pEList->nExpr; e++)
354 if (!sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName))
drh9adf9ac2002-05-15 11:44:13 +0000355 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000356
357 return 0;
358}
359
360/* A global variable that is TRUE if we should always set up temp tables for
361 * for triggers, even if there are no triggers to code. This is used to test
362 * how much overhead the triggers algorithm is causing.
363 *
364 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
365 * The pragma is not documented since it is not really part of the interface
366 * to SQLite, just the test procedure.
367*/
368int always_code_trigger_setup = 0;
369
370/*
371 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
372 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
373 * found in the list specified as pTrigger.
374 */
375int sqliteTriggersExist(
danielk1977633ed082002-05-17 00:05:58 +0000376 Parse *pParse,
377 Trigger *pTrigger,
378 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
379 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
380 int foreach, /* one of TK_ROW or TK_STATEMENT */
381 ExprList *pChanges)
danielk1977c3f9bad2002-05-15 08:30:12 +0000382{
danielk1977633ed082002-05-17 00:05:58 +0000383 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000384
danielk1977633ed082002-05-17 00:05:58 +0000385 if( always_code_trigger_setup ){
386 return 1;
387 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000388
danielk1977633ed082002-05-17 00:05:58 +0000389 pTriggerCursor = pTrigger;
390 while( pTriggerCursor ){
391 if( pTriggerCursor->op == op &&
392 pTriggerCursor->tr_tm == tr_tm &&
393 pTriggerCursor->foreach == foreach &&
394 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000395 TriggerStack * ss;
396 ss = pParse->trigStack;
397 while (ss && ss->pTrigger != pTrigger) ss = ss->pNext;
398 if (!ss) return 1;
399 }
danielk1977633ed082002-05-17 00:05:58 +0000400 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000401 }
402
403 return 0;
404}
405
406static int codeTriggerProgram(
danielk1977633ed082002-05-17 00:05:58 +0000407 Parse *pParse,
408 TriggerStep *pStepList,
409 int orconfin
410){
411 TriggerStep * pTriggerStep = pStepList;
412 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000413
danielk1977633ed082002-05-17 00:05:58 +0000414 while( pTriggerStep ){
415 int saveNTab = pParse->nTab;
416 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
417 pParse->trigStack->orconf = orconf;
418 switch( pTriggerStep->op ){
419 case TK_SELECT: {
420 int tmp_tbl = pParse->nTab++;
421 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenTemp, tmp_tbl, 0);
422 sqliteVdbeAddOp(pParse->pVdbe, OP_KeyAsData, tmp_tbl, 1);
423 sqliteSelect(pParse, pTriggerStep->pSelect, SRT_Union,
424 tmp_tbl, 0, 0, 0);
425 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, tmp_tbl, 0);
426 pParse->nTab--;
427 break;
428 }
429 case TK_UPDATE: {
430 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
431 sqliteUpdate(pParse, &pTriggerStep->target,
432 sqliteExprListDup(pTriggerStep->pExprList),
433 sqliteExprDup(pTriggerStep->pWhere), orconf);
434 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
435 break;
436 }
437 case TK_INSERT: {
438 sqliteInsert(pParse, &pTriggerStep->target,
439 sqliteExprListDup(pTriggerStep->pExprList),
440 sqliteSelectDup(pTriggerStep->pSelect),
441 sqliteIdListDup(pTriggerStep->pIdList), orconf);
442 break;
443 }
444 case TK_DELETE: {
445 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
446 sqliteDeleteFrom(pParse, &pTriggerStep->target,
447 sqliteExprDup(pTriggerStep->pWhere));
448 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
449 break;
450 }
451 default:
452 assert(0);
453 }
454 pParse->nTab = saveNTab;
455 pTriggerStep = pTriggerStep->pNext;
456 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000457
danielk1977633ed082002-05-17 00:05:58 +0000458 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000459}
460
danielk1977633ed082002-05-17 00:05:58 +0000461/*
462** This is called to code FOR EACH ROW triggers.
463**
464** When the code that this function generates is executed, the following
465** must be true:
466** 1. NO vdbe cursors must be open.
467** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
468** a temporary vdbe cursor (index newIdx) must be open and pointing at
469** a row containing values to be substituted for new.* expressions in the
470** trigger program(s).
471** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
472** a temporary vdbe cursor (index oldIdx) must be open and pointing at
473** a row containing values to be substituted for old.* expressions in the
474** trigger program(s).
475**
476*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000477int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000478 Parse *pParse, /* Parse context */
479 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
480 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
481 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
482 Table *pTab, /* The table to code triggers from */
483 int newIdx, /* The indice of the "new" row to access */
484 int oldIdx, /* The indice of the "old" row to access */
485 int orconf) /* ON CONFLICT policy */
danielk1977c3f9bad2002-05-15 08:30:12 +0000486{
487 Trigger * pTrigger;
488 TriggerStack * pTriggerStack;
489
danielk1977c3f9bad2002-05-15 08:30:12 +0000490 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
491 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
492
danielk1977633ed082002-05-17 00:05:58 +0000493 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000494
danielk1977633ed082002-05-17 00:05:58 +0000495 pTrigger = pTab->pTrigger;
danielk1977c3f9bad2002-05-15 08:30:12 +0000496 while (pTrigger) {
497 int fire_this = 0;
498
499 /* determine whether we should code this trigger */
500 if (pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
drh9adf9ac2002-05-15 11:44:13 +0000501 pTrigger->foreach == TK_ROW) {
danielk1977c3f9bad2002-05-15 08:30:12 +0000502 fire_this = 1;
503 pTriggerStack = pParse->trigStack;
504 while (pTriggerStack) {
drh9adf9ac2002-05-15 11:44:13 +0000505 if (pTriggerStack->pTrigger == pTrigger) fire_this = 0;
506 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000507 }
508 if (op == TK_UPDATE && pTrigger->pColumns &&
danielk1977633ed082002-05-17 00:05:58 +0000509 !checkColumnOverLap(pTrigger->pColumns, pChanges))
drh9adf9ac2002-05-15 11:44:13 +0000510 fire_this = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000511 }
512
513 if (fire_this) {
514 int endTrigger;
515 IdList dummyTablist;
516 Expr * whenExpr;
517
518 dummyTablist.nId = 0;
519 dummyTablist.a = 0;
520
521 /* Push an entry on to the trigger stack */
522 pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
523 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000524 pTriggerStack->newIdx = newIdx;
525 pTriggerStack->oldIdx = oldIdx;
526 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000527 pTriggerStack->pNext = pParse->trigStack;
528 pParse->trigStack = pTriggerStack;
529
530 /* code the WHEN clause */
531 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
532 whenExpr = sqliteExprDup(pTrigger->pWhen);
533 if (sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr)) {
drh9adf9ac2002-05-15 11:44:13 +0000534 pParse->trigStack = pParse->trigStack->pNext;
535 sqliteFree(pTriggerStack);
536 sqliteExprDelete(whenExpr);
537 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000538 }
539 sqliteExprIfFalse(pParse, whenExpr, endTrigger);
540 sqliteExprDelete(whenExpr);
541
danielk1977633ed082002-05-17 00:05:58 +0000542 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000543
544 /* Pop the entry off the trigger stack */
545 pParse->trigStack = pParse->trigStack->pNext;
546 sqliteFree(pTriggerStack);
547
548 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
549 }
550 pTrigger = pTrigger->pNext;
551 }
552
553 return 0;
554}
555
556/*
danielk1977633ed082002-05-17 00:05:58 +0000557 * This function is called to code ON UPDATE and ON DELETE triggers on
558 * views.
559 *
560 * This function deletes the data pointed at by the pWhere and pChanges
561 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000562 */
danielk1977633ed082002-05-17 00:05:58 +0000563void sqliteViewTriggers(
564 Parse *pParse,
565 Table *pTab, /* The view to code triggers on */
566 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
567 int orconf, /* The ON CONFLICT policy specified as part of the
568 statement causing these triggers */
569 ExprList *pChanges /* If this is an statement causing triggers to fire
570 is an UPDATE, then this list holds the columns
571 to update and the expressions to update them to.
572 See comments for sqliteUpdate(). */
573){
danielk1977c3f9bad2002-05-15 08:30:12 +0000574 int oldIdx = -1;
575 int newIdx = -1;
576 int *aXRef = 0;
577 Vdbe *v;
578 int endOfLoop;
579 int startOfLoop;
580 Select theSelect;
581 Token tblNameToken;
582
583 assert(pTab->pSelect);
584
585 tblNameToken.z = pTab->zName;
586 tblNameToken.n = strlen(pTab->zName);
587
588 theSelect.isDistinct = 0;
589 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
590 theSelect.pSrc = sqliteIdListAppend(0, &tblNameToken);
591 theSelect.pWhere = pWhere; pWhere = 0;
592 theSelect.pGroupBy = 0;
593 theSelect.pHaving = 0;
594 theSelect.pOrderBy = 0;
595 theSelect.op = TK_SELECT; /* ?? */
596 theSelect.pPrior = 0;
597 theSelect.nLimit = -1;
598 theSelect.nOffset = -1;
599 theSelect.zSelect = 0;
600 theSelect.base = 0;
601
602 v = sqliteGetVdbe(pParse);
603 assert(v);
604 sqliteBeginMultiWriteOperation(pParse);
605
606 /* Allocate temp tables */
607 oldIdx = pParse->nTab++;
608 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000609 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000610 newIdx = pParse->nTab++;
611 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
612 }
613
614 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000615 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000616 goto trigger_cleanup;
617 }
618
619 /* loop thru the view snapshot, executing triggers for each row */
620 endOfLoop = sqliteVdbeMakeLabel(v);
621 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
622
623 /* Loop thru the view snapshot, executing triggers for each row */
624 startOfLoop = sqliteVdbeCurrentAddr(v);
625
626 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000627 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000628 int ii, jj;
629
630 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
631 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000632 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000633 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000634 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000635
636 for(ii=0; ii<pChanges->nExpr; ii++){
637 int jj;
638 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
drh9adf9ac2002-05-15 11:44:13 +0000639 pChanges->a[ii].pExpr) )
640 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000641
642 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000643 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000644
645 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000646 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
647 aXRef[jj] = ii;
648 break;
649 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000650 }
651 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000652 sqliteSetString(&pParse->zErrMsg, "no such column: ",
653 pChanges->a[ii].zName, 0);
654 pParse->nErr++;
655 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000656 }
657 }
658
659 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
660
danielk1977633ed082002-05-17 00:05:58 +0000661 for(ii = 0; ii<pTab->nCol; ii++){
662 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000663 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977633ed082002-05-17 00:05:58 +0000664 } else {
drh9adf9ac2002-05-15 11:44:13 +0000665 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000666 }
667 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000668
669 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
670 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
671 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
672
673 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk1977633ed082002-05-17 00:05:58 +0000674 pTab, newIdx, oldIdx, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000675 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk1977633ed082002-05-17 00:05:58 +0000676 pTab, newIdx, oldIdx, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000677 } else {
678 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000679 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000680 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000681 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000682 }
683
684 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
685
686 sqliteVdbeResolveLabel(v, endOfLoop);
687 sqliteEndWriteOperation(pParse);
688
689trigger_cleanup:
690 sqliteFree(aXRef);
691 sqliteExprListDelete(pChanges);
692 sqliteExprDelete(pWhere);
693 sqliteExprListDelete(theSelect.pEList);
694 sqliteIdListDelete(theSelect.pSrc);
695 sqliteExprDelete(theSelect.pWhere);
696 return;
697}