blob: 8ad7027a13fd119547a2ac4aa5107d7339bc7638 [file] [log] [blame]
danielk1977c3f9bad2002-05-15 08:30:12 +00001/*
2 * All copyright on this work is disclaimed by the author.
3 *
4 */
5
6#include "sqliteInt.h"
7/*
8 * This is called by the parser when it sees a CREATE TRIGGER statement
9 */
10void
11sqliteCreateTrigger(
12 Parse * pParse, /* The parse context of the CREATE TRIGGER statement */
13 Token * nm, /* The name of the trigger */
14 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
15 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
16 IdList * cols, /* column list if this is an UPDATE OF trigger */
17 Token * tbl, /* The name of the table/view the trigger applies to */
18 int foreach, /* One of TK_ROW or TK_STATEMENT */
19 Expr * pWhen, /* WHEN clause */
20 TriggerStep * steps, /* The triggered program */
21 char const * cc, int len) /* The string data to make persistent */
22{
23 Trigger * nt;
24 Table * tab;
25 int offset;
26 TriggerStep * ss;
27
28 /* Check that:
29 1. the trigger name does not already exist.
30 2. the table (or view) does exist.
31 */
32 {
33 char * tmp_str = sqliteStrNDup(nm->z, nm->n);
34 if (sqliteHashFind(&(pParse->db->trigHash), tmp_str, nm->n + 1)) {
35 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
36 nm->z, nm->n, " already exists", -1, 0);
37 sqliteFree(tmp_str);
38 pParse->nErr++;
39 goto trigger_cleanup;
40 }
41 sqliteFree(tmp_str);
42 }
43 {
44 char * tmp_str = sqliteStrNDup(tbl->z, tbl->n);
45 tab = sqliteFindTable(pParse->db, tmp_str);
46 sqliteFree(tmp_str);
47 if (!tab) {
48 sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
49 tbl->z, tbl->n, 0);
50 pParse->nErr++;
51 goto trigger_cleanup;
52 }
53 }
54
55 /* Build the Trigger object */
56 nt = (Trigger *)sqliteMalloc(sizeof(Trigger));
57
58 nt->name = sqliteStrNDup(nm->z, nm->n);
59 nt->table = sqliteStrNDup(tbl->z, tbl->n);
60 nt->op = op;
61 nt->tr_tm = tr_tm;
62 nt->pWhen = pWhen;
63 nt->pColumns = cols;
64 nt->foreach = foreach;
65 nt->step_list = steps;
66 nt->isCommit = 0;
67
68 nt->strings = sqliteStrNDup(cc, len);
69 offset = (int)(nt->strings - cc);
70
71 sqliteExprMoveStrings(nt->pWhen, offset);
72
73 ss = nt->step_list;
74 while (ss) {
75 sqliteSelectMoveStrings(ss->pSelect, offset);
76 if (ss->target.z) ss->target.z += offset;
77 sqliteExprMoveStrings(ss->pWhere, offset);
78 sqliteExprListMoveStrings(ss->pExprList, offset);
79
80 ss = ss->pNext;
81 }
82
83 /* if we are not initializing, and this trigger is not on a TEMP table,
84 build the sqlite_master entry */
85 if (!pParse->initFlag && !tab->isTemp) {
86
87 /* Make an entry in the sqlite_master table */
88 sqliteBeginWriteOperation(pParse);
89
90 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenWrite, 0, 2);
91 sqliteVdbeChangeP3(pParse->pVdbe, -1, MASTER_NAME, P3_STATIC);
92 sqliteVdbeAddOp(pParse->pVdbe, OP_NewRecno, 0, 0);
93 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
94 sqliteVdbeChangeP3(pParse->pVdbe, -1, "trigger", P3_STATIC);
95 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
96 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->name, 0);
97 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
98 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->table, 0);
99 sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, 0, 0);
100 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
101 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->strings, 0);
102 sqliteVdbeAddOp(pParse->pVdbe, OP_MakeRecord, 5, 0);
103 sqliteVdbeAddOp(pParse->pVdbe, OP_PutIntKey, 0, 1);
104
105 /* Change the cookie, since the schema is changed */
106 changeCookie(pParse->db);
107 sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, pParse->db->next_cookie, 0);
108 sqliteVdbeAddOp(pParse->pVdbe, OP_SetCookie, 0, 0);
109
110 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, 0, 0);
111
112 sqliteEndWriteOperation(pParse);
113 }
114
115 if (!pParse->explain) {
116 /* Stick it in the hash-table */
117 sqliteHashInsert(&(pParse->db->trigHash), nt->name, nm->n + 1, nt);
118
119 /* Attach it to the table object */
120 nt->pNext = tab->pTrigger;
121 tab->pTrigger = nt;
122 return;
123 } else {
124 sqliteFree(nt->strings);
125 sqliteFree(nt->name);
126 sqliteFree(nt->table);
127 sqliteFree(nt);
128 }
129
130trigger_cleanup:
131
132 sqliteIdListDelete(cols);
133 sqliteExprDelete(pWhen);
134 {
135 TriggerStep * pp;
136 TriggerStep * nn;
137
138 pp = steps;
139 while (pp) {
140 nn = pp->pNext;
141 sqliteExprDelete(pp->pWhere);
142 sqliteExprListDelete(pp->pExprList);
143 sqliteSelectDelete(pp->pSelect);
144 sqliteIdListDelete(pp->pIdList);
145 sqliteFree(pp);
146 pp = nn;
147 }
148 }
149}
150
151 TriggerStep *
152sqliteTriggerSelectStep(Select * s)
153{
154 TriggerStep * tt = sqliteMalloc(sizeof(TriggerStep));
155
156 tt->op = TK_SELECT;
157 tt->pSelect = s;
158 tt->orconf = OE_Default;
159
160 return tt;
161}
162
163TriggerStep *
164sqliteTriggerInsertStep(Token * tbl, IdList * col, ExprList * val, Select * s, int orconf)
165{
166 TriggerStep * tt = sqliteMalloc(sizeof(TriggerStep));
167
168 assert(val == 0 || s == 0);
169 assert(val != 0 || s != 0);
170
171 tt->op = TK_INSERT;
172 tt->pSelect = s;
173 tt->target = *tbl;
174 tt->pIdList = col;
175 tt->pExprList = val;
176 tt->orconf = orconf;
177
178 return tt;
179}
180
181TriggerStep *
182sqliteTriggerUpdateStep(Token * tbl, ExprList * val, Expr * w, int orconf)
183{
184 TriggerStep * tt = sqliteMalloc(sizeof(TriggerStep));
185
186 tt->op = TK_UPDATE;
187 tt->target = *tbl;
188 tt->pExprList = val;
189 tt->pWhere = w;
190 tt->orconf = orconf;
191
192 return tt;
193}
194
195TriggerStep *
196sqliteTriggerDeleteStep(Token * tbl, Expr * w)
197{
198 TriggerStep * tt = sqliteMalloc(sizeof(TriggerStep));
199
200 tt->op = TK_DELETE;
201 tt->target = *tbl;
202 tt->pWhere = w;
203 tt->orconf = OE_Default;
204
205 return tt;
206}
207
208
209/* This does a recursive delete of the trigger structure */
210void sqliteDeleteTrigger(Trigger * tt)
211{
212 TriggerStep * ts, * tc;
213 ts = tt->step_list;
214
215 while (ts) {
216 tc = ts;
217 ts = ts->pNext;
218
219 sqliteExprDelete(tc->pWhere);
220 sqliteExprListDelete(tc->pExprList);
221 sqliteSelectDelete(tc->pSelect);
222 sqliteIdListDelete(tc->pIdList);
223
224 sqliteFree(tc);
225 }
226
227 sqliteFree(tt->name);
228 sqliteFree(tt->table);
229 sqliteExprDelete(tt->pWhen);
230 sqliteIdListDelete(tt->pColumns);
231 sqliteFree(tt->strings);
232 sqliteFree(tt);
233}
234
235/*
236 * "nested" is true if this is begin called as the result of a DROP TABLE
237 */
238void sqliteDropTrigger(Parse *pParse, Token * trigname, int nested)
239{
240 char * tmp_name;
241 Trigger * trig;
242 Table * tbl;
243
244 tmp_name = sqliteStrNDup(trigname->z, trigname->n);
245
246 /* ensure that the trigger being dropped exists */
247 trig = sqliteHashFind(&(pParse->db->trigHash), tmp_name, trigname->n + 1);
248 if (!trig) {
249 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
250 tmp_name, -1, 0);
251 sqliteFree(tmp_name);
252 return;
253 }
254
255 /*
256 * If this is not an "explain", do the following:
257 * 1. Remove the trigger from its associated table structure
258 * 2. Move the trigger from the trigHash hash to trigDrop
259 */
260 if (!pParse->explain) {
261 /* 1 */
262 tbl = sqliteFindTable(pParse->db, trig->table);
263 assert(tbl);
264 if (tbl->pTrigger == trig)
265 tbl->pTrigger = trig->pNext;
266 else {
267 Trigger * cc = tbl->pTrigger;
268 while (cc) {
269 if (cc->pNext == trig) {
270 cc->pNext = cc->pNext->pNext;
271 break;
272 }
273 cc = cc->pNext;
274 }
275 assert(cc);
276 }
277
278 /* 2 */
279 sqliteHashInsert(&(pParse->db->trigHash), tmp_name,
280 trigname->n + 1, NULL);
281 sqliteHashInsert(&(pParse->db->trigDrop), trig->name,
282 trigname->n + 1, trig);
283 }
284
285 /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
286 * database record of the trigger */
287 if (!tbl->isTemp) {
288 int base;
289 static VdbeOp dropTrigger[] = {
290 { OP_OpenWrite, 0, 2, MASTER_NAME},
291 { OP_Rewind, 0, ADDR(9), 0},
292 { OP_String, 0, 0, 0}, /* 2 */
293 { OP_MemStore, 1, 1, 0},
294 { OP_MemLoad, 1, 0, 0}, /* 4 */
295 { OP_Column, 0, 1, 0},
296 { OP_Ne, 0, ADDR(8), 0},
297 { OP_Delete, 0, 0, 0},
298 { OP_Next, 0, ADDR(4), 0}, /* 8 */
299 { OP_Integer, 0, 0, 0}, /* 9 */
300 { OP_SetCookie, 0, 0, 0},
301 { OP_Close, 0, 0, 0},
302 };
303
304 if (!nested)
305 sqliteBeginWriteOperation(pParse);
306
307 base = sqliteVdbeAddOpList(pParse->pVdbe,
308 ArraySize(dropTrigger), dropTrigger);
309 sqliteVdbeChangeP3(pParse->pVdbe, base+2, tmp_name, 0);
310
311 if (!nested)
312 changeCookie(pParse->db);
313
314 sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
315
316 if (!nested)
317 sqliteEndWriteOperation(pParse);
318 }
319
320 sqliteFree(tmp_name);
321}
322
323static int checkColumnOverLap(IdList * ii, ExprList * ee)
324{
325 int i, e;
326 if (!ii) return 1;
327 if (!ee) return 1;
328
329 for (i = 0; i < ii->nId; i++)
330 for (e = 0; e < ee->nExpr; e++)
331 if (!sqliteStrICmp(ii->a[i].zName, ee->a[e].zName))
332 return 1;
333
334 return 0;
335}
336
337/* A global variable that is TRUE if we should always set up temp tables for
338 * for triggers, even if there are no triggers to code. This is used to test
339 * how much overhead the triggers algorithm is causing.
340 *
341 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
342 * The pragma is not documented since it is not really part of the interface
343 * to SQLite, just the test procedure.
344*/
345int always_code_trigger_setup = 0;
346
347/*
348 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
349 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
350 * found in the list specified as pTrigger.
351 */
352int sqliteTriggersExist(
353 Parse * pParse,
354 Trigger * pTrigger,
355 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
356 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
357 int foreach, /* one of TK_ROW or TK_STATEMENT */
358 ExprList * pChanges)
359{
360 Trigger * tt;
361
362 if (always_code_trigger_setup) return 1;
363
364 tt = pTrigger;
365 while (tt) {
366 if (tt->op == op && tt->tr_tm == tr_tm && tt->foreach == foreach &&
367 checkColumnOverLap(tt->pColumns, pChanges)) {
368 TriggerStack * ss;
369 ss = pParse->trigStack;
370 while (ss && ss->pTrigger != pTrigger) ss = ss->pNext;
371 if (!ss) return 1;
372 }
373 tt = tt->pNext;
374 }
375
376 return 0;
377}
378
379static int codeTriggerProgram(
380 Parse *pParse,
381 TriggerStep * program,
382 int onError)
383{
384 TriggerStep * step = program;
385 int orconf;
386
387 while (step) {
388 int saveNTab = pParse->nTab;
389 orconf = (onError == OE_Default)?step->orconf:onError;
390 pParse->trigStack->orconf = orconf;
391 switch(step->op) {
392 case TK_SELECT: {
393 int tmp_tbl = pParse->nTab++;
394 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenTemp, tmp_tbl, 0);
395 sqliteVdbeAddOp(pParse->pVdbe, OP_KeyAsData, tmp_tbl, 1);
396 sqliteSelect(pParse, step->pSelect,
397 SRT_Union, tmp_tbl, 0, 0, 0);
398 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, tmp_tbl, 0);
399 pParse->nTab--;
400 break;
401 }
402 case TK_UPDATE: {
403 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
404 sqliteUpdate(pParse, &step->target,
405 sqliteExprListDup(step->pExprList),
406 sqliteExprDup(step->pWhere), orconf);
407 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
408 break;
409 }
410 case TK_INSERT: {
411 sqliteInsert(pParse, &step->target,
412 sqliteExprListDup(step->pExprList),
413 sqliteSelectDup(step->pSelect),
414 sqliteIdListDup(step->pIdList), orconf);
415 break;
416 }
417 case TK_DELETE: {
418 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
419 sqliteDeleteFrom(pParse, &step->target,
420 sqliteExprDup(step->pWhere)
421 );
422 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
423 break;
424 }
425 default:
426 assert(0);
427 }
428 pParse->nTab = saveNTab;
429 step = step->pNext;
430 }
431
432 return 0;
433}
434
435int sqliteCodeRowTrigger(
436 Parse * pParse, /* Parse context */
437 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
438 ExprList * changes, /* Changes list for any UPDATE OF triggers */
439 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
440 Table * tbl, /* The table to code triggers from */
441 int newTable, /* The indice of the "new" row to access */
442 int oldTable, /* The indice of the "old" row to access */
443 int onError) /* ON CONFLICT policy */
444{
445 Trigger * pTrigger;
446 TriggerStack * pTriggerStack;
447
448
449 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
450 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
451
452 assert(newTable != -1 || oldTable != -1);
453
454 pTrigger = tbl->pTrigger;
455 while (pTrigger) {
456 int fire_this = 0;
457
458 /* determine whether we should code this trigger */
459 if (pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
460 pTrigger->foreach == TK_ROW) {
461 fire_this = 1;
462 pTriggerStack = pParse->trigStack;
463 while (pTriggerStack) {
464 if (pTriggerStack->pTrigger == pTrigger) fire_this = 0;
465 pTriggerStack = pTriggerStack->pNext;
466 }
467 if (op == TK_UPDATE && pTrigger->pColumns &&
468 !checkColumnOverLap(pTrigger->pColumns, changes))
469 fire_this = 0;
470 }
471
472 if (fire_this) {
473 int endTrigger;
474 IdList dummyTablist;
475 Expr * whenExpr;
476
477 dummyTablist.nId = 0;
478 dummyTablist.a = 0;
479
480 /* Push an entry on to the trigger stack */
481 pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
482 pTriggerStack->pTrigger = pTrigger;
483 pTriggerStack->newIdx = newTable;
484 pTriggerStack->oldIdx = oldTable;
485 pTriggerStack->pTab = tbl;
486 pTriggerStack->pNext = pParse->trigStack;
487 pParse->trigStack = pTriggerStack;
488
489 /* code the WHEN clause */
490 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
491 whenExpr = sqliteExprDup(pTrigger->pWhen);
492 if (sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr)) {
493 pParse->trigStack = pParse->trigStack->pNext;
494 sqliteFree(pTriggerStack);
495 sqliteExprDelete(whenExpr);
496 return 1;
497 }
498 sqliteExprIfFalse(pParse, whenExpr, endTrigger);
499 sqliteExprDelete(whenExpr);
500
501 codeTriggerProgram(pParse, pTrigger->step_list, onError);
502
503 /* Pop the entry off the trigger stack */
504 pParse->trigStack = pParse->trigStack->pNext;
505 sqliteFree(pTriggerStack);
506
507 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
508 }
509 pTrigger = pTrigger->pNext;
510 }
511
512 return 0;
513}
514
515/*
516 * Handle UPDATE and DELETE triggers on views
517 */
518void sqliteViewTriggers(Parse *pParse, Table *pTab,
519 Expr * pWhere, int onError, ExprList * pChanges)
520{
521 int oldIdx = -1;
522 int newIdx = -1;
523 int *aXRef = 0;
524 Vdbe *v;
525 int endOfLoop;
526 int startOfLoop;
527 Select theSelect;
528 Token tblNameToken;
529
530 assert(pTab->pSelect);
531
532 tblNameToken.z = pTab->zName;
533 tblNameToken.n = strlen(pTab->zName);
534
535 theSelect.isDistinct = 0;
536 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
537 theSelect.pSrc = sqliteIdListAppend(0, &tblNameToken);
538 theSelect.pWhere = pWhere; pWhere = 0;
539 theSelect.pGroupBy = 0;
540 theSelect.pHaving = 0;
541 theSelect.pOrderBy = 0;
542 theSelect.op = TK_SELECT; /* ?? */
543 theSelect.pPrior = 0;
544 theSelect.nLimit = -1;
545 theSelect.nOffset = -1;
546 theSelect.zSelect = 0;
547 theSelect.base = 0;
548
549 v = sqliteGetVdbe(pParse);
550 assert(v);
551 sqliteBeginMultiWriteOperation(pParse);
552
553 /* Allocate temp tables */
554 oldIdx = pParse->nTab++;
555 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
556 if (pChanges) {
557 newIdx = pParse->nTab++;
558 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
559 }
560
561 /* Snapshot the view */
562 if (sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0)) {
563 goto trigger_cleanup;
564 }
565
566 /* loop thru the view snapshot, executing triggers for each row */
567 endOfLoop = sqliteVdbeMakeLabel(v);
568 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
569
570 /* Loop thru the view snapshot, executing triggers for each row */
571 startOfLoop = sqliteVdbeCurrentAddr(v);
572
573 /* Build the updated row if required */
574 if (pChanges) {
575 int ii, jj;
576
577 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
578 if( aXRef==0 ) goto trigger_cleanup;
579 for (ii = 0; ii < pTab->nCol; ii++)
580 aXRef[ii] = -1;
581
582 for(ii=0; ii<pChanges->nExpr; ii++){
583 int jj;
584 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
585 pChanges->a[ii].pExpr) )
586 goto trigger_cleanup;
587
588 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
589 goto trigger_cleanup;
590
591 for(jj=0; jj<pTab->nCol; jj++){
592 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
593 aXRef[jj] = ii;
594 break;
595 }
596 }
597 if( jj>=pTab->nCol ){
598 sqliteSetString(&pParse->zErrMsg, "no such column: ",
599 pChanges->a[ii].zName, 0);
600 pParse->nErr++;
601 goto trigger_cleanup;
602 }
603 }
604
605 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
606
607 for (ii = 0; ii < pTab->nCol; ii++)
608 if( aXRef[ii] < 0 )
609 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
610 else
611 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
612
613 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
614 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
615 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
616
617 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
618 pTab, newIdx, oldIdx, onError);
619 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
620 pTab, newIdx, oldIdx, onError);
621 } else {
622 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
623 onError);
624 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
625 onError);
626 }
627
628 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
629
630 sqliteVdbeResolveLabel(v, endOfLoop);
631 sqliteEndWriteOperation(pParse);
632
633trigger_cleanup:
634 sqliteFree(aXRef);
635 sqliteExprListDelete(pChanges);
636 sqliteExprDelete(pWhere);
637 sqliteExprListDelete(theSelect.pEList);
638 sqliteIdListDelete(theSelect.pSrc);
639 sqliteExprDelete(theSelect.pWhere);
640 return;
641}
642
643