blob: 5864b7d8c7ceb106f81570c09cfaad5459d94727 [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 }
drh1873cd52002-05-23 00:30:31 +000063 if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
64 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
65 "table: " MASTER_NAME, 0);
66 pParse->nErr++;
67 goto trigger_cleanup;
68 }
danielk1977c3f9bad2002-05-15 08:30:12 +000069 }
70
71 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +000072 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
danielk1977633ed082002-05-17 00:05:58 +000073 nt->name = sqliteStrNDup(pName->z, pName->n);
74 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +000075 nt->op = op;
76 nt->tr_tm = tr_tm;
77 nt->pWhen = pWhen;
danielk1977633ed082002-05-17 00:05:58 +000078 nt->pColumns = pColumns;
danielk1977c3f9bad2002-05-15 08:30:12 +000079 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +000080 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +000081 nt->isCommit = 0;
82
danielk1977633ed082002-05-17 00:05:58 +000083 nt->strings = sqliteStrNDup(zData, zDataLen);
84 offset = (int)(nt->strings - zData);
danielk1977c3f9bad2002-05-15 08:30:12 +000085
86 sqliteExprMoveStrings(nt->pWhen, offset);
87
88 ss = nt->step_list;
danielk1977f29ce552002-05-19 23:43:12 +000089 while( ss ){
danielk1977c3f9bad2002-05-15 08:30:12 +000090 sqliteSelectMoveStrings(ss->pSelect, offset);
danielk1977f29ce552002-05-19 23:43:12 +000091 if( ss->target.z ){
92 ss->target.z += offset;
93 }
danielk1977c3f9bad2002-05-15 08:30:12 +000094 sqliteExprMoveStrings(ss->pWhere, offset);
95 sqliteExprListMoveStrings(ss->pExprList, offset);
96
97 ss = ss->pNext;
98 }
99
100 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000101 ** build the sqlite_master entry
102 */
103 if( !pParse->initFlag && !tab->isTemp ){
drhc977f7f2002-05-21 11:38:11 +0000104 static VdbeOp insertTrig[] = {
105 { OP_OpenWrite, 0, 2, MASTER_NAME},
106 { OP_NewRecno, 0, 0, 0 },
107 { OP_String, 0, 0, "trigger" },
108 { OP_String, 0, 0, 0 }, /* 3: trigger name */
109 { OP_String, 0, 0, 0 }, /* 4: table name */
110 { OP_Integer, 0, 0, 0 },
111 { OP_String, 0, 0, 0 }, /* 6: SQL */
112 { OP_MakeRecord, 5, 0, 0 },
113 { OP_PutIntKey, 0, 0, 0 },
114 { OP_Integer, 0, 0, 0 }, /* 9: Next cookie */
115 { OP_SetCookie, 0, 0, 0 },
116 { OP_Close, 0, 0, 0 },
117 };
118 int addr;
119 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000120
121 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000122 v = sqliteGetVdbe(pParse);
123 sqliteBeginWriteOperation(pParse, 0);
124 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
125 sqliteVdbeChangeP3(v, addr+3, nt->name, 0);
126 sqliteVdbeChangeP3(v, addr+4, nt->table, 0);
127 sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);
drhdc379452002-05-15 12:45:43 +0000128 sqliteChangeCookie(pParse->db);
drhc977f7f2002-05-21 11:38:11 +0000129 sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);
danielk1977c3f9bad2002-05-15 08:30:12 +0000130 sqliteEndWriteOperation(pParse);
131 }
132
danielk1977633ed082002-05-17 00:05:58 +0000133 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000134 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000135 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000136
137 /* Attach it to the table object */
138 nt->pNext = tab->pTrigger;
139 tab->pTrigger = nt;
140 return;
danielk1977f29ce552002-05-19 23:43:12 +0000141 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000142 sqliteFree(nt->strings);
143 sqliteFree(nt->name);
144 sqliteFree(nt->table);
145 sqliteFree(nt);
146 }
147
148trigger_cleanup:
149
danielk1977633ed082002-05-17 00:05:58 +0000150 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000151 sqliteExprDelete(pWhen);
152 {
153 TriggerStep * pp;
154 TriggerStep * nn;
155
danielk1977633ed082002-05-17 00:05:58 +0000156 pp = pStepList;
danielk1977f29ce552002-05-19 23:43:12 +0000157 while( pp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000158 nn = pp->pNext;
159 sqliteExprDelete(pp->pWhere);
160 sqliteExprListDelete(pp->pExprList);
161 sqliteSelectDelete(pp->pSelect);
162 sqliteIdListDelete(pp->pIdList);
163 sqliteFree(pp);
164 pp = nn;
165 }
166 }
167}
168
drhc977f7f2002-05-21 11:38:11 +0000169/*
170** Turn a SELECT statement (that the pSelect parameter points to) into
171** a trigger step. Return a pointer to a TriggerStep structure.
172**
173** The parser calls this routine when it finds a SELECT statement in
174** body of a TRIGGER.
175*/
176TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000177 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000178
danielk1977633ed082002-05-17 00:05:58 +0000179 pTriggerStep->op = TK_SELECT;
180 pTriggerStep->pSelect = pSelect;
181 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000182
danielk1977633ed082002-05-17 00:05:58 +0000183 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000184}
185
drhc977f7f2002-05-21 11:38:11 +0000186/*
187** Build a trigger step out of an INSERT statement. Return a pointer
188** to the new trigger step.
189**
190** The parser calls this routine when it sees an INSERT inside the
191** body of a trigger.
192*/
danielk1977633ed082002-05-17 00:05:58 +0000193TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000194 Token *pTableName, /* Name of the table into which we insert */
195 IdList *pColumn, /* List of columns in pTableName to insert into */
196 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
197 Select *pSelect, /* A SELECT statement that supplies values */
198 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000199){
200 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000201
danielk1977633ed082002-05-17 00:05:58 +0000202 assert(pEList == 0 || pSelect == 0);
203 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000204
danielk1977633ed082002-05-17 00:05:58 +0000205 pTriggerStep->op = TK_INSERT;
206 pTriggerStep->pSelect = pSelect;
207 pTriggerStep->target = *pTableName;
208 pTriggerStep->pIdList = pColumn;
209 pTriggerStep->pExprList = pEList;
210 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000211
danielk1977633ed082002-05-17 00:05:58 +0000212 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000213}
214
drhc977f7f2002-05-21 11:38:11 +0000215/*
216** Construct a trigger step that implements an UPDATE statement and return
217** a pointer to that trigger step. The parser calls this routine when it
218** sees an UPDATE statement inside the body of a CREATE TRIGGER.
219*/
danielk1977633ed082002-05-17 00:05:58 +0000220TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000221 Token *pTableName, /* Name of the table to be updated */
222 ExprList *pEList, /* The SET clause: list of column and new values */
223 Expr *pWhere, /* The WHERE clause */
224 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
225){
danielk1977633ed082002-05-17 00:05:58 +0000226 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000227
danielk1977633ed082002-05-17 00:05:58 +0000228 pTriggerStep->op = TK_UPDATE;
229 pTriggerStep->target = *pTableName;
230 pTriggerStep->pExprList = pEList;
231 pTriggerStep->pWhere = pWhere;
232 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000233
danielk1977633ed082002-05-17 00:05:58 +0000234 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000235}
236
drhc977f7f2002-05-21 11:38:11 +0000237/*
238** Construct a trigger step that implements a DELETE statement and return
239** a pointer to that trigger step. The parser calls this routine when it
240** sees a DELETE statement inside the body of a CREATE TRIGGER.
241*/
242TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
danielk1977633ed082002-05-17 00:05:58 +0000243 TriggerStep * pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000244
danielk1977633ed082002-05-17 00:05:58 +0000245 pTriggerStep->op = TK_DELETE;
246 pTriggerStep->target = *pTableName;
247 pTriggerStep->pWhere = pWhere;
248 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000249
danielk1977633ed082002-05-17 00:05:58 +0000250 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000251}
252
danielk1977633ed082002-05-17 00:05:58 +0000253/*
254** Recursively delete a Trigger structure
255*/
drh1d1f3052002-05-21 13:18:25 +0000256void sqliteDeleteTrigger(Trigger *pTrigger){
danielk1977633ed082002-05-17 00:05:58 +0000257 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000258
danielk1977633ed082002-05-17 00:05:58 +0000259 pTriggerStep = pTrigger->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000260 while( pTriggerStep ){
danielk1977633ed082002-05-17 00:05:58 +0000261 TriggerStep * pTmp = pTriggerStep;
262 pTriggerStep = pTriggerStep->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000263
danielk1977633ed082002-05-17 00:05:58 +0000264 sqliteExprDelete(pTmp->pWhere);
265 sqliteExprListDelete(pTmp->pExprList);
266 sqliteSelectDelete(pTmp->pSelect);
267 sqliteIdListDelete(pTmp->pIdList);
danielk1977c3f9bad2002-05-15 08:30:12 +0000268
danielk1977633ed082002-05-17 00:05:58 +0000269 sqliteFree(pTmp);
danielk1977c3f9bad2002-05-15 08:30:12 +0000270 }
271
danielk1977633ed082002-05-17 00:05:58 +0000272 sqliteFree(pTrigger->name);
273 sqliteFree(pTrigger->table);
274 sqliteExprDelete(pTrigger->pWhen);
275 sqliteIdListDelete(pTrigger->pColumns);
276 sqliteFree(pTrigger->strings);
277 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000278}
279
280/*
danielk1977633ed082002-05-17 00:05:58 +0000281 * This function is called to drop a trigger from the database schema.
282 *
283 * This may be called directly from the parser, or from within
284 * sqliteDropTable(). In the latter case the "nested" argument is true.
285 *
286 * Note that this function does not delete the trigger entirely. Instead it
287 * removes it from the internal schema and places it in the trigDrop hash
288 * table. This is so that the trigger can be restored into the database schema
289 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000290 */
danielk1977633ed082002-05-17 00:05:58 +0000291void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
danielk1977c3f9bad2002-05-15 08:30:12 +0000292{
danielk1977633ed082002-05-17 00:05:58 +0000293 char *zName;
294 Trigger *pTrigger;
295 Table *pTable;
danielk1977c3f9bad2002-05-15 08:30:12 +0000296
danielk1977633ed082002-05-17 00:05:58 +0000297 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000298
299 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000300 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
301 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000302 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000303 zName, -1, 0);
304 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000305 return;
306 }
307
308 /*
309 * If this is not an "explain", do the following:
310 * 1. Remove the trigger from its associated table structure
311 * 2. Move the trigger from the trigHash hash to trigDrop
312 */
danielk1977633ed082002-05-17 00:05:58 +0000313 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000314 /* 1 */
danielk1977633ed082002-05-17 00:05:58 +0000315 pTable = sqliteFindTable(pParse->db, pTrigger->table);
316 assert(pTable);
317 if( pTable->pTrigger == pTrigger ){
318 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000319 }else{
danielk1977633ed082002-05-17 00:05:58 +0000320 Trigger *cc = pTable->pTrigger;
321 while( cc ){
322 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000323 cc->pNext = cc->pNext->pNext;
324 break;
325 }
326 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000327 }
328 assert(cc);
329 }
330
331 /* 2 */
danielk1977633ed082002-05-17 00:05:58 +0000332 sqliteHashInsert(&(pParse->db->trigHash), zName,
333 pName->n + 1, NULL);
334 sqliteHashInsert(&(pParse->db->trigDrop), pTrigger->name,
335 pName->n + 1, pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000336 }
337
338 /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
339 * database record of the trigger */
danielk1977633ed082002-05-17 00:05:58 +0000340 if( !pTable->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000341 int base;
342 static VdbeOp dropTrigger[] = {
343 { OP_OpenWrite, 0, 2, MASTER_NAME},
344 { OP_Rewind, 0, ADDR(9), 0},
345 { OP_String, 0, 0, 0}, /* 2 */
346 { OP_MemStore, 1, 1, 0},
347 { OP_MemLoad, 1, 0, 0}, /* 4 */
348 { OP_Column, 0, 1, 0},
349 { OP_Ne, 0, ADDR(8), 0},
350 { OP_Delete, 0, 0, 0},
351 { OP_Next, 0, ADDR(4), 0}, /* 8 */
352 { OP_Integer, 0, 0, 0}, /* 9 */
353 { OP_SetCookie, 0, 0, 0},
354 { OP_Close, 0, 0, 0},
355 };
356
drhdc379452002-05-15 12:45:43 +0000357 if( !nested ){
drhc977f7f2002-05-21 11:38:11 +0000358 sqliteBeginWriteOperation(pParse, 0);
drhdc379452002-05-15 12:45:43 +0000359 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000360 base = sqliteVdbeAddOpList(pParse->pVdbe,
drh9adf9ac2002-05-15 11:44:13 +0000361 ArraySize(dropTrigger), dropTrigger);
danielk1977633ed082002-05-17 00:05:58 +0000362 sqliteVdbeChangeP3(pParse->pVdbe, base+2, zName, 0);
drhdc379452002-05-15 12:45:43 +0000363 if( !nested ){
364 sqliteChangeCookie(pParse->db);
365 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000366 sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
drhdc379452002-05-15 12:45:43 +0000367 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000368 sqliteEndWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000369 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000370 }
371
danielk1977633ed082002-05-17 00:05:58 +0000372 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000373}
374
drhc977f7f2002-05-21 11:38:11 +0000375/*
376** pEList is the SET clause of an UPDATE statement. Each entry
377** in pEList is of the format <id>=<expr>. If any of the entries
378** in pEList have an <id> which matches an identifier in pIdList,
379** then return TRUE. If pIdList==NULL, then it is considered a
380** wildcard that matches anything. Likewise if pEList==NULL then
381** it matches anything so always return true. Return false only
382** if there is no match.
383*/
384static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
danielk1977c3f9bad2002-05-15 08:30:12 +0000385 int i, e;
danielk1977f29ce552002-05-19 23:43:12 +0000386 if( !pIdList )return 1;
387 if( !pEList )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000388
danielk1977f29ce552002-05-19 23:43:12 +0000389 for(i = 0; i < pIdList->nId; i++){
390 for(e = 0; e < pEList->nExpr; e++){
391 if( !sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName) ){
drh9adf9ac2002-05-15 11:44:13 +0000392 return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000393 }
394 }
395 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000396
397 return 0;
398}
399
400/* A global variable that is TRUE if we should always set up temp tables for
401 * for triggers, even if there are no triggers to code. This is used to test
402 * how much overhead the triggers algorithm is causing.
403 *
404 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
405 * The pragma is not documented since it is not really part of the interface
406 * to SQLite, just the test procedure.
407*/
408int always_code_trigger_setup = 0;
409
410/*
411 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
412 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
413 * found in the list specified as pTrigger.
414 */
415int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000416 Parse *pParse, /* Used to check for recursive triggers */
417 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000418 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
419 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
420 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000421 ExprList *pChanges /* Columns that change in an UPDATE statement */
422){
danielk1977633ed082002-05-17 00:05:58 +0000423 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000424
danielk1977633ed082002-05-17 00:05:58 +0000425 if( always_code_trigger_setup ){
426 return 1;
427 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000428
danielk1977633ed082002-05-17 00:05:58 +0000429 pTriggerCursor = pTrigger;
430 while( pTriggerCursor ){
431 if( pTriggerCursor->op == op &&
432 pTriggerCursor->tr_tm == tr_tm &&
433 pTriggerCursor->foreach == foreach &&
434 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000435 TriggerStack * ss;
436 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000437 while( ss && ss->pTrigger != pTrigger ){
438 ss = ss->pNext;
439 }
440 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000441 }
danielk1977633ed082002-05-17 00:05:58 +0000442 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000443 }
444
445 return 0;
446}
447
drhc977f7f2002-05-21 11:38:11 +0000448/*
449** Generate VDBE code for zero or more statements inside the body of a
450** trigger.
451*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000452static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000453 Parse *pParse, /* The parser context */
454 TriggerStep *pStepList, /* List of statements inside the trigger body */
455 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000456){
457 TriggerStep * pTriggerStep = pStepList;
458 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000459
danielk1977633ed082002-05-17 00:05:58 +0000460 while( pTriggerStep ){
461 int saveNTab = pParse->nTab;
462 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
463 pParse->trigStack->orconf = orconf;
464 switch( pTriggerStep->op ){
465 case TK_SELECT: {
466 int tmp_tbl = pParse->nTab++;
467 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenTemp, tmp_tbl, 0);
468 sqliteVdbeAddOp(pParse->pVdbe, OP_KeyAsData, tmp_tbl, 1);
469 sqliteSelect(pParse, pTriggerStep->pSelect, SRT_Union,
470 tmp_tbl, 0, 0, 0);
471 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, tmp_tbl, 0);
472 pParse->nTab--;
473 break;
474 }
475 case TK_UPDATE: {
476 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
477 sqliteUpdate(pParse, &pTriggerStep->target,
478 sqliteExprListDup(pTriggerStep->pExprList),
479 sqliteExprDup(pTriggerStep->pWhere), orconf);
480 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
481 break;
482 }
483 case TK_INSERT: {
484 sqliteInsert(pParse, &pTriggerStep->target,
485 sqliteExprListDup(pTriggerStep->pExprList),
486 sqliteSelectDup(pTriggerStep->pSelect),
487 sqliteIdListDup(pTriggerStep->pIdList), orconf);
488 break;
489 }
490 case TK_DELETE: {
491 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
492 sqliteDeleteFrom(pParse, &pTriggerStep->target,
493 sqliteExprDup(pTriggerStep->pWhere));
494 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
495 break;
496 }
497 default:
498 assert(0);
499 }
500 pParse->nTab = saveNTab;
501 pTriggerStep = pTriggerStep->pNext;
502 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000503
danielk1977633ed082002-05-17 00:05:58 +0000504 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000505}
506
danielk1977633ed082002-05-17 00:05:58 +0000507/*
508** This is called to code FOR EACH ROW triggers.
509**
510** When the code that this function generates is executed, the following
511** must be true:
drhc977f7f2002-05-21 11:38:11 +0000512**
513** 1. No cursors may be open in the main database. (But newIdx and oldIdx
514** can be indices of cursors in temporary tables. See below.)
515**
danielk1977633ed082002-05-17 00:05:58 +0000516** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
517** a temporary vdbe cursor (index newIdx) must be open and pointing at
518** a row containing values to be substituted for new.* expressions in the
519** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000520**
danielk1977633ed082002-05-17 00:05:58 +0000521** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
522** a temporary vdbe cursor (index oldIdx) must be open and pointing at
523** a row containing values to be substituted for old.* expressions in the
524** trigger program(s).
525**
526*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000527int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000528 Parse *pParse, /* Parse context */
529 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
530 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
531 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
532 Table *pTab, /* The table to code triggers from */
533 int newIdx, /* The indice of the "new" row to access */
534 int oldIdx, /* The indice of the "old" row to access */
drhc977f7f2002-05-21 11:38:11 +0000535 int orconf /* ON CONFLICT policy */
536){
danielk1977c3f9bad2002-05-15 08:30:12 +0000537 Trigger * pTrigger;
538 TriggerStack * pTriggerStack;
539
danielk1977c3f9bad2002-05-15 08:30:12 +0000540 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
541 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
542
danielk1977633ed082002-05-17 00:05:58 +0000543 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000544
danielk1977633ed082002-05-17 00:05:58 +0000545 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000546 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000547 int fire_this = 0;
548
549 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000550 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
551 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000552 fire_this = 1;
553 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000554 while( pTriggerStack ){
555 if( pTriggerStack->pTrigger == pTrigger ){
556 fire_this = 0;
557 }
drh9adf9ac2002-05-15 11:44:13 +0000558 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000559 }
danielk1977f29ce552002-05-19 23:43:12 +0000560 if( op == TK_UPDATE && pTrigger->pColumns &&
561 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000562 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000563 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000564 }
565
danielk1977f29ce552002-05-19 23:43:12 +0000566 if( fire_this ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000567 int endTrigger;
568 IdList dummyTablist;
569 Expr * whenExpr;
570
571 dummyTablist.nId = 0;
572 dummyTablist.a = 0;
573
574 /* Push an entry on to the trigger stack */
575 pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
576 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000577 pTriggerStack->newIdx = newIdx;
578 pTriggerStack->oldIdx = oldIdx;
579 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000580 pTriggerStack->pNext = pParse->trigStack;
581 pParse->trigStack = pTriggerStack;
582
583 /* code the WHEN clause */
584 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
585 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000586 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000587 pParse->trigStack = pParse->trigStack->pNext;
588 sqliteFree(pTriggerStack);
589 sqliteExprDelete(whenExpr);
590 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000591 }
592 sqliteExprIfFalse(pParse, whenExpr, endTrigger);
593 sqliteExprDelete(whenExpr);
594
danielk1977633ed082002-05-17 00:05:58 +0000595 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000596
597 /* Pop the entry off the trigger stack */
598 pParse->trigStack = pParse->trigStack->pNext;
599 sqliteFree(pTriggerStack);
600
601 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
602 }
603 pTrigger = pTrigger->pNext;
604 }
605
606 return 0;
607}
608
609/*
danielk1977633ed082002-05-17 00:05:58 +0000610 * This function is called to code ON UPDATE and ON DELETE triggers on
611 * views.
612 *
613 * This function deletes the data pointed at by the pWhere and pChanges
614 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000615 */
danielk1977633ed082002-05-17 00:05:58 +0000616void sqliteViewTriggers(
617 Parse *pParse,
618 Table *pTab, /* The view to code triggers on */
619 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
620 int orconf, /* The ON CONFLICT policy specified as part of the
621 statement causing these triggers */
622 ExprList *pChanges /* If this is an statement causing triggers to fire
623 is an UPDATE, then this list holds the columns
624 to update and the expressions to update them to.
625 See comments for sqliteUpdate(). */
626){
danielk1977c3f9bad2002-05-15 08:30:12 +0000627 int oldIdx = -1;
628 int newIdx = -1;
629 int *aXRef = 0;
630 Vdbe *v;
631 int endOfLoop;
632 int startOfLoop;
633 Select theSelect;
634 Token tblNameToken;
635
636 assert(pTab->pSelect);
637
638 tblNameToken.z = pTab->zName;
639 tblNameToken.n = strlen(pTab->zName);
640
641 theSelect.isDistinct = 0;
642 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
643 theSelect.pSrc = sqliteIdListAppend(0, &tblNameToken);
644 theSelect.pWhere = pWhere; pWhere = 0;
645 theSelect.pGroupBy = 0;
646 theSelect.pHaving = 0;
647 theSelect.pOrderBy = 0;
648 theSelect.op = TK_SELECT; /* ?? */
649 theSelect.pPrior = 0;
650 theSelect.nLimit = -1;
651 theSelect.nOffset = -1;
652 theSelect.zSelect = 0;
653 theSelect.base = 0;
654
655 v = sqliteGetVdbe(pParse);
656 assert(v);
drhc977f7f2002-05-21 11:38:11 +0000657 sqliteBeginWriteOperation(pParse, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000658
659 /* Allocate temp tables */
660 oldIdx = pParse->nTab++;
661 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000662 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000663 newIdx = pParse->nTab++;
664 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
665 }
666
667 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000668 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000669 goto trigger_cleanup;
670 }
671
672 /* loop thru the view snapshot, executing triggers for each row */
673 endOfLoop = sqliteVdbeMakeLabel(v);
674 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
675
676 /* Loop thru the view snapshot, executing triggers for each row */
677 startOfLoop = sqliteVdbeCurrentAddr(v);
678
679 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000680 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000681 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000682
683 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
684 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000685 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000686 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000687 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000688
689 for(ii=0; ii<pChanges->nExpr; ii++){
690 int jj;
691 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000692 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000693 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000694 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000695
696 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000697 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000698
699 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000700 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
701 aXRef[jj] = ii;
702 break;
703 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000704 }
705 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000706 sqliteSetString(&pParse->zErrMsg, "no such column: ",
707 pChanges->a[ii].zName, 0);
708 pParse->nErr++;
709 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000710 }
711 }
712
713 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
714
danielk1977633ed082002-05-17 00:05:58 +0000715 for(ii = 0; ii<pTab->nCol; ii++){
716 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000717 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000718 }else{
drh9adf9ac2002-05-15 11:44:13 +0000719 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000720 }
721 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000722
723 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
724 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
725 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
726
727 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk1977633ed082002-05-17 00:05:58 +0000728 pTab, newIdx, oldIdx, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000729 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk1977633ed082002-05-17 00:05:58 +0000730 pTab, newIdx, oldIdx, orconf);
danielk1977f29ce552002-05-19 23:43:12 +0000731 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000732 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000733 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000734 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000735 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000736 }
737
738 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
739
740 sqliteVdbeResolveLabel(v, endOfLoop);
741 sqliteEndWriteOperation(pParse);
742
743trigger_cleanup:
744 sqliteFree(aXRef);
745 sqliteExprListDelete(pChanges);
746 sqliteExprDelete(pWhere);
747 sqliteExprListDelete(theSelect.pEList);
748 sqliteIdListDelete(theSelect.pSrc);
749 sqliteExprDelete(theSelect.pWhere);
750 return;
751}