blob: 222d09de0d5bbe80127a01042fd57e7b45642a70 [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/*
drh4b59ab52002-08-24 18:24:51 +000016** Delete a linked list of TriggerStep structures.
17*/
18static void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
19 while( pTriggerStep ){
20 TriggerStep * pTmp = pTriggerStep;
21 pTriggerStep = pTriggerStep->pNext;
22
drh8c74a8c2002-08-25 19:20:40 +000023 if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
drh4b59ab52002-08-24 18:24:51 +000024 sqliteExprDelete(pTmp->pWhere);
25 sqliteExprListDelete(pTmp->pExprList);
26 sqliteSelectDelete(pTmp->pSelect);
27 sqliteIdListDelete(pTmp->pIdList);
28
29 sqliteFree(pTmp);
30 }
31}
32
33/*
danielk1977633ed082002-05-17 00:05:58 +000034** This is called by the parser when it sees a CREATE TRIGGER statement. See
35** comments surrounding struct Trigger in sqliteInt.h for a description of
36** how triggers are stored.
drh9adf9ac2002-05-15 11:44:13 +000037*/
38void sqliteCreateTrigger(
39 Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
danielk1977633ed082002-05-17 00:05:58 +000040 Token *pName, /* The name of the trigger */
danielk1977d702fcc2002-05-26 23:24:40 +000041 int tr_tm, /* One of TK_BEFORE, TK_AFTER , TK_INSTEAD */
drh9adf9ac2002-05-15 11:44:13 +000042 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
danielk1977633ed082002-05-17 00:05:58 +000043 IdList *pColumns, /* column list if this is an UPDATE OF trigger */
44 Token *pTableName, /* The name of the table/view the trigger applies to */
drh9adf9ac2002-05-15 11:44:13 +000045 int foreach, /* One of TK_ROW or TK_STATEMENT */
46 Expr *pWhen, /* WHEN clause */
danielk1977633ed082002-05-17 00:05:58 +000047 TriggerStep *pStepList, /* The triggered program */
drh4b59ab52002-08-24 18:24:51 +000048 Token *pAll /* Token that describes the complete CREATE TRIGGER */
drh9adf9ac2002-05-15 11:44:13 +000049){
50 Trigger *nt;
51 Table *tab;
danielk1977c3f9bad2002-05-15 08:30:12 +000052
53 /* Check that:
drh9adf9ac2002-05-15 11:44:13 +000054 ** 1. the trigger name does not already exist.
55 ** 2. the table (or view) does exist.
danielk1977d702fcc2002-05-26 23:24:40 +000056 ** 3. that we are not trying to create a trigger on the sqlite_master table
57 ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
58 ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
drh9adf9ac2002-05-15 11:44:13 +000059 */
danielk1977c3f9bad2002-05-15 08:30:12 +000060 {
danielk1977633ed082002-05-17 00:05:58 +000061 char *tmp_str = sqliteStrNDup(pName->z, pName->n);
62 if( sqliteHashFind(&(pParse->db->trigHash), tmp_str, pName->n + 1) ){
danielk1977c3f9bad2002-05-15 08:30:12 +000063 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
danielk1977633ed082002-05-17 00:05:58 +000064 pName->z, pName->n, " already exists", -1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000065 sqliteFree(tmp_str);
66 pParse->nErr++;
67 goto trigger_cleanup;
68 }
69 sqliteFree(tmp_str);
70 }
71 {
danielk1977633ed082002-05-17 00:05:58 +000072 char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +000073 if( tmp_str==0 ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000074 tab = sqliteFindTable(pParse->db, tmp_str);
75 sqliteFree(tmp_str);
drh9adf9ac2002-05-15 11:44:13 +000076 if( !tab ){
danielk1977c3f9bad2002-05-15 08:30:12 +000077 sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
danielk1977633ed082002-05-17 00:05:58 +000078 pTableName->z, pTableName->n, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +000079 pParse->nErr++;
80 goto trigger_cleanup;
81 }
drh1873cd52002-05-23 00:30:31 +000082 if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
83 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
84 "table: " MASTER_NAME, 0);
85 pParse->nErr++;
86 goto trigger_cleanup;
87 }
drhe0bc4042002-06-25 01:09:11 +000088 if( sqliteStrICmp(tab->zName, TEMP_MASTER_NAME)==0 ){
89 sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
90 "table: " TEMP_MASTER_NAME, 0);
91 pParse->nErr++;
92 goto trigger_cleanup;
93 }
danielk1977d702fcc2002-05-26 23:24:40 +000094 if( tab->pSelect && tr_tm != TK_INSTEAD ){
95 sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
96 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
97 , pTableName->z, pTableName->n, 0);
98 goto trigger_cleanup;
99 }
100 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
101 sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1,
102 " trigger on table: ", -1, pTableName->z, pTableName->n, 0);
103 goto trigger_cleanup;
104 }
105 }
106
107 if (tr_tm == TK_INSTEAD){
108 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +0000109 }
110
111 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +0000112 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +0000113 if( nt==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000114 nt->name = sqliteStrNDup(pName->z, pName->n);
115 nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
drhe4697f52002-05-23 02:09:03 +0000116 if( sqlite_malloc_failed ) goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000117 nt->op = op;
118 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000119 nt->pWhen = sqliteExprDup(pWhen);
120 sqliteExprDelete(pWhen);
121 nt->pColumns = sqliteIdListDup(pColumns);
122 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000123 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000124 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000125
126 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000127 ** build the sqlite_master entry
128 */
drhe0bc4042002-06-25 01:09:11 +0000129 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000130 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000131 { OP_NewRecno, 0, 0, 0 },
132 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000133 { OP_String, 0, 0, 0 }, /* 2: trigger name */
134 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000135 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000136 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000137 { OP_MakeRecord, 5, 0, 0 },
138 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000139 };
140 int addr;
141 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000142
143 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000144 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000145 if( v==0 ) goto trigger_cleanup;
drhcabb0812002-09-14 13:47:32 +0000146 sqliteBeginWriteOperation(pParse, 0, 0);
drhe0bc4042002-06-25 01:09:11 +0000147 sqliteOpenMasterTable(v, tab->isTemp);
drhc977f7f2002-05-21 11:38:11 +0000148 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhe0bc4042002-06-25 01:09:11 +0000149 sqliteVdbeChangeP3(v, addr, tab->isTemp ? TEMP_MASTER_NAME : MASTER_NAME,
150 P3_STATIC);
151 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
152 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000153 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhe0bc4042002-06-25 01:09:11 +0000154 if( !tab->isTemp ){
155 sqliteChangeCookie(pParse->db, v);
156 }
157 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000158 sqliteEndWriteOperation(pParse);
159 }
160
danielk1977633ed082002-05-17 00:05:58 +0000161 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000162 /* Stick it in the hash-table */
danielk1977633ed082002-05-17 00:05:58 +0000163 sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000164
165 /* Attach it to the table object */
166 nt->pNext = tab->pTrigger;
167 tab->pTrigger = nt;
168 return;
danielk1977f29ce552002-05-19 23:43:12 +0000169 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000170 sqliteFree(nt->name);
171 sqliteFree(nt->table);
172 sqliteFree(nt);
173 }
174
175trigger_cleanup:
176
danielk1977633ed082002-05-17 00:05:58 +0000177 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000178 sqliteExprDelete(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000179 sqliteDeleteTriggerStep(pStepList);
180}
danielk1977c3f9bad2002-05-15 08:30:12 +0000181
drh4b59ab52002-08-24 18:24:51 +0000182/*
183** Make a copy of all components of the given trigger step. This has
184** the effect of copying all Expr.token.z values into memory obtained
185** from sqliteMalloc(). As initially created, the Expr.token.z values
186** all point to the input string that was fed to the parser. But that
187** string is ephemeral - it will go away as soon as the sqlite_exec()
188** call that started the parser exits. This routine makes a persistent
189** copy of all the Expr.token.z strings so that the TriggerStep structure
190** will be valid even after the sqlite_exec() call returns.
191*/
192static void sqlitePersistTriggerStep(TriggerStep *p){
193 if( p->target.z ){
194 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
195 p->target.dyn = 1;
196 }
197 if( p->pSelect ){
198 Select *pNew = sqliteSelectDup(p->pSelect);
199 sqliteSelectDelete(p->pSelect);
200 p->pSelect = pNew;
201 }
202 if( p->pWhere ){
203 Expr *pNew = sqliteExprDup(p->pWhere);
204 sqliteExprDelete(p->pWhere);
205 p->pWhere = pNew;
206 }
207 if( p->pExprList ){
208 ExprList *pNew = sqliteExprListDup(p->pExprList);
209 sqliteExprListDelete(p->pExprList);
210 p->pExprList = pNew;
211 }
212 if( p->pIdList ){
213 IdList *pNew = sqliteIdListDup(p->pIdList);
214 sqliteIdListDelete(p->pIdList);
215 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000216 }
217}
218
drhc977f7f2002-05-21 11:38:11 +0000219/*
220** Turn a SELECT statement (that the pSelect parameter points to) into
221** a trigger step. Return a pointer to a TriggerStep structure.
222**
223** The parser calls this routine when it finds a SELECT statement in
224** body of a TRIGGER.
225*/
226TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000227 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 pTriggerStep->op = TK_SELECT;
231 pTriggerStep->pSelect = pSelect;
232 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000233 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000234
danielk1977633ed082002-05-17 00:05:58 +0000235 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000236}
237
drhc977f7f2002-05-21 11:38:11 +0000238/*
239** Build a trigger step out of an INSERT statement. Return a pointer
240** to the new trigger step.
241**
242** The parser calls this routine when it sees an INSERT inside the
243** body of a trigger.
244*/
danielk1977633ed082002-05-17 00:05:58 +0000245TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000246 Token *pTableName, /* Name of the table into which we insert */
247 IdList *pColumn, /* List of columns in pTableName to insert into */
248 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
249 Select *pSelect, /* A SELECT statement that supplies values */
250 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000251){
252 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000253 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000254
danielk1977633ed082002-05-17 00:05:58 +0000255 assert(pEList == 0 || pSelect == 0);
256 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000257
danielk1977633ed082002-05-17 00:05:58 +0000258 pTriggerStep->op = TK_INSERT;
259 pTriggerStep->pSelect = pSelect;
260 pTriggerStep->target = *pTableName;
261 pTriggerStep->pIdList = pColumn;
262 pTriggerStep->pExprList = pEList;
263 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000264 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000265
danielk1977633ed082002-05-17 00:05:58 +0000266 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000267}
268
drhc977f7f2002-05-21 11:38:11 +0000269/*
270** Construct a trigger step that implements an UPDATE statement and return
271** a pointer to that trigger step. The parser calls this routine when it
272** sees an UPDATE statement inside the body of a CREATE TRIGGER.
273*/
danielk1977633ed082002-05-17 00:05:58 +0000274TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000275 Token *pTableName, /* Name of the table to be updated */
276 ExprList *pEList, /* The SET clause: list of column and new values */
277 Expr *pWhere, /* The WHERE clause */
278 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
279){
danielk1977633ed082002-05-17 00:05:58 +0000280 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000281 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000282
danielk1977633ed082002-05-17 00:05:58 +0000283 pTriggerStep->op = TK_UPDATE;
284 pTriggerStep->target = *pTableName;
285 pTriggerStep->pExprList = pEList;
286 pTriggerStep->pWhere = pWhere;
287 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000288 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000289
danielk1977633ed082002-05-17 00:05:58 +0000290 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000291}
292
drhc977f7f2002-05-21 11:38:11 +0000293/*
294** Construct a trigger step that implements a DELETE statement and return
295** a pointer to that trigger step. The parser calls this routine when it
296** sees a DELETE statement inside the body of a CREATE TRIGGER.
297*/
298TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000299 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
300 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000301
danielk1977633ed082002-05-17 00:05:58 +0000302 pTriggerStep->op = TK_DELETE;
303 pTriggerStep->target = *pTableName;
304 pTriggerStep->pWhere = pWhere;
305 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000306 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000307
danielk1977633ed082002-05-17 00:05:58 +0000308 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000309}
310
danielk1977633ed082002-05-17 00:05:58 +0000311/*
312** Recursively delete a Trigger structure
313*/
drh1d1f3052002-05-21 13:18:25 +0000314void sqliteDeleteTrigger(Trigger *pTrigger){
drh4b59ab52002-08-24 18:24:51 +0000315 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000316 sqliteFree(pTrigger->name);
317 sqliteFree(pTrigger->table);
318 sqliteExprDelete(pTrigger->pWhen);
319 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000320 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000321}
322
323/*
danielk1977633ed082002-05-17 00:05:58 +0000324 * This function is called to drop a trigger from the database schema.
325 *
326 * This may be called directly from the parser, or from within
327 * sqliteDropTable(). In the latter case the "nested" argument is true.
328 *
329 * Note that this function does not delete the trigger entirely. Instead it
330 * removes it from the internal schema and places it in the trigDrop hash
331 * table. This is so that the trigger can be restored into the database schema
332 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000333 */
drhe0bc4042002-06-25 01:09:11 +0000334void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000335 char *zName;
336 Trigger *pTrigger;
337 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000338 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000339
danielk1977633ed082002-05-17 00:05:58 +0000340 zName = sqliteStrNDup(pName->z, pName->n);
danielk1977c3f9bad2002-05-15 08:30:12 +0000341
342 /* ensure that the trigger being dropped exists */
danielk1977633ed082002-05-17 00:05:58 +0000343 pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1);
344 if( !pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000345 sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
danielk1977633ed082002-05-17 00:05:58 +0000346 zName, -1, 0);
347 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000348 return;
349 }
350
351 /*
drhe0bc4042002-06-25 01:09:11 +0000352 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000353 */
danielk1977633ed082002-05-17 00:05:58 +0000354 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000355 pTable = sqliteFindTable(pParse->db, pTrigger->table);
356 assert(pTable);
357 if( pTable->pTrigger == pTrigger ){
358 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000359 }else{
danielk1977633ed082002-05-17 00:05:58 +0000360 Trigger *cc = pTable->pTrigger;
361 while( cc ){
362 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000363 cc->pNext = cc->pNext->pNext;
364 break;
365 }
366 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000367 }
368 assert(cc);
369 }
drhe0bc4042002-06-25 01:09:11 +0000370 sqliteHashInsert(&(pParse->db->trigHash), zName, pName->n + 1, NULL);
371 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000372 }
373
drhe0bc4042002-06-25 01:09:11 +0000374 /* Generate code to destroy the database record of the trigger.
375 */
376 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000377 int base;
378 static VdbeOp dropTrigger[] = {
drhe0bc4042002-06-25 01:09:11 +0000379 { OP_Rewind, 0, ADDR(8), 0},
380 { OP_String, 0, 0, 0}, /* 1 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000381 { OP_MemStore, 1, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000382 { OP_MemLoad, 1, 0, 0}, /* 3 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000383 { OP_Column, 0, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000384 { OP_Ne, 0, ADDR(7), 0},
danielk1977c3f9bad2002-05-15 08:30:12 +0000385 { OP_Delete, 0, 0, 0},
drhe0bc4042002-06-25 01:09:11 +0000386 { OP_Next, 0, ADDR(3), 0}, /* 7 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000387 };
388
drhcabb0812002-09-14 13:47:32 +0000389 sqliteBeginWriteOperation(pParse, 0, 0);
drhe0bc4042002-06-25 01:09:11 +0000390 sqliteOpenMasterTable(v, pTable->isTemp);
391 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
392 sqliteVdbeChangeP3(v, base+1, zName, 0);
393 if( !pTable->isTemp ){
394 sqliteChangeCookie(pParse->db, v);
drhdc379452002-05-15 12:45:43 +0000395 }
drhe0bc4042002-06-25 01:09:11 +0000396 sqliteVdbeAddOp(v, OP_Close, 0, 0);
397 sqliteEndWriteOperation(pParse);
danielk1977c3f9bad2002-05-15 08:30:12 +0000398 }
399
danielk1977633ed082002-05-17 00:05:58 +0000400 sqliteFree(zName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000401}
402
drhc977f7f2002-05-21 11:38:11 +0000403/*
404** pEList is the SET clause of an UPDATE statement. Each entry
405** in pEList is of the format <id>=<expr>. If any of the entries
406** in pEList have an <id> which matches an identifier in pIdList,
407** then return TRUE. If pIdList==NULL, then it is considered a
408** wildcard that matches anything. Likewise if pEList==NULL then
409** it matches anything so always return true. Return false only
410** if there is no match.
411*/
412static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000413 int e;
414 if( !pIdList || !pEList ) return 1;
415 for(e=0; e<pEList->nExpr; e++){
416 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000417 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000418 return 0;
419}
420
421/* A global variable that is TRUE if we should always set up temp tables for
422 * for triggers, even if there are no triggers to code. This is used to test
423 * how much overhead the triggers algorithm is causing.
424 *
425 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
426 * The pragma is not documented since it is not really part of the interface
427 * to SQLite, just the test procedure.
428*/
429int always_code_trigger_setup = 0;
430
431/*
432 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
433 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
434 * found in the list specified as pTrigger.
435 */
436int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000437 Parse *pParse, /* Used to check for recursive triggers */
438 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000439 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
440 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
441 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000442 ExprList *pChanges /* Columns that change in an UPDATE statement */
443){
danielk1977633ed082002-05-17 00:05:58 +0000444 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000445
danielk1977633ed082002-05-17 00:05:58 +0000446 if( always_code_trigger_setup ){
447 return 1;
448 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000449
danielk1977633ed082002-05-17 00:05:58 +0000450 pTriggerCursor = pTrigger;
451 while( pTriggerCursor ){
452 if( pTriggerCursor->op == op &&
453 pTriggerCursor->tr_tm == tr_tm &&
454 pTriggerCursor->foreach == foreach &&
455 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000456 TriggerStack * ss;
457 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000458 while( ss && ss->pTrigger != pTrigger ){
459 ss = ss->pNext;
460 }
461 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000462 }
danielk1977633ed082002-05-17 00:05:58 +0000463 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000464 }
465
466 return 0;
467}
468
drhc977f7f2002-05-21 11:38:11 +0000469/*
470** Generate VDBE code for zero or more statements inside the body of a
471** trigger.
472*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000473static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000474 Parse *pParse, /* The parser context */
475 TriggerStep *pStepList, /* List of statements inside the trigger body */
476 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000477){
478 TriggerStep * pTriggerStep = pStepList;
479 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000480
danielk1977633ed082002-05-17 00:05:58 +0000481 while( pTriggerStep ){
482 int saveNTab = pParse->nTab;
483 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
484 pParse->trigStack->orconf = orconf;
485 switch( pTriggerStep->op ){
486 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000487 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
488 assert(ss);
489 assert(ss->pSrc);
490 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
491 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000492 break;
493 }
494 case TK_UPDATE: {
drhbd5a4512002-05-23 22:07:02 +0000495 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000496 sqliteUpdate(pParse, &pTriggerStep->target,
danielk19776f349032002-06-11 02:25:40 +0000497 sqliteExprListDup(pTriggerStep->pExprList),
498 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000499 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000500 break;
501 }
502 case TK_INSERT: {
503 sqliteInsert(pParse, &pTriggerStep->target,
504 sqliteExprListDup(pTriggerStep->pExprList),
505 sqliteSelectDup(pTriggerStep->pSelect),
506 sqliteIdListDup(pTriggerStep->pIdList), orconf);
507 break;
508 }
509 case TK_DELETE: {
drhbd5a4512002-05-23 22:07:02 +0000510 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000511 sqliteDeleteFrom(pParse, &pTriggerStep->target,
512 sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000513 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000514 break;
515 }
516 default:
517 assert(0);
518 }
519 pParse->nTab = saveNTab;
520 pTriggerStep = pTriggerStep->pNext;
521 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000522
danielk1977633ed082002-05-17 00:05:58 +0000523 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000524}
525
danielk1977633ed082002-05-17 00:05:58 +0000526/*
527** This is called to code FOR EACH ROW triggers.
528**
529** When the code that this function generates is executed, the following
530** must be true:
drhc977f7f2002-05-21 11:38:11 +0000531**
532** 1. No cursors may be open in the main database. (But newIdx and oldIdx
533** can be indices of cursors in temporary tables. See below.)
534**
danielk1977633ed082002-05-17 00:05:58 +0000535** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
536** a temporary vdbe cursor (index newIdx) must be open and pointing at
537** a row containing values to be substituted for new.* expressions in the
538** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000539**
danielk1977633ed082002-05-17 00:05:58 +0000540** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
541** a temporary vdbe cursor (index oldIdx) must be open and pointing at
542** a row containing values to be substituted for old.* expressions in the
543** trigger program(s).
544**
545*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000546int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000547 Parse *pParse, /* Parse context */
548 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
549 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
550 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
551 Table *pTab, /* The table to code triggers from */
552 int newIdx, /* The indice of the "new" row to access */
553 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000554 int orconf, /* ON CONFLICT policy */
555 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000556){
danielk1977c3f9bad2002-05-15 08:30:12 +0000557 Trigger * pTrigger;
558 TriggerStack * pTriggerStack;
559
danielk1977c3f9bad2002-05-15 08:30:12 +0000560 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
561 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
562
danielk1977633ed082002-05-17 00:05:58 +0000563 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000564
danielk1977633ed082002-05-17 00:05:58 +0000565 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000566 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000567 int fire_this = 0;
568
569 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000570 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
571 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000572 fire_this = 1;
573 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000574 while( pTriggerStack ){
575 if( pTriggerStack->pTrigger == pTrigger ){
576 fire_this = 0;
577 }
drh9adf9ac2002-05-15 11:44:13 +0000578 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000579 }
danielk1977f29ce552002-05-19 23:43:12 +0000580 if( op == TK_UPDATE && pTrigger->pColumns &&
581 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000582 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000583 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000584 }
585
drhe4697f52002-05-23 02:09:03 +0000586 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000587 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000588 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000589 Expr * whenExpr;
590
drhad3cab52002-05-24 02:04:32 +0000591 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000592 dummyTablist.a = 0;
593
594 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000595 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000596 pTriggerStack->newIdx = newIdx;
597 pTriggerStack->oldIdx = oldIdx;
598 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000599 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000600 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000601 pParse->trigStack = pTriggerStack;
602
603 /* code the WHEN clause */
604 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
605 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000606 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000607 pParse->trigStack = pParse->trigStack->pNext;
608 sqliteFree(pTriggerStack);
609 sqliteExprDelete(whenExpr);
610 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000611 }
drhf5905aa2002-05-26 20:54:33 +0000612 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000613 sqliteExprDelete(whenExpr);
614
danielk1977633ed082002-05-17 00:05:58 +0000615 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000616
617 /* Pop the entry off the trigger stack */
618 pParse->trigStack = pParse->trigStack->pNext;
619 sqliteFree(pTriggerStack);
620
621 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
622 }
623 pTrigger = pTrigger->pNext;
624 }
625
626 return 0;
627}
628
629/*
danielk1977633ed082002-05-17 00:05:58 +0000630 * This function is called to code ON UPDATE and ON DELETE triggers on
631 * views.
632 *
633 * This function deletes the data pointed at by the pWhere and pChanges
634 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000635 */
danielk1977633ed082002-05-17 00:05:58 +0000636void sqliteViewTriggers(
637 Parse *pParse,
638 Table *pTab, /* The view to code triggers on */
639 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
640 int orconf, /* The ON CONFLICT policy specified as part of the
641 statement causing these triggers */
642 ExprList *pChanges /* If this is an statement causing triggers to fire
643 is an UPDATE, then this list holds the columns
644 to update and the expressions to update them to.
645 See comments for sqliteUpdate(). */
646){
danielk1977c3f9bad2002-05-15 08:30:12 +0000647 int oldIdx = -1;
648 int newIdx = -1;
649 int *aXRef = 0;
650 Vdbe *v;
651 int endOfLoop;
652 int startOfLoop;
653 Select theSelect;
654 Token tblNameToken;
655
656 assert(pTab->pSelect);
657
658 tblNameToken.z = pTab->zName;
659 tblNameToken.n = strlen(pTab->zName);
660
661 theSelect.isDistinct = 0;
662 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drhad3cab52002-05-24 02:04:32 +0000663 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken);
danielk1977c3f9bad2002-05-15 08:30:12 +0000664 theSelect.pWhere = pWhere; pWhere = 0;
665 theSelect.pGroupBy = 0;
666 theSelect.pHaving = 0;
667 theSelect.pOrderBy = 0;
668 theSelect.op = TK_SELECT; /* ?? */
669 theSelect.pPrior = 0;
670 theSelect.nLimit = -1;
671 theSelect.nOffset = -1;
672 theSelect.zSelect = 0;
673 theSelect.base = 0;
674
675 v = sqliteGetVdbe(pParse);
676 assert(v);
drhcabb0812002-09-14 13:47:32 +0000677 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000678
679 /* Allocate temp tables */
680 oldIdx = pParse->nTab++;
681 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000682 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000683 newIdx = pParse->nTab++;
684 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
685 }
686
687 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000688 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000689 goto trigger_cleanup;
690 }
691
692 /* loop thru the view snapshot, executing triggers for each row */
693 endOfLoop = sqliteVdbeMakeLabel(v);
694 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
695
696 /* Loop thru the view snapshot, executing triggers for each row */
697 startOfLoop = sqliteVdbeCurrentAddr(v);
698
699 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000700 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000701 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000702
703 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
704 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000705 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000706 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000707 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000708
709 for(ii=0; ii<pChanges->nExpr; ii++){
710 int jj;
711 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000712 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000713 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000714 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000715
716 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000717 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000718
719 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000720 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
721 aXRef[jj] = ii;
722 break;
723 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000724 }
725 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000726 sqliteSetString(&pParse->zErrMsg, "no such column: ",
727 pChanges->a[ii].zName, 0);
728 pParse->nErr++;
729 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000730 }
731 }
732
733 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
734
danielk1977633ed082002-05-17 00:05:58 +0000735 for(ii = 0; ii<pTab->nCol; ii++){
736 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000737 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000738 }else{
drh9adf9ac2002-05-15 11:44:13 +0000739 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000740 }
741 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000742
743 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
744 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
745 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
746
747 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000748 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000749 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000750 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000751 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000752 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000753 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000754 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000755 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000756 }
757
758 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
759
760 sqliteVdbeResolveLabel(v, endOfLoop);
761 sqliteEndWriteOperation(pParse);
762
763trigger_cleanup:
764 sqliteFree(aXRef);
765 sqliteExprListDelete(pChanges);
766 sqliteExprDelete(pWhere);
767 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000768 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000769 sqliteExprDelete(theSelect.pWhere);
770 return;
771}