blob: d0141b0eb19f26f0b809d63f47a8dcc965e2af15 [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;
danielk1977f29ce552002-05-19 23:43:12 +000083 while( ss ){
danielk1977c3f9bad2002-05-15 08:30:12 +000084 sqliteSelectMoveStrings(ss->pSelect, offset);
danielk1977f29ce552002-05-19 23:43:12 +000085 if( ss->target.z ){
86 ss->target.z += offset;
87 }
danielk1977c3f9bad2002-05-15 08:30:12 +000088 sqliteExprMoveStrings(ss->pWhere, offset);
89 sqliteExprListMoveStrings(ss->pExprList, offset);
90
91 ss = ss->pNext;
92 }
93
94 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +000095 ** build the sqlite_master entry
96 */
97 if( !pParse->initFlag && !tab->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +000098
99 /* Make an entry in the sqlite_master table */
100 sqliteBeginWriteOperation(pParse);
101
102 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenWrite, 0, 2);
103 sqliteVdbeChangeP3(pParse->pVdbe, -1, MASTER_NAME, P3_STATIC);
104 sqliteVdbeAddOp(pParse->pVdbe, OP_NewRecno, 0, 0);
105 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
106 sqliteVdbeChangeP3(pParse->pVdbe, -1, "trigger", P3_STATIC);
107 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
108 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->name, 0);
109 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
110 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->table, 0);
111 sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, 0, 0);
112 sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
113 sqliteVdbeChangeP3(pParse->pVdbe, -1, nt->strings, 0);
114 sqliteVdbeAddOp(pParse->pVdbe, OP_MakeRecord, 5, 0);
115 sqliteVdbeAddOp(pParse->pVdbe, OP_PutIntKey, 0, 1);
116
117 /* Change the cookie, since the schema is changed */
drhdc379452002-05-15 12:45:43 +0000118 sqliteChangeCookie(pParse->db);
danielk1977c3f9bad2002-05-15 08:30:12 +0000119 sqliteVdbeAddOp(pParse->pVdbe, OP_Integer, pParse->db->next_cookie, 0);
120 sqliteVdbeAddOp(pParse->pVdbe, OP_SetCookie, 0, 0);
121
122 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, 0, 0);
123
124 sqliteEndWriteOperation(pParse);
125 }
126
danielk1977633ed082002-05-17 00:05:58 +0000127 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000128 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000129 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000130
131 /* Attach it to the table object */
132 nt->pNext = tab->pTrigger;
133 tab->pTrigger = nt;
134 return;
danielk1977f29ce552002-05-19 23:43:12 +0000135 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000136 sqliteFree(nt->strings);
137 sqliteFree(nt->name);
138 sqliteFree(nt->table);
139 sqliteFree(nt);
140 }
141
142trigger_cleanup:
143
danielk1977633ed082002-05-17 00:05:58 +0000144 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000145 sqliteExprDelete(pWhen);
146 {
147 TriggerStep * pp;
148 TriggerStep * nn;
149
danielk1977633ed082002-05-17 00:05:58 +0000150 pp = pStepList;
danielk1977f29ce552002-05-19 23:43:12 +0000151 while( pp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000152 nn = pp->pNext;
153 sqliteExprDelete(pp->pWhere);
154 sqliteExprListDelete(pp->pExprList);
155 sqliteSelectDelete(pp->pSelect);
156 sqliteIdListDelete(pp->pIdList);
157 sqliteFree(pp);
158 pp = nn;
159 }
160 }
161}
162
danielk1977633ed082002-05-17 00:05:58 +0000163TriggerStep *sqliteTriggerSelectStep(Select * pSelect)
danielk1977c3f9bad2002-05-15 08:30:12 +0000164{
danielk1977633ed082002-05-17 00:05:58 +0000165 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000166
danielk1977633ed082002-05-17 00:05:58 +0000167 pTriggerStep->op = TK_SELECT;
168 pTriggerStep->pSelect = pSelect;
169 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000170
danielk1977633ed082002-05-17 00:05:58 +0000171 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000172}
173
danielk1977633ed082002-05-17 00:05:58 +0000174TriggerStep *sqliteTriggerInsertStep(
175 Token *pTableName,
176 IdList *pColumn,
177 ExprList *pEList,
178 Select *pSelect,
179 int orconf
180){
181 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000182
danielk1977633ed082002-05-17 00:05:58 +0000183 assert(pEList == 0 || pSelect == 0);
184 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000185
danielk1977633ed082002-05-17 00:05:58 +0000186 pTriggerStep->op = TK_INSERT;
187 pTriggerStep->pSelect = pSelect;
188 pTriggerStep->target = *pTableName;
189 pTriggerStep->pIdList = pColumn;
190 pTriggerStep->pExprList = pEList;
191 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000192
danielk1977633ed082002-05-17 00:05:58 +0000193 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000194}
195
danielk1977633ed082002-05-17 00:05:58 +0000196TriggerStep *sqliteTriggerUpdateStep(
197 Token *pTableName,
198 ExprList *pEList,
199 Expr *pWhere,
200 int orconf)
danielk1977c3f9bad2002-05-15 08:30:12 +0000201{
danielk1977633ed082002-05-17 00:05:58 +0000202 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000203
danielk1977633ed082002-05-17 00:05:58 +0000204 pTriggerStep->op = TK_UPDATE;
205 pTriggerStep->target = *pTableName;
206 pTriggerStep->pExprList = pEList;
207 pTriggerStep->pWhere = pWhere;
208 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000209
danielk1977633ed082002-05-17 00:05:58 +0000210 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000211}
212
danielk1977633ed082002-05-17 00:05:58 +0000213TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere)
danielk1977c3f9bad2002-05-15 08:30:12 +0000214{
danielk1977633ed082002-05-17 00:05:58 +0000215 TriggerStep * pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
danielk1977c3f9bad2002-05-15 08:30:12 +0000216
danielk1977633ed082002-05-17 00:05:58 +0000217 pTriggerStep->op = TK_DELETE;
218 pTriggerStep->target = *pTableName;
219 pTriggerStep->pWhere = pWhere;
220 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000221
danielk1977633ed082002-05-17 00:05:58 +0000222 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000223}
224
danielk1977633ed082002-05-17 00:05:58 +0000225/*
226** Recursively delete a Trigger structure
227*/
228void sqliteDeleteTrigger(Trigger *pTrigger)
danielk1977c3f9bad2002-05-15 08:30:12 +0000229{
danielk1977633ed082002-05-17 00:05:58 +0000230 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000231
danielk1977633ed082002-05-17 00:05:58 +0000232 pTriggerStep = pTrigger->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000233 while( pTriggerStep ){
danielk1977633ed082002-05-17 00:05:58 +0000234 TriggerStep * pTmp = pTriggerStep;
235 pTriggerStep = pTriggerStep->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000236
danielk1977633ed082002-05-17 00:05:58 +0000237 sqliteExprDelete(pTmp->pWhere);
238 sqliteExprListDelete(pTmp->pExprList);
239 sqliteSelectDelete(pTmp->pSelect);
240 sqliteIdListDelete(pTmp->pIdList);
danielk1977c3f9bad2002-05-15 08:30:12 +0000241
danielk1977633ed082002-05-17 00:05:58 +0000242 sqliteFree(pTmp);
danielk1977c3f9bad2002-05-15 08:30:12 +0000243 }
244
danielk1977633ed082002-05-17 00:05:58 +0000245 sqliteFree(pTrigger->name);
246 sqliteFree(pTrigger->table);
247 sqliteExprDelete(pTrigger->pWhen);
248 sqliteIdListDelete(pTrigger->pColumns);
249 sqliteFree(pTrigger->strings);
250 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000251}
252
253/*
danielk1977633ed082002-05-17 00:05:58 +0000254 * This function is called to drop a trigger from the database schema.
255 *
256 * This may be called directly from the parser, or from within
257 * sqliteDropTable(). In the latter case the "nested" argument is true.
258 *
259 * Note that this function does not delete the trigger entirely. Instead it
260 * removes it from the internal schema and places it in the trigDrop hash
261 * table. This is so that the trigger can be restored into the database schema
262 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000263 */
danielk1977633ed082002-05-17 00:05:58 +0000264void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
danielk1977c3f9bad2002-05-15 08:30:12 +0000265{
danielk1977633ed082002-05-17 00:05:58 +0000266 char *zName;
267 Trigger *pTrigger;
268 Table *pTable;
danielk1977c3f9bad2002-05-15 08:30:12 +0000269
danielk1977633ed082002-05-17 00:05:58 +0000270 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000271
272 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000273 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
274 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000275 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000276 zName, -1, 0);
277 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000278 return;
279 }
280
281 /*
282 * If this is not an "explain", do the following:
283 * 1. Remove the trigger from its associated table structure
284 * 2. Move the trigger from the trigHash hash to trigDrop
285 */
danielk1977633ed082002-05-17 00:05:58 +0000286 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000287 /* 1 */
danielk1977633ed082002-05-17 00:05:58 +0000288 pTable = sqliteFindTable(pParse->db, pTrigger->table);
289 assert(pTable);
290 if( pTable->pTrigger == pTrigger ){
291 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000292 }else{
danielk1977633ed082002-05-17 00:05:58 +0000293 Trigger *cc = pTable->pTrigger;
294 while( cc ){
295 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000296 cc->pNext = cc->pNext->pNext;
297 break;
298 }
299 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000300 }
301 assert(cc);
302 }
303
304 /* 2 */
danielk1977633ed082002-05-17 00:05:58 +0000305 sqliteHashInsert(&(pParse->db->trigHash), zName,
306 pName->n + 1, NULL);
307 sqliteHashInsert(&(pParse->db->trigDrop), pTrigger->name,
308 pName->n + 1, pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000309 }
310
311 /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
312 * database record of the trigger */
danielk1977633ed082002-05-17 00:05:58 +0000313 if( !pTable->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000314 int base;
315 static VdbeOp dropTrigger[] = {
316 { OP_OpenWrite, 0, 2, MASTER_NAME},
317 { OP_Rewind, 0, ADDR(9), 0},
318 { OP_String, 0, 0, 0}, /* 2 */
319 { OP_MemStore, 1, 1, 0},
320 { OP_MemLoad, 1, 0, 0}, /* 4 */
321 { OP_Column, 0, 1, 0},
322 { OP_Ne, 0, ADDR(8), 0},
323 { OP_Delete, 0, 0, 0},
324 { OP_Next, 0, ADDR(4), 0}, /* 8 */
325 { OP_Integer, 0, 0, 0}, /* 9 */
326 { OP_SetCookie, 0, 0, 0},
327 { OP_Close, 0, 0, 0},
328 };
329
drhdc379452002-05-15 12:45:43 +0000330 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000331 sqliteBeginWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000332 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000333 base = sqliteVdbeAddOpList(pParse->pVdbe,
drh9adf9ac2002-05-15 11:44:13 +0000334 ArraySize(dropTrigger), dropTrigger);
danielk1977633ed082002-05-17 00:05:58 +0000335 sqliteVdbeChangeP3(pParse->pVdbe, base+2, zName, 0);
drhdc379452002-05-15 12:45:43 +0000336 if( !nested ){
337 sqliteChangeCookie(pParse->db);
338 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000339 sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
drhdc379452002-05-15 12:45:43 +0000340 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000341 sqliteEndWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000342 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000343 }
344
danielk1977633ed082002-05-17 00:05:58 +0000345 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000346}
347
danielk1977633ed082002-05-17 00:05:58 +0000348static int checkColumnOverLap(IdList * pIdList, ExprList * pEList)
danielk1977c3f9bad2002-05-15 08:30:12 +0000349{
350 int i, e;
danielk1977f29ce552002-05-19 23:43:12 +0000351 if( !pIdList )return 1;
352 if( !pEList )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000353
danielk1977f29ce552002-05-19 23:43:12 +0000354 for(i = 0; i < pIdList->nId; i++){
355 for(e = 0; e < pEList->nExpr; e++){
356 if( !sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName) ){
drh9adf9ac2002-05-15 11:44:13 +0000357 return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000358 }
359 }
360 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000361
362 return 0;
363}
364
365/* A global variable that is TRUE if we should always set up temp tables for
366 * for triggers, even if there are no triggers to code. This is used to test
367 * how much overhead the triggers algorithm is causing.
368 *
369 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
370 * The pragma is not documented since it is not really part of the interface
371 * to SQLite, just the test procedure.
372*/
373int always_code_trigger_setup = 0;
374
375/*
376 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
377 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
378 * found in the list specified as pTrigger.
379 */
380int sqliteTriggersExist(
danielk1977633ed082002-05-17 00:05:58 +0000381 Parse *pParse,
382 Trigger *pTrigger,
383 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
384 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
385 int foreach, /* one of TK_ROW or TK_STATEMENT */
386 ExprList *pChanges)
danielk1977c3f9bad2002-05-15 08:30:12 +0000387{
danielk1977633ed082002-05-17 00:05:58 +0000388 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000389
danielk1977633ed082002-05-17 00:05:58 +0000390 if( always_code_trigger_setup ){
391 return 1;
392 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000393
danielk1977633ed082002-05-17 00:05:58 +0000394 pTriggerCursor = pTrigger;
395 while( pTriggerCursor ){
396 if( pTriggerCursor->op == op &&
397 pTriggerCursor->tr_tm == tr_tm &&
398 pTriggerCursor->foreach == foreach &&
399 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000400 TriggerStack * ss;
401 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000402 while( ss && ss->pTrigger != pTrigger ){
403 ss = ss->pNext;
404 }
405 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000406 }
danielk1977633ed082002-05-17 00:05:58 +0000407 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000408 }
409
410 return 0;
411}
412
413static int codeTriggerProgram(
danielk1977633ed082002-05-17 00:05:58 +0000414 Parse *pParse,
415 TriggerStep *pStepList,
416 int orconfin
417){
418 TriggerStep * pTriggerStep = pStepList;
419 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000420
danielk1977633ed082002-05-17 00:05:58 +0000421 while( pTriggerStep ){
422 int saveNTab = pParse->nTab;
423 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
424 pParse->trigStack->orconf = orconf;
425 switch( pTriggerStep->op ){
426 case TK_SELECT: {
427 int tmp_tbl = pParse->nTab++;
428 sqliteVdbeAddOp(pParse->pVdbe, OP_OpenTemp, tmp_tbl, 0);
429 sqliteVdbeAddOp(pParse->pVdbe, OP_KeyAsData, tmp_tbl, 1);
430 sqliteSelect(pParse, pTriggerStep->pSelect, SRT_Union,
431 tmp_tbl, 0, 0, 0);
432 sqliteVdbeAddOp(pParse->pVdbe, OP_Close, tmp_tbl, 0);
433 pParse->nTab--;
434 break;
435 }
436 case TK_UPDATE: {
437 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
438 sqliteUpdate(pParse, &pTriggerStep->target,
439 sqliteExprListDup(pTriggerStep->pExprList),
440 sqliteExprDup(pTriggerStep->pWhere), orconf);
441 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
442 break;
443 }
444 case TK_INSERT: {
445 sqliteInsert(pParse, &pTriggerStep->target,
446 sqliteExprListDup(pTriggerStep->pExprList),
447 sqliteSelectDup(pTriggerStep->pSelect),
448 sqliteIdListDup(pTriggerStep->pIdList), orconf);
449 break;
450 }
451 case TK_DELETE: {
452 sqliteVdbeAddOp(pParse->pVdbe, OP_PushList, 0, 0);
453 sqliteDeleteFrom(pParse, &pTriggerStep->target,
454 sqliteExprDup(pTriggerStep->pWhere));
455 sqliteVdbeAddOp(pParse->pVdbe, OP_PopList, 0, 0);
456 break;
457 }
458 default:
459 assert(0);
460 }
461 pParse->nTab = saveNTab;
462 pTriggerStep = pTriggerStep->pNext;
463 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000464
danielk1977633ed082002-05-17 00:05:58 +0000465 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000466}
467
danielk1977633ed082002-05-17 00:05:58 +0000468/*
469** This is called to code FOR EACH ROW triggers.
470**
471** When the code that this function generates is executed, the following
472** must be true:
473** 1. NO vdbe cursors must be open.
474** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
475** a temporary vdbe cursor (index newIdx) must be open and pointing at
476** a row containing values to be substituted for new.* expressions in the
477** trigger program(s).
478** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
479** a temporary vdbe cursor (index oldIdx) must be open and pointing at
480** a row containing values to be substituted for old.* expressions in the
481** trigger program(s).
482**
483*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000484int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000485 Parse *pParse, /* Parse context */
486 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
487 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
488 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
489 Table *pTab, /* The table to code triggers from */
490 int newIdx, /* The indice of the "new" row to access */
491 int oldIdx, /* The indice of the "old" row to access */
492 int orconf) /* ON CONFLICT policy */
danielk1977c3f9bad2002-05-15 08:30:12 +0000493{
494 Trigger * pTrigger;
495 TriggerStack * pTriggerStack;
496
danielk1977c3f9bad2002-05-15 08:30:12 +0000497 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
498 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
499
danielk1977633ed082002-05-17 00:05:58 +0000500 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000501
danielk1977633ed082002-05-17 00:05:58 +0000502 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000503 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000504 int fire_this = 0;
505
506 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000507 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
508 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000509 fire_this = 1;
510 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000511 while( pTriggerStack ){
512 if( pTriggerStack->pTrigger == pTrigger ){
513 fire_this = 0;
514 }
drh9adf9ac2002-05-15 11:44:13 +0000515 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000516 }
danielk1977f29ce552002-05-19 23:43:12 +0000517 if( op == TK_UPDATE && pTrigger->pColumns &&
518 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000519 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000520 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000521 }
522
danielk1977f29ce552002-05-19 23:43:12 +0000523 if( fire_this ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000524 int endTrigger;
525 IdList dummyTablist;
526 Expr * whenExpr;
527
528 dummyTablist.nId = 0;
529 dummyTablist.a = 0;
530
531 /* Push an entry on to the trigger stack */
532 pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
533 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000534 pTriggerStack->newIdx = newIdx;
535 pTriggerStack->oldIdx = oldIdx;
536 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000537 pTriggerStack->pNext = pParse->trigStack;
538 pParse->trigStack = pTriggerStack;
539
540 /* code the WHEN clause */
541 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
542 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000543 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000544 pParse->trigStack = pParse->trigStack->pNext;
545 sqliteFree(pTriggerStack);
546 sqliteExprDelete(whenExpr);
547 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000548 }
549 sqliteExprIfFalse(pParse, whenExpr, endTrigger);
550 sqliteExprDelete(whenExpr);
551
danielk1977633ed082002-05-17 00:05:58 +0000552 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000553
554 /* Pop the entry off the trigger stack */
555 pParse->trigStack = pParse->trigStack->pNext;
556 sqliteFree(pTriggerStack);
557
558 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
559 }
560 pTrigger = pTrigger->pNext;
561 }
562
563 return 0;
564}
565
566/*
danielk1977633ed082002-05-17 00:05:58 +0000567 * This function is called to code ON UPDATE and ON DELETE triggers on
568 * views.
569 *
570 * This function deletes the data pointed at by the pWhere and pChanges
571 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000572 */
danielk1977633ed082002-05-17 00:05:58 +0000573void sqliteViewTriggers(
574 Parse *pParse,
575 Table *pTab, /* The view to code triggers on */
576 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
577 int orconf, /* The ON CONFLICT policy specified as part of the
578 statement causing these triggers */
579 ExprList *pChanges /* If this is an statement causing triggers to fire
580 is an UPDATE, then this list holds the columns
581 to update and the expressions to update them to.
582 See comments for sqliteUpdate(). */
583){
danielk1977c3f9bad2002-05-15 08:30:12 +0000584 int oldIdx = -1;
585 int newIdx = -1;
586 int *aXRef = 0;
587 Vdbe *v;
588 int endOfLoop;
589 int startOfLoop;
590 Select theSelect;
591 Token tblNameToken;
592
593 assert(pTab->pSelect);
594
595 tblNameToken.z = pTab->zName;
596 tblNameToken.n = strlen(pTab->zName);
597
598 theSelect.isDistinct = 0;
599 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
600 theSelect.pSrc = sqliteIdListAppend(0, &tblNameToken);
601 theSelect.pWhere = pWhere; pWhere = 0;
602 theSelect.pGroupBy = 0;
603 theSelect.pHaving = 0;
604 theSelect.pOrderBy = 0;
605 theSelect.op = TK_SELECT; /* ?? */
606 theSelect.pPrior = 0;
607 theSelect.nLimit = -1;
608 theSelect.nOffset = -1;
609 theSelect.zSelect = 0;
610 theSelect.base = 0;
611
612 v = sqliteGetVdbe(pParse);
613 assert(v);
614 sqliteBeginMultiWriteOperation(pParse);
615
616 /* Allocate temp tables */
617 oldIdx = pParse->nTab++;
618 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000619 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000620 newIdx = pParse->nTab++;
621 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
622 }
623
624 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000625 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000626 goto trigger_cleanup;
627 }
628
629 /* loop thru the view snapshot, executing triggers for each row */
630 endOfLoop = sqliteVdbeMakeLabel(v);
631 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
632
633 /* Loop thru the view snapshot, executing triggers for each row */
634 startOfLoop = sqliteVdbeCurrentAddr(v);
635
636 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000637 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000638 int ii, jj;
639
640 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
641 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000642 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000643 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000644 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000645
646 for(ii=0; ii<pChanges->nExpr; ii++){
647 int jj;
648 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000649 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000650 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000651 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000652
653 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000654 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000655
656 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000657 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
658 aXRef[jj] = ii;
659 break;
660 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000661 }
662 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000663 sqliteSetString(&pParse->zErrMsg, "no such column: ",
664 pChanges->a[ii].zName, 0);
665 pParse->nErr++;
666 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000667 }
668 }
669
670 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
671
danielk1977633ed082002-05-17 00:05:58 +0000672 for(ii = 0; ii<pTab->nCol; ii++){
673 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000674 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000675 }else{
drh9adf9ac2002-05-15 11:44:13 +0000676 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000677 }
678 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000679
680 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
681 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
682 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
683
684 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk1977633ed082002-05-17 00:05:58 +0000685 pTab, newIdx, oldIdx, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000686 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk1977633ed082002-05-17 00:05:58 +0000687 pTab, newIdx, oldIdx, orconf);
danielk1977f29ce552002-05-19 23:43:12 +0000688 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000689 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000690 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000691 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk1977633ed082002-05-17 00:05:58 +0000692 orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000693 }
694
695 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
696
697 sqliteVdbeResolveLabel(v, endOfLoop);
698 sqliteEndWriteOperation(pParse);
699
700trigger_cleanup:
701 sqliteFree(aXRef);
702 sqliteExprListDelete(pChanges);
703 sqliteExprDelete(pWhere);
704 sqliteExprListDelete(theSelect.pEList);
705 sqliteIdListDelete(theSelect.pSrc);
706 sqliteExprDelete(theSelect.pWhere);
707 return;
708}