blob: 53eff0c41d0ed94855f5b1153a7a0a8ffb0aab3e [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 }
drhe0bc4042002-06-25 01:09:11 +000073 if( sqliteStrICmp(tab->zName, TEMP_MASTER_NAME)==0 ){
74 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
75 "table: " TEMP_MASTER_NAME, 0);
76 pParse->nErr++;
77 goto trigger_cleanup;
78 }
danielk1977d702fcc2002-05-26 23:24:40 +000079 if( tab->pSelect && tr_tm != TK_INSTEAD ){
80 sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
81 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
82 , pTableName->z, pTableName->n, 0);
83 goto trigger_cleanup;
84 }
85 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
86 sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1,
87 " trigger on table: ", -1, pTableName->z, pTableName->n, 0);
88 goto trigger_cleanup;
89 }
90 }
91
92 if (tr_tm == TK_INSTEAD){
93 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +000094 }
95
96 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +000097 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +000098 if( nt==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +000099 nt->name = sqliteStrNDup(pName->z, pName->n);
100 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +0000101 nt->strings = sqliteStrNDup(zData, zDataLen);
102 if( sqlite_malloc_failed ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000103 nt->op = op;
104 nt->tr_tm = tr_tm;
105 nt->pWhen = pWhen;
danielk1977633ed082002-05-17 00:05:58 +0000106 nt->pColumns = pColumns;
danielk1977c3f9bad2002-05-15 08:30:12 +0000107 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000108 nt->step_list = pStepList;
danielk1977633ed082002-05-17 00:05:58 +0000109 offset = (int)(nt->strings - zData);
danielk1977c3f9bad2002-05-15 08:30:12 +0000110 sqliteExprMoveStrings(nt->pWhen, offset);
111
112 ss = nt->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000113 while( ss ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000114 sqliteSelectMoveStrings(ss->pSelect, offset);
danielk1977f29ce552002-05-19 23:43:12 +0000115 if( ss->target.z ){
116 ss->target.z += offset;
117 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000118 sqliteExprMoveStrings(ss->pWhere, offset);
119 sqliteExprListMoveStrings(ss->pExprList, offset);
120
121 ss = ss->pNext;
122 }
123
124 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000125 ** build the sqlite_master entry
126 */
drhe0bc4042002-06-25 01:09:11 +0000127 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000128 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000129 { OP_NewRecno, 0, 0, 0 },
130 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000131 { OP_String, 0, 0, 0 }, /* 2: trigger name */
132 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000133 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000134 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000135 { OP_MakeRecord, 5, 0, 0 },
136 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000137 };
138 int addr;
139 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000140
141 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000142 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000143 if( v==0 ) goto trigger_cleanup;
drhc977f7f2002-05-21 11:38:11 +0000144 sqliteBeginWriteOperation(pParse, 0);
drhe0bc4042002-06-25 01:09:11 +0000145 sqliteOpenMasterTable(v, tab->isTemp);
drhc977f7f2002-05-21 11:38:11 +0000146 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhe0bc4042002-06-25 01:09:11 +0000147 sqliteVdbeChangeP3(v, addr, tab->isTemp ? TEMP_MASTER_NAME : MASTER_NAME,
148 P3_STATIC);
149 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
150 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
151 sqliteVdbeChangeP3(v, addr+5, nt->strings, 0);
152 if( !tab->isTemp ){
153 sqliteChangeCookie(pParse->db, v);
154 }
155 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000156 sqliteEndWriteOperation(pParse);
157 }
158
danielk1977633ed082002-05-17 00:05:58 +0000159 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000160 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000161 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000162
163 /* Attach it to the table object */
164 nt->pNext = tab->pTrigger;
165 tab->pTrigger = nt;
166 return;
danielk1977f29ce552002-05-19 23:43:12 +0000167 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000168 sqliteFree(nt->strings);
169 sqliteFree(nt->name);
170 sqliteFree(nt->table);
171 sqliteFree(nt);
172 }
173
174trigger_cleanup:
175
danielk1977633ed082002-05-17 00:05:58 +0000176 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000177 sqliteExprDelete(pWhen);
178 {
179 TriggerStep * pp;
180 TriggerStep * nn;
181
danielk1977633ed082002-05-17 00:05:58 +0000182 pp = pStepList;
danielk1977f29ce552002-05-19 23:43:12 +0000183 while( pp ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000184 nn = pp->pNext;
185 sqliteExprDelete(pp->pWhere);
186 sqliteExprListDelete(pp->pExprList);
187 sqliteSelectDelete(pp->pSelect);
188 sqliteIdListDelete(pp->pIdList);
189 sqliteFree(pp);
190 pp = nn;
191 }
192 }
193}
194
drhc977f7f2002-05-21 11:38:11 +0000195/*
196** Turn a SELECT statement (that the pSelect parameter points to) into
197** a trigger step. Return a pointer to a TriggerStep structure.
198**
199** The parser calls this routine when it finds a SELECT statement in
200** body of a TRIGGER.
201*/
202TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000203 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000204 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000205
danielk1977633ed082002-05-17 00:05:58 +0000206 pTriggerStep->op = TK_SELECT;
207 pTriggerStep->pSelect = pSelect;
208 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000209
danielk1977633ed082002-05-17 00:05:58 +0000210 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000211}
212
drhc977f7f2002-05-21 11:38:11 +0000213/*
214** Build a trigger step out of an INSERT statement. Return a pointer
215** to the new trigger step.
216**
217** The parser calls this routine when it sees an INSERT inside the
218** body of a trigger.
219*/
danielk1977633ed082002-05-17 00:05:58 +0000220TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000221 Token *pTableName, /* Name of the table into which we insert */
222 IdList *pColumn, /* List of columns in pTableName to insert into */
223 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
224 Select *pSelect, /* A SELECT statement that supplies values */
225 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000226){
227 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000228 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000229
danielk1977633ed082002-05-17 00:05:58 +0000230 assert(pEList == 0 || pSelect == 0);
231 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000232
danielk1977633ed082002-05-17 00:05:58 +0000233 pTriggerStep->op = TK_INSERT;
234 pTriggerStep->pSelect = pSelect;
235 pTriggerStep->target = *pTableName;
236 pTriggerStep->pIdList = pColumn;
237 pTriggerStep->pExprList = pEList;
238 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000239
danielk1977633ed082002-05-17 00:05:58 +0000240 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000241}
242
drhc977f7f2002-05-21 11:38:11 +0000243/*
244** Construct a trigger step that implements an UPDATE statement and return
245** a pointer to that trigger step. The parser calls this routine when it
246** sees an UPDATE statement inside the body of a CREATE TRIGGER.
247*/
danielk1977633ed082002-05-17 00:05:58 +0000248TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000249 Token *pTableName, /* Name of the table to be updated */
250 ExprList *pEList, /* The SET clause: list of column and new values */
251 Expr *pWhere, /* The WHERE clause */
252 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
253){
danielk1977633ed082002-05-17 00:05:58 +0000254 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000255 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000256
danielk1977633ed082002-05-17 00:05:58 +0000257 pTriggerStep->op = TK_UPDATE;
258 pTriggerStep->target = *pTableName;
259 pTriggerStep->pExprList = pEList;
260 pTriggerStep->pWhere = pWhere;
261 pTriggerStep->orconf = orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000262
danielk1977633ed082002-05-17 00:05:58 +0000263 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000264}
265
drhc977f7f2002-05-21 11:38:11 +0000266/*
267** Construct a trigger step that implements a DELETE statement and return
268** a pointer to that trigger step. The parser calls this routine when it
269** sees a DELETE statement inside the body of a CREATE TRIGGER.
270*/
271TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000272 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
273 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000274
danielk1977633ed082002-05-17 00:05:58 +0000275 pTriggerStep->op = TK_DELETE;
276 pTriggerStep->target = *pTableName;
277 pTriggerStep->pWhere = pWhere;
278 pTriggerStep->orconf = OE_Default;
danielk1977c3f9bad2002-05-15 08:30:12 +0000279
danielk1977633ed082002-05-17 00:05:58 +0000280 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000281}
282
danielk1977633ed082002-05-17 00:05:58 +0000283/*
284** Recursively delete a Trigger structure
285*/
drh1d1f3052002-05-21 13:18:25 +0000286void sqliteDeleteTrigger(Trigger *pTrigger){
danielk1977633ed082002-05-17 00:05:58 +0000287 TriggerStep *pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000288
danielk1977633ed082002-05-17 00:05:58 +0000289 pTriggerStep = pTrigger->step_list;
danielk1977f29ce552002-05-19 23:43:12 +0000290 while( pTriggerStep ){
danielk1977633ed082002-05-17 00:05:58 +0000291 TriggerStep * pTmp = pTriggerStep;
292 pTriggerStep = pTriggerStep->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000293
danielk1977633ed082002-05-17 00:05:58 +0000294 sqliteExprDelete(pTmp->pWhere);
295 sqliteExprListDelete(pTmp->pExprList);
296 sqliteSelectDelete(pTmp->pSelect);
297 sqliteIdListDelete(pTmp->pIdList);
danielk1977c3f9bad2002-05-15 08:30:12 +0000298
danielk1977633ed082002-05-17 00:05:58 +0000299 sqliteFree(pTmp);
danielk1977c3f9bad2002-05-15 08:30:12 +0000300 }
301
danielk1977633ed082002-05-17 00:05:58 +0000302 sqliteFree(pTrigger->name);
303 sqliteFree(pTrigger->table);
304 sqliteExprDelete(pTrigger->pWhen);
305 sqliteIdListDelete(pTrigger->pColumns);
306 sqliteFree(pTrigger->strings);
307 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000308}
309
310/*
danielk1977633ed082002-05-17 00:05:58 +0000311 * This function is called to drop a trigger from the database schema.
312 *
313 * This may be called directly from the parser, or from within
314 * sqliteDropTable(). In the latter case the "nested" argument is true.
315 *
316 * Note that this function does not delete the trigger entirely. Instead it
317 * removes it from the internal schema and places it in the trigDrop hash
318 * table. This is so that the trigger can be restored into the database schema
319 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000320 */
drhe0bc4042002-06-25 01:09:11 +0000321void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000322 char *zName;
323 Trigger *pTrigger;
324 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000325 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000326
danielk1977633ed082002-05-17 00:05:58 +0000327 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000328
329 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000330 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
331 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000332 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000333 zName, -1, 0);
334 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000335 return;
336 }
337
338 /*
drhe0bc4042002-06-25 01:09:11 +0000339 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000340 */
danielk1977633ed082002-05-17 00:05:58 +0000341 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000342 pTable = sqliteFindTable(pParse->db, pTrigger->table);
343 assert(pTable);
344 if( pTable->pTrigger == pTrigger ){
345 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000346 }else{
danielk1977633ed082002-05-17 00:05:58 +0000347 Trigger *cc = pTable->pTrigger;
348 while( cc ){
349 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000350 cc->pNext = cc->pNext->pNext;
351 break;
352 }
353 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000354 }
355 assert(cc);
356 }
drhe0bc4042002-06-25 01:09:11 +0000357 sqliteHashInsert(&(pParse->db->trigHash), zName, pName->n + 1, NULL);
358 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000359 }
360
drhe0bc4042002-06-25 01:09:11 +0000361 /* Generate code to destroy the database record of the trigger.
362 */
363 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000364 int base;
365 static VdbeOp dropTrigger[] = {
drhe0bc4042002-06-25 01:09:11 +0000366 { OP_Rewind, 0, ADDR(8), 0},
367 { OP_String, 0, 0, 0}, /* 1 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000368 { OP_MemStore, 1, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000369 { OP_MemLoad, 1, 0, 0}, /* 3 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000370 { OP_Column, 0, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000371 { OP_Ne, 0, ADDR(7), 0},
danielk1977c3f9bad2002-05-15 08:30:12 +0000372 { OP_Delete, 0, 0, 0},
drhe0bc4042002-06-25 01:09:11 +0000373 { OP_Next, 0, ADDR(3), 0}, /* 7 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000374 };
375
drhe0bc4042002-06-25 01:09:11 +0000376 sqliteBeginWriteOperation(pParse, 0);
377 sqliteOpenMasterTable(v, pTable->isTemp);
378 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
379 sqliteVdbeChangeP3(v, base+1, zName, 0);
380 if( !pTable->isTemp ){
381 sqliteChangeCookie(pParse->db, v);
drhdc379452002-05-15 12:45:43 +0000382 }
drhe0bc4042002-06-25 01:09:11 +0000383 sqliteVdbeAddOp(v, OP_Close, 0, 0);
384 sqliteEndWriteOperation(pParse);
danielk1977c3f9bad2002-05-15 08:30:12 +0000385 }
386
danielk1977633ed082002-05-17 00:05:58 +0000387 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000388}
389
drhc977f7f2002-05-21 11:38:11 +0000390/*
391** pEList is the SET clause of an UPDATE statement. Each entry
392** in pEList is of the format <id>=<expr>. If any of the entries
393** in pEList have an <id> which matches an identifier in pIdList,
394** then return TRUE. If pIdList==NULL, then it is considered a
395** wildcard that matches anything. Likewise if pEList==NULL then
396** it matches anything so always return true. Return false only
397** if there is no match.
398*/
399static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000400 int e;
401 if( !pIdList || !pEList ) return 1;
402 for(e=0; e<pEList->nExpr; e++){
403 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000404 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000405 return 0;
406}
407
408/* A global variable that is TRUE if we should always set up temp tables for
409 * for triggers, even if there are no triggers to code. This is used to test
410 * how much overhead the triggers algorithm is causing.
411 *
412 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
413 * The pragma is not documented since it is not really part of the interface
414 * to SQLite, just the test procedure.
415*/
416int always_code_trigger_setup = 0;
417
418/*
419 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
420 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
421 * found in the list specified as pTrigger.
422 */
423int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000424 Parse *pParse, /* Used to check for recursive triggers */
425 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000426 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
427 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
428 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000429 ExprList *pChanges /* Columns that change in an UPDATE statement */
430){
danielk1977633ed082002-05-17 00:05:58 +0000431 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000432
danielk1977633ed082002-05-17 00:05:58 +0000433 if( always_code_trigger_setup ){
434 return 1;
435 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000436
danielk1977633ed082002-05-17 00:05:58 +0000437 pTriggerCursor = pTrigger;
438 while( pTriggerCursor ){
439 if( pTriggerCursor->op == op &&
440 pTriggerCursor->tr_tm == tr_tm &&
441 pTriggerCursor->foreach == foreach &&
442 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000443 TriggerStack * ss;
444 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000445 while( ss && ss->pTrigger != pTrigger ){
446 ss = ss->pNext;
447 }
448 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000449 }
danielk1977633ed082002-05-17 00:05:58 +0000450 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000451 }
452
453 return 0;
454}
455
drhc977f7f2002-05-21 11:38:11 +0000456/*
457** Generate VDBE code for zero or more statements inside the body of a
458** trigger.
459*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000460static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000461 Parse *pParse, /* The parser context */
462 TriggerStep *pStepList, /* List of statements inside the trigger body */
463 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000464){
465 TriggerStep * pTriggerStep = pStepList;
466 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000467
danielk1977633ed082002-05-17 00:05:58 +0000468 while( pTriggerStep ){
469 int saveNTab = pParse->nTab;
470 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
471 pParse->trigStack->orconf = orconf;
472 switch( pTriggerStep->op ){
473 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000474 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
475 assert(ss);
476 assert(ss->pSrc);
477 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
478 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000479 break;
480 }
481 case TK_UPDATE: {
drhbd5a4512002-05-23 22:07:02 +0000482 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000483 sqliteUpdate(pParse, &pTriggerStep->target,
danielk19776f349032002-06-11 02:25:40 +0000484 sqliteExprListDup(pTriggerStep->pExprList),
485 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000486 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000487 break;
488 }
489 case TK_INSERT: {
490 sqliteInsert(pParse, &pTriggerStep->target,
491 sqliteExprListDup(pTriggerStep->pExprList),
492 sqliteSelectDup(pTriggerStep->pSelect),
493 sqliteIdListDup(pTriggerStep->pIdList), orconf);
494 break;
495 }
496 case TK_DELETE: {
drhbd5a4512002-05-23 22:07:02 +0000497 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000498 sqliteDeleteFrom(pParse, &pTriggerStep->target,
499 sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000500 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000501 break;
502 }
503 default:
504 assert(0);
505 }
506 pParse->nTab = saveNTab;
507 pTriggerStep = pTriggerStep->pNext;
508 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000509
danielk1977633ed082002-05-17 00:05:58 +0000510 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000511}
512
danielk1977633ed082002-05-17 00:05:58 +0000513/*
514** This is called to code FOR EACH ROW triggers.
515**
516** When the code that this function generates is executed, the following
517** must be true:
drhc977f7f2002-05-21 11:38:11 +0000518**
519** 1. No cursors may be open in the main database. (But newIdx and oldIdx
520** can be indices of cursors in temporary tables. See below.)
521**
danielk1977633ed082002-05-17 00:05:58 +0000522** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
523** a temporary vdbe cursor (index newIdx) must be open and pointing at
524** a row containing values to be substituted for new.* expressions in the
525** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000526**
danielk1977633ed082002-05-17 00:05:58 +0000527** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
528** a temporary vdbe cursor (index oldIdx) must be open and pointing at
529** a row containing values to be substituted for old.* expressions in the
530** trigger program(s).
531**
532*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000533int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000534 Parse *pParse, /* Parse context */
535 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
536 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
537 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
538 Table *pTab, /* The table to code triggers from */
539 int newIdx, /* The indice of the "new" row to access */
540 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000541 int orconf, /* ON CONFLICT policy */
542 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000543){
danielk1977c3f9bad2002-05-15 08:30:12 +0000544 Trigger * pTrigger;
545 TriggerStack * pTriggerStack;
546
danielk1977c3f9bad2002-05-15 08:30:12 +0000547 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
548 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
549
danielk1977633ed082002-05-17 00:05:58 +0000550 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000551
danielk1977633ed082002-05-17 00:05:58 +0000552 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000553 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000554 int fire_this = 0;
555
556 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000557 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
558 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000559 fire_this = 1;
560 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000561 while( pTriggerStack ){
562 if( pTriggerStack->pTrigger == pTrigger ){
563 fire_this = 0;
564 }
drh9adf9ac2002-05-15 11:44:13 +0000565 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000566 }
danielk1977f29ce552002-05-19 23:43:12 +0000567 if( op == TK_UPDATE && pTrigger->pColumns &&
568 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000569 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000570 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000571 }
572
drhe4697f52002-05-23 02:09:03 +0000573 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000574 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000575 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000576 Expr * whenExpr;
577
drhad3cab52002-05-24 02:04:32 +0000578 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000579 dummyTablist.a = 0;
580
581 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000582 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000583 pTriggerStack->newIdx = newIdx;
584 pTriggerStack->oldIdx = oldIdx;
585 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000586 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000587 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000588 pParse->trigStack = pTriggerStack;
589
590 /* code the WHEN clause */
591 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
592 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000593 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000594 pParse->trigStack = pParse->trigStack->pNext;
595 sqliteFree(pTriggerStack);
596 sqliteExprDelete(whenExpr);
597 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000598 }
drhf5905aa2002-05-26 20:54:33 +0000599 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000600 sqliteExprDelete(whenExpr);
601
danielk1977633ed082002-05-17 00:05:58 +0000602 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000603
604 /* Pop the entry off the trigger stack */
605 pParse->trigStack = pParse->trigStack->pNext;
606 sqliteFree(pTriggerStack);
607
608 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
609 }
610 pTrigger = pTrigger->pNext;
611 }
612
613 return 0;
614}
615
616/*
danielk1977633ed082002-05-17 00:05:58 +0000617 * This function is called to code ON UPDATE and ON DELETE triggers on
618 * views.
619 *
620 * This function deletes the data pointed at by the pWhere and pChanges
621 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000622 */
danielk1977633ed082002-05-17 00:05:58 +0000623void sqliteViewTriggers(
624 Parse *pParse,
625 Table *pTab, /* The view to code triggers on */
626 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
627 int orconf, /* The ON CONFLICT policy specified as part of the
628 statement causing these triggers */
629 ExprList *pChanges /* If this is an statement causing triggers to fire
630 is an UPDATE, then this list holds the columns
631 to update and the expressions to update them to.
632 See comments for sqliteUpdate(). */
633){
danielk1977c3f9bad2002-05-15 08:30:12 +0000634 int oldIdx = -1;
635 int newIdx = -1;
636 int *aXRef = 0;
637 Vdbe *v;
638 int endOfLoop;
639 int startOfLoop;
640 Select theSelect;
641 Token tblNameToken;
642
643 assert(pTab->pSelect);
644
645 tblNameToken.z = pTab->zName;
646 tblNameToken.n = strlen(pTab->zName);
647
648 theSelect.isDistinct = 0;
649 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drhad3cab52002-05-24 02:04:32 +0000650 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken);
danielk1977c3f9bad2002-05-15 08:30:12 +0000651 theSelect.pWhere = pWhere; pWhere = 0;
652 theSelect.pGroupBy = 0;
653 theSelect.pHaving = 0;
654 theSelect.pOrderBy = 0;
655 theSelect.op = TK_SELECT; /* ?? */
656 theSelect.pPrior = 0;
657 theSelect.nLimit = -1;
658 theSelect.nOffset = -1;
659 theSelect.zSelect = 0;
660 theSelect.base = 0;
661
662 v = sqliteGetVdbe(pParse);
663 assert(v);
drhc977f7f2002-05-21 11:38:11 +0000664 sqliteBeginWriteOperation(pParse, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000665
666 /* Allocate temp tables */
667 oldIdx = pParse->nTab++;
668 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000669 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000670 newIdx = pParse->nTab++;
671 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
672 }
673
674 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000675 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000676 goto trigger_cleanup;
677 }
678
679 /* loop thru the view snapshot, executing triggers for each row */
680 endOfLoop = sqliteVdbeMakeLabel(v);
681 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
682
683 /* Loop thru the view snapshot, executing triggers for each row */
684 startOfLoop = sqliteVdbeCurrentAddr(v);
685
686 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000687 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000688 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000689
690 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
691 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000692 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000693 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000694 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000695
696 for(ii=0; ii<pChanges->nExpr; ii++){
697 int jj;
698 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000699 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000700 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000701 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000702
703 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000704 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000705
706 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000707 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
708 aXRef[jj] = ii;
709 break;
710 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000711 }
712 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000713 sqliteSetString(&pParse->zErrMsg, "no such column: ",
714 pChanges->a[ii].zName, 0);
715 pParse->nErr++;
716 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000717 }
718 }
719
720 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
721
danielk1977633ed082002-05-17 00:05:58 +0000722 for(ii = 0; ii<pTab->nCol; ii++){
723 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000724 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000725 }else{
drh9adf9ac2002-05-15 11:44:13 +0000726 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000727 }
728 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000729
730 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
731 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
732 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
733
734 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000735 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000736 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000737 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000738 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000739 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000740 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000741 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000742 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000743 }
744
745 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
746
747 sqliteVdbeResolveLabel(v, endOfLoop);
748 sqliteEndWriteOperation(pParse);
749
750trigger_cleanup:
751 sqliteFree(aXRef);
752 sqliteExprListDelete(pChanges);
753 sqliteExprDelete(pWhere);
754 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000755 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000756 sqliteExprDelete(theSelect.pWhere);
757 return;
758}