blob: 95e8fc9f81f76a1a14c73e788e763cb9f53a6f9f [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 */
danielk1977d702fcc2002-05-26 23:24:40 +000023 int tr_tm, /* One of TK_BEFORE, TK_AFTER , TK_INSTEAD */
drh9adf9ac2002-05-15 11:44:13 +000024 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.
danielk1977d702fcc2002-05-26 23:24:40 +000041 ** 3. that we are not trying to create a trigger on the sqlite_master table
42 ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
43 ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
drh9adf9ac2002-05-15 11:44:13 +000044 */
danielk1977c3f9bad2002-05-15 08:30:12 +000045 {
danielk1977633ed082002-05-17 00:05:58 +000046 char *tmp_str = sqliteStrNDup(pName->z, pName->n);
47 if( sqliteHashFind(&(pParse->db->trigHash), tmp_str, pName->n + 1) ){
danielk1977c3f9bad2002-05-15 08:30:12 +000048 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
danielk1977633ed082002-05-17 00:05:58 +000049 pName->z, pName->n, " already exists", -1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000050 sqliteFree(tmp_str);
51 pParse->nErr++;
52 goto trigger_cleanup;
53 }
54 sqliteFree(tmp_str);
55 }
56 {
danielk1977633ed082002-05-17 00:05:58 +000057 char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +000058 if( tmp_str==0 ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000059 tab = sqliteFindTable(pParse->db, tmp_str);
60 sqliteFree(tmp_str);
drh9adf9ac2002-05-15 11:44:13 +000061 if( !tab ){
danielk1977c3f9bad2002-05-15 08:30:12 +000062 sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
danielk1977633ed082002-05-17 00:05:58 +000063 pTableName->z, pTableName->n, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000064 pParse->nErr++;
65 goto trigger_cleanup;
66 }
drh1873cd52002-05-23 00:30:31 +000067 if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
68 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
69 "table: " MASTER_NAME, 0);
70 pParse->nErr++;
71 goto trigger_cleanup;
72 }
danielk1977d702fcc2002-05-26 23:24:40 +000073 if( tab->pSelect && tr_tm != TK_INSTEAD ){
74 sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
75 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
76 , pTableName->z, pTableName->n, 0);
77 goto trigger_cleanup;
78 }
79 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
80 sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1,
81 " trigger on table: ", -1, pTableName->z, pTableName->n, 0);
82 goto trigger_cleanup;
83 }
84 }
85
86 if (tr_tm == TK_INSTEAD){
87 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +000088 }
89
90 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +000091 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +000092 if( nt==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +000093 nt->name = sqliteStrNDup(pName->z, pName->n);
94 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +000095 nt->strings = sqliteStrNDup(zData, zDataLen);
96 if( sqlite_malloc_failed ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000097 nt->op = op;
98 nt->tr_tm = tr_tm;
99 nt->pWhen = pWhen;
danielk1977633ed082002-05-17 00:05:58 +0000100 nt->pColumns = pColumns;
danielk1977c3f9bad2002-05-15 08:30:12 +0000101 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000102 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000103 nt->isCommit = 0;
danielk1977633ed082002-05-17 00:05:58 +0000104 offset = (int)(nt->strings - zData);
danielk1977c3f9bad2002-05-15 08:30:12 +0000105 sqliteExprMoveStrings(nt->pWhen, offset);
106
107 ss = nt->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000108 while( ss ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000109 sqliteSelectMoveStrings(ss->pSelect, offset);
danielk1977f29ce552002-05-19 23:43:12 +0000110 if( ss->target.z ){
111 ss->target.z += offset;
112 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000113 sqliteExprMoveStrings(ss->pWhere, offset);
114 sqliteExprListMoveStrings(ss->pExprList, offset);
115
116 ss = ss->pNext;
117 }
118
119 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000120 ** build the sqlite_master entry
121 */
122 if( !pParse->initFlag && !tab->isTemp ){
drhc977f7f2002-05-21 11:38:11 +0000123 static VdbeOp insertTrig[] = {
124 { OP_OpenWrite, 0, 2, MASTER_NAME},
125 { OP_NewRecno, 0, 0, 0 },
126 { OP_String, 0, 0, "trigger" },
127 { OP_String, 0, 0, 0 }, /* 3: trigger name */
128 { OP_String, 0, 0, 0 }, /* 4: table name */
129 { OP_Integer, 0, 0, 0 },
130 { OP_String, 0, 0, 0 }, /* 6: SQL */
131 { OP_MakeRecord, 5, 0, 0 },
132 { OP_PutIntKey, 0, 0, 0 },
133 { OP_Integer, 0, 0, 0 }, /* 9: Next cookie */
134 { OP_SetCookie, 0, 0, 0 },
135 { OP_Close, 0, 0, 0 },
136 };
137 int addr;
138 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000139
140 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000141 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000142 if( v==0 ) goto trigger_cleanup;
drhc977f7f2002-05-21 11:38:11 +0000143 sqliteBeginWriteOperation(pParse, 0);
144 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
145 sqliteVdbeChangeP3(v, addr+3, nt->name, 0);
146 sqliteVdbeChangeP3(v, addr+4, nt->table, 0);
147 sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);
drhdc379452002-05-15 12:45:43 +0000148 sqliteChangeCookie(pParse->db);
drhc977f7f2002-05-21 11:38:11 +0000149 sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);
danielk1977c3f9bad2002-05-15 08:30:12 +0000150 sqliteEndWriteOperation(pParse);
151 }
152
danielk1977633ed082002-05-17 00:05:58 +0000153 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000154 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000155 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000156
157 /* Attach it to the table object */
158 nt->pNext = tab->pTrigger;
159 tab->pTrigger = nt;
160 return;
danielk1977f29ce552002-05-19 23:43:12 +0000161 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000162 sqliteFree(nt->strings);
163 sqliteFree(nt->name);
164 sqliteFree(nt->table);
165 sqliteFree(nt);
166 }
167
168trigger_cleanup:
169
danielk1977633ed082002-05-17 00:05:58 +0000170 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000171 sqliteExprDelete(pWhen);
172 {
173 TriggerStep * pp;
174 TriggerStep * nn;
175
danielk1977633ed082002-05-17 00:05:58 +0000176 pp = pStepList;
danielk1977f29ce552002-05-19 23:43:12 +0000177 while( pp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000178 nn = pp->pNext;
179 sqliteExprDelete(pp->pWhere);
180 sqliteExprListDelete(pp->pExprList);
181 sqliteSelectDelete(pp->pSelect);
182 sqliteIdListDelete(pp->pIdList);
183 sqliteFree(pp);
184 pp = nn;
185 }
186 }
187}
188
drhc977f7f2002-05-21 11:38:11 +0000189/*
190** Turn a SELECT statement (that the pSelect parameter points to) into
191** a trigger step. Return a pointer to a TriggerStep structure.
192**
193** The parser calls this routine when it finds a SELECT statement in
194** body of a TRIGGER.
195*/
196TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000197 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000198 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000199
danielk1977633ed082002-05-17 00:05:58 +0000200 pTriggerStep->op = TK_SELECT;
201 pTriggerStep->pSelect = pSelect;
202 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000203
danielk1977633ed082002-05-17 00:05:58 +0000204 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000205}
206
drhc977f7f2002-05-21 11:38:11 +0000207/*
208** Build a trigger step out of an INSERT statement. Return a pointer
209** to the new trigger step.
210**
211** The parser calls this routine when it sees an INSERT inside the
212** body of a trigger.
213*/
danielk1977633ed082002-05-17 00:05:58 +0000214TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000215 Token *pTableName, /* Name of the table into which we insert */
216 IdList *pColumn, /* List of columns in pTableName to insert into */
217 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
218 Select *pSelect, /* A SELECT statement that supplies values */
219 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000220){
221 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000222 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000223
danielk1977633ed082002-05-17 00:05:58 +0000224 assert(pEList == 0 || pSelect == 0);
225 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000226
danielk1977633ed082002-05-17 00:05:58 +0000227 pTriggerStep->op = TK_INSERT;
228 pTriggerStep->pSelect = pSelect;
229 pTriggerStep->target = *pTableName;
230 pTriggerStep->pIdList = pColumn;
231 pTriggerStep->pExprList = pEList;
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 an UPDATE statement and return
239** a pointer to that trigger step. The parser calls this routine when it
240** sees an UPDATE statement inside the body of a CREATE TRIGGER.
241*/
danielk1977633ed082002-05-17 00:05:58 +0000242TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000243 Token *pTableName, /* Name of the table to be updated */
244 ExprList *pEList, /* The SET clause: list of column and new values */
245 Expr *pWhere, /* The WHERE clause */
246 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
247){
danielk1977633ed082002-05-17 00:05:58 +0000248 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000249 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000250
danielk1977633ed082002-05-17 00:05:58 +0000251 pTriggerStep->op = TK_UPDATE;
252 pTriggerStep->target = *pTableName;
253 pTriggerStep->pExprList = pEList;
254 pTriggerStep->pWhere = pWhere;
255 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000256
danielk1977633ed082002-05-17 00:05:58 +0000257 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000258}
259
drhc977f7f2002-05-21 11:38:11 +0000260/*
261** Construct a trigger step that implements a DELETE statement and return
262** a pointer to that trigger step. The parser calls this routine when it
263** sees a DELETE statement inside the body of a CREATE TRIGGER.
264*/
265TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000266 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
267 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000268
danielk1977633ed082002-05-17 00:05:58 +0000269 pTriggerStep->op = TK_DELETE;
270 pTriggerStep->target = *pTableName;
271 pTriggerStep->pWhere = pWhere;
272 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000273
danielk1977633ed082002-05-17 00:05:58 +0000274 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000275}
276
danielk1977633ed082002-05-17 00:05:58 +0000277/*
278** Recursively delete a Trigger structure
279*/
drh1d1f3052002-05-21 13:18:25 +0000280void sqliteDeleteTrigger(Trigger *pTrigger){
danielk1977633ed082002-05-17 00:05:58 +0000281 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000282
danielk1977633ed082002-05-17 00:05:58 +0000283 pTriggerStep = pTrigger->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000284 while( pTriggerStep ){
danielk1977633ed082002-05-17 00:05:58 +0000285 TriggerStep * pTmp = pTriggerStep;
286 pTriggerStep = pTriggerStep->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000287
danielk1977633ed082002-05-17 00:05:58 +0000288 sqliteExprDelete(pTmp->pWhere);
289 sqliteExprListDelete(pTmp->pExprList);
290 sqliteSelectDelete(pTmp->pSelect);
291 sqliteIdListDelete(pTmp->pIdList);
danielk1977c3f9bad2002-05-15 08:30:12 +0000292
danielk1977633ed082002-05-17 00:05:58 +0000293 sqliteFree(pTmp);
danielk1977c3f9bad2002-05-15 08:30:12 +0000294 }
295
danielk1977633ed082002-05-17 00:05:58 +0000296 sqliteFree(pTrigger->name);
297 sqliteFree(pTrigger->table);
298 sqliteExprDelete(pTrigger->pWhen);
299 sqliteIdListDelete(pTrigger->pColumns);
300 sqliteFree(pTrigger->strings);
301 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000302}
303
304/*
danielk1977633ed082002-05-17 00:05:58 +0000305 * This function is called to drop a trigger from the database schema.
306 *
307 * This may be called directly from the parser, or from within
308 * sqliteDropTable(). In the latter case the "nested" argument is true.
309 *
310 * Note that this function does not delete the trigger entirely. Instead it
311 * removes it from the internal schema and places it in the trigDrop hash
312 * table. This is so that the trigger can be restored into the database schema
313 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000314 */
danielk1977633ed082002-05-17 00:05:58 +0000315void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
danielk1977c3f9bad2002-05-15 08:30:12 +0000316{
danielk1977633ed082002-05-17 00:05:58 +0000317 char *zName;
318 Trigger *pTrigger;
319 Table *pTable;
danielk1977c3f9bad2002-05-15 08:30:12 +0000320
danielk1977633ed082002-05-17 00:05:58 +0000321 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000322
323 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000324 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
325 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000326 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000327 zName, -1, 0);
328 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000329 return;
330 }
331
332 /*
333 * If this is not an "explain", do the following:
334 * 1. Remove the trigger from its associated table structure
335 * 2. Move the trigger from the trigHash hash to trigDrop
336 */
danielk1977633ed082002-05-17 00:05:58 +0000337 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000338 /* 1 */
danielk1977633ed082002-05-17 00:05:58 +0000339 pTable = sqliteFindTable(pParse->db, pTrigger->table);
340 assert(pTable);
341 if( pTable->pTrigger == pTrigger ){
342 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000343 }else{
danielk1977633ed082002-05-17 00:05:58 +0000344 Trigger *cc = pTable->pTrigger;
345 while( cc ){
346 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000347 cc->pNext = cc->pNext->pNext;
348 break;
349 }
350 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000351 }
352 assert(cc);
353 }
354
355 /* 2 */
danielk1977633ed082002-05-17 00:05:58 +0000356 sqliteHashInsert(&(pParse->db->trigHash), zName,
357 pName->n + 1, NULL);
358 sqliteHashInsert(&(pParse->db->trigDrop), pTrigger->name,
359 pName->n + 1, pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000360 }
361
362 /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
363 * database record of the trigger */
danielk1977633ed082002-05-17 00:05:58 +0000364 if( !pTable->isTemp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000365 int base;
366 static VdbeOp dropTrigger[] = {
367 { OP_OpenWrite, 0, 2, MASTER_NAME},
368 { OP_Rewind, 0, ADDR(9), 0},
369 { OP_String, 0, 0, 0}, /* 2 */
370 { OP_MemStore, 1, 1, 0},
371 { OP_MemLoad, 1, 0, 0}, /* 4 */
372 { OP_Column, 0, 1, 0},
373 { OP_Ne, 0, ADDR(8), 0},
374 { OP_Delete, 0, 0, 0},
375 { OP_Next, 0, ADDR(4), 0}, /* 8 */
376 { OP_Integer, 0, 0, 0}, /* 9 */
377 { OP_SetCookie, 0, 0, 0},
378 { OP_Close, 0, 0, 0},
379 };
380
drhdc379452002-05-15 12:45:43 +0000381 if( !nested ){
drhc977f7f2002-05-21 11:38:11 +0000382 sqliteBeginWriteOperation(pParse, 0);
drhdc379452002-05-15 12:45:43 +0000383 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000384 base = sqliteVdbeAddOpList(pParse->pVdbe,
drh9adf9ac2002-05-15 11:44:13 +0000385 ArraySize(dropTrigger), dropTrigger);
danielk1977633ed082002-05-17 00:05:58 +0000386 sqliteVdbeChangeP3(pParse->pVdbe, base+2, zName, 0);
drhdc379452002-05-15 12:45:43 +0000387 if( !nested ){
388 sqliteChangeCookie(pParse->db);
389 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000390 sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
drhdc379452002-05-15 12:45:43 +0000391 if( !nested ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000392 sqliteEndWriteOperation(pParse);
drhdc379452002-05-15 12:45:43 +0000393 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000394 }
395
danielk1977633ed082002-05-17 00:05:58 +0000396 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000397}
398
drhc977f7f2002-05-21 11:38:11 +0000399/*
400** pEList is the SET clause of an UPDATE statement. Each entry
401** in pEList is of the format <id>=<expr>. If any of the entries
402** in pEList have an <id> which matches an identifier in pIdList,
403** then return TRUE. If pIdList==NULL, then it is considered a
404** wildcard that matches anything. Likewise if pEList==NULL then
405** it matches anything so always return true. Return false only
406** if there is no match.
407*/
408static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000409 int e;
410 if( !pIdList || !pEList ) return 1;
411 for(e=0; e<pEList->nExpr; e++){
412 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000413 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000414 return 0;
415}
416
417/* A global variable that is TRUE if we should always set up temp tables for
418 * for triggers, even if there are no triggers to code. This is used to test
419 * how much overhead the triggers algorithm is causing.
420 *
421 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
422 * The pragma is not documented since it is not really part of the interface
423 * to SQLite, just the test procedure.
424*/
425int always_code_trigger_setup = 0;
426
427/*
428 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
429 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
430 * found in the list specified as pTrigger.
431 */
432int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000433 Parse *pParse, /* Used to check for recursive triggers */
434 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000435 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
436 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
437 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000438 ExprList *pChanges /* Columns that change in an UPDATE statement */
439){
danielk1977633ed082002-05-17 00:05:58 +0000440 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000441
danielk1977633ed082002-05-17 00:05:58 +0000442 if( always_code_trigger_setup ){
443 return 1;
444 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000445
danielk1977633ed082002-05-17 00:05:58 +0000446 pTriggerCursor = pTrigger;
447 while( pTriggerCursor ){
448 if( pTriggerCursor->op == op &&
449 pTriggerCursor->tr_tm == tr_tm &&
450 pTriggerCursor->foreach == foreach &&
451 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000452 TriggerStack * ss;
453 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000454 while( ss && ss->pTrigger != pTrigger ){
455 ss = ss->pNext;
456 }
457 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000458 }
danielk1977633ed082002-05-17 00:05:58 +0000459 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000460 }
461
462 return 0;
463}
464
drhc977f7f2002-05-21 11:38:11 +0000465/*
466** Generate VDBE code for zero or more statements inside the body of a
467** trigger.
468*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000469static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000470 Parse *pParse, /* The parser context */
471 TriggerStep *pStepList, /* List of statements inside the trigger body */
472 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000473){
474 TriggerStep * pTriggerStep = pStepList;
475 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000476
danielk1977633ed082002-05-17 00:05:58 +0000477 while( pTriggerStep ){
478 int saveNTab = pParse->nTab;
479 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
480 pParse->trigStack->orconf = orconf;
481 switch( pTriggerStep->op ){
482 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000483 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
484 assert(ss);
485 assert(ss->pSrc);
486 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
487 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000488 break;
489 }
490 case TK_UPDATE: {
drhbd5a4512002-05-23 22:07:02 +0000491 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000492 sqliteUpdate(pParse, &pTriggerStep->target,
danielk19776f349032002-06-11 02:25:40 +0000493 sqliteExprListDup(pTriggerStep->pExprList),
494 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000495 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000496 break;
497 }
498 case TK_INSERT: {
499 sqliteInsert(pParse, &pTriggerStep->target,
500 sqliteExprListDup(pTriggerStep->pExprList),
501 sqliteSelectDup(pTriggerStep->pSelect),
502 sqliteIdListDup(pTriggerStep->pIdList), orconf);
503 break;
504 }
505 case TK_DELETE: {
drhbd5a4512002-05-23 22:07:02 +0000506 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000507 sqliteDeleteFrom(pParse, &pTriggerStep->target,
508 sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000509 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000510 break;
511 }
512 default:
513 assert(0);
514 }
515 pParse->nTab = saveNTab;
516 pTriggerStep = pTriggerStep->pNext;
517 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000518
danielk1977633ed082002-05-17 00:05:58 +0000519 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000520}
521
danielk1977633ed082002-05-17 00:05:58 +0000522/*
523** This is called to code FOR EACH ROW triggers.
524**
525** When the code that this function generates is executed, the following
526** must be true:
drhc977f7f2002-05-21 11:38:11 +0000527**
528** 1. No cursors may be open in the main database. (But newIdx and oldIdx
529** can be indices of cursors in temporary tables. See below.)
530**
danielk1977633ed082002-05-17 00:05:58 +0000531** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
532** a temporary vdbe cursor (index newIdx) must be open and pointing at
533** a row containing values to be substituted for new.* expressions in the
534** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000535**
danielk1977633ed082002-05-17 00:05:58 +0000536** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
537** a temporary vdbe cursor (index oldIdx) must be open and pointing at
538** a row containing values to be substituted for old.* expressions in the
539** trigger program(s).
540**
541*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000542int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000543 Parse *pParse, /* Parse context */
544 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
545 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
546 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
547 Table *pTab, /* The table to code triggers from */
548 int newIdx, /* The indice of the "new" row to access */
549 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000550 int orconf, /* ON CONFLICT policy */
551 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000552){
danielk1977c3f9bad2002-05-15 08:30:12 +0000553 Trigger * pTrigger;
554 TriggerStack * pTriggerStack;
555
danielk1977c3f9bad2002-05-15 08:30:12 +0000556 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
557 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
558
danielk1977633ed082002-05-17 00:05:58 +0000559 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000560
danielk1977633ed082002-05-17 00:05:58 +0000561 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000562 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000563 int fire_this = 0;
564
565 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000566 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
567 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000568 fire_this = 1;
569 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000570 while( pTriggerStack ){
571 if( pTriggerStack->pTrigger == pTrigger ){
572 fire_this = 0;
573 }
drh9adf9ac2002-05-15 11:44:13 +0000574 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000575 }
danielk1977f29ce552002-05-19 23:43:12 +0000576 if( op == TK_UPDATE && pTrigger->pColumns &&
577 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000578 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000579 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000580 }
581
drhe4697f52002-05-23 02:09:03 +0000582 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000583 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000584 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000585 Expr * whenExpr;
586
drhad3cab52002-05-24 02:04:32 +0000587 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000588 dummyTablist.a = 0;
589
590 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000591 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000592 pTriggerStack->newIdx = newIdx;
593 pTriggerStack->oldIdx = oldIdx;
594 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000595 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000596 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000597 pParse->trigStack = pTriggerStack;
598
599 /* code the WHEN clause */
600 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
601 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000602 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000603 pParse->trigStack = pParse->trigStack->pNext;
604 sqliteFree(pTriggerStack);
605 sqliteExprDelete(whenExpr);
606 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000607 }
drhf5905aa2002-05-26 20:54:33 +0000608 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000609 sqliteExprDelete(whenExpr);
610
danielk1977633ed082002-05-17 00:05:58 +0000611 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000612
613 /* Pop the entry off the trigger stack */
614 pParse->trigStack = pParse->trigStack->pNext;
615 sqliteFree(pTriggerStack);
616
617 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
618 }
619 pTrigger = pTrigger->pNext;
620 }
621
622 return 0;
623}
624
625/*
danielk1977633ed082002-05-17 00:05:58 +0000626 * This function is called to code ON UPDATE and ON DELETE triggers on
627 * views.
628 *
629 * This function deletes the data pointed at by the pWhere and pChanges
630 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000631 */
danielk1977633ed082002-05-17 00:05:58 +0000632void sqliteViewTriggers(
633 Parse *pParse,
634 Table *pTab, /* The view to code triggers on */
635 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
636 int orconf, /* The ON CONFLICT policy specified as part of the
637 statement causing these triggers */
638 ExprList *pChanges /* If this is an statement causing triggers to fire
639 is an UPDATE, then this list holds the columns
640 to update and the expressions to update them to.
641 See comments for sqliteUpdate(). */
642){
danielk1977c3f9bad2002-05-15 08:30:12 +0000643 int oldIdx = -1;
644 int newIdx = -1;
645 int *aXRef = 0;
646 Vdbe *v;
647 int endOfLoop;
648 int startOfLoop;
649 Select theSelect;
650 Token tblNameToken;
651
652 assert(pTab->pSelect);
653
654 tblNameToken.z = pTab->zName;
655 tblNameToken.n = strlen(pTab->zName);
656
657 theSelect.isDistinct = 0;
658 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drhad3cab52002-05-24 02:04:32 +0000659 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken);
danielk1977c3f9bad2002-05-15 08:30:12 +0000660 theSelect.pWhere = pWhere; pWhere = 0;
661 theSelect.pGroupBy = 0;
662 theSelect.pHaving = 0;
663 theSelect.pOrderBy = 0;
664 theSelect.op = TK_SELECT; /* ?? */
665 theSelect.pPrior = 0;
666 theSelect.nLimit = -1;
667 theSelect.nOffset = -1;
668 theSelect.zSelect = 0;
669 theSelect.base = 0;
670
671 v = sqliteGetVdbe(pParse);
672 assert(v);
drhc977f7f2002-05-21 11:38:11 +0000673 sqliteBeginWriteOperation(pParse, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000674
675 /* Allocate temp tables */
676 oldIdx = pParse->nTab++;
677 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000678 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000679 newIdx = pParse->nTab++;
680 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
681 }
682
683 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000684 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000685 goto trigger_cleanup;
686 }
687
688 /* loop thru the view snapshot, executing triggers for each row */
689 endOfLoop = sqliteVdbeMakeLabel(v);
690 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
691
692 /* Loop thru the view snapshot, executing triggers for each row */
693 startOfLoop = sqliteVdbeCurrentAddr(v);
694
695 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000696 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000697 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000698
699 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
700 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000701 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000702 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000703 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000704
705 for(ii=0; ii<pChanges->nExpr; ii++){
706 int jj;
707 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000708 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000709 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000710 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000711
712 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000713 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000714
715 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000716 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
717 aXRef[jj] = ii;
718 break;
719 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000720 }
721 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000722 sqliteSetString(&pParse->zErrMsg, "no such column: ",
723 pChanges->a[ii].zName, 0);
724 pParse->nErr++;
725 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000726 }
727 }
728
729 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
730
danielk1977633ed082002-05-17 00:05:58 +0000731 for(ii = 0; ii<pTab->nCol; ii++){
732 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000733 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000734 }else{
drh9adf9ac2002-05-15 11:44:13 +0000735 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000736 }
737 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000738
739 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
740 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
741 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
742
743 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000744 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000745 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000746 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000747 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000748 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000749 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000750 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000751 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000752 }
753
754 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
755
756 sqliteVdbeResolveLabel(v, endOfLoop);
757 sqliteEndWriteOperation(pParse);
758
759trigger_cleanup:
760 sqliteFree(aXRef);
761 sqliteExprListDelete(pChanges);
762 sqliteExprDelete(pWhere);
763 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000764 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000765 sqliteExprDelete(theSelect.pWhere);
766 return;
767}