blob: 7e48e4d5758a0626dbaf6fd1281dfb8927cc996c [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 */
drhd24cc422003-03-27 12:51:24 +000044 SrcList *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;
drhe5f9c642003-01-13 23:27:31 +000052 char *zName = 0; /* Name of the trigger */
drhd24cc422003-03-27 12:51:24 +000053 sqlite *db = pParse->db;
drhed6c8672003-01-12 18:02:16 +000054
danielk1977c3f9bad2002-05-15 08:30:12 +000055 /* Check that:
drh9adf9ac2002-05-15 11:44:13 +000056 ** 1. the trigger name does not already exist.
57 ** 2. the table (or view) does exist.
danielk1977d702fcc2002-05-26 23:24:40 +000058 ** 3. that we are not trying to create a trigger on the sqlite_master table
59 ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
60 ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
drh9adf9ac2002-05-15 11:44:13 +000061 */
drhd24cc422003-03-27 12:51:24 +000062 if( sqlite_malloc_failed ) goto trigger_cleanup;
63 assert( pTableName->nSrc==1 );
drh812d7a22003-03-27 13:50:00 +000064 tab = sqliteSrcListLookup(pParse, pTableName);
drhd24cc422003-03-27 12:51:24 +000065 if( !tab ){
66 goto trigger_cleanup;
67 }
68 if( tab->iDb>=2 ){
69 sqliteSetString(&pParse->zErrMsg, "triggers may not be added to "
70 "auxiliary database \"", db->aDb[tab->iDb].zName, "\"", 0);
71 pParse->nErr++;
72 goto trigger_cleanup;
73 }
74
drhe5f9c642003-01-13 23:27:31 +000075 zName = sqliteStrNDup(pName->z, pName->n);
drhd24cc422003-03-27 12:51:24 +000076 if( sqliteHashFind(&(db->aDb[tab->iDb].trigHash), zName,pName->n+1) ){
drhe5f9c642003-01-13 23:27:31 +000077 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
78 pName->z, pName->n, " already exists", -1, 0);
79 pParse->nErr++;
80 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000081 }
drhd24cc422003-03-27 12:51:24 +000082 if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
83 sqliteSetString(&pParse->zErrMsg,"cannot create trigger on system table",0);
84 pParse->nErr++;
85 goto trigger_cleanup;
danielk1977d702fcc2002-05-26 23:24:40 +000086 }
drhd24cc422003-03-27 12:51:24 +000087 if( tab->pSelect && tr_tm != TK_INSTEAD ){
drh0951d702003-03-27 13:01:28 +000088 sqliteSetString(&pParse->zErrMsg, "cannot create ",
drhd24cc422003-03-27 12:51:24 +000089 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", " trigger on view: ",
90 pTableName->a[0].zName, 0);
91 goto trigger_cleanup;
92 }
93 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
drh0951d702003-03-27 13:01:28 +000094 sqliteSetString(&pParse->zErrMsg, "cannot create INSTEAD OF",
95 " trigger on table: ", pTableName->a[0].zName, 0);
drhd24cc422003-03-27 12:51:24 +000096 goto trigger_cleanup;
97 }
98#ifndef SQLITE_OMIT_AUTHORIZATION
99 {
100 int code = SQLITE_CREATE_TRIGGER;
101 if( tab->iDb==1 ) code = SQLITE_CREATE_TEMP_TRIGGER;
102 if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
103 goto trigger_cleanup;
104 }
105 if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0)){
106 goto trigger_cleanup;
107 }
108 }
109#endif
danielk1977d702fcc2002-05-26 23:24:40 +0000110
111 if (tr_tm == TK_INSTEAD){
112 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +0000113 }
114
115 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +0000116 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +0000117 if( nt==0 ) goto trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000118 nt->name = zName;
119 zName = 0;
drhd24cc422003-03-27 12:51:24 +0000120 nt->table = sqliteStrDup(pTableName->a[0].zName);
drhe4697f52002-05-23 02:09:03 +0000121 if( sqlite_malloc_failed ) goto trigger_cleanup;
drhd24cc422003-03-27 12:51:24 +0000122 nt->iDb = tab->iDb;
danielk1977c3f9bad2002-05-15 08:30:12 +0000123 nt->op = op;
124 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000125 nt->pWhen = sqliteExprDup(pWhen);
126 sqliteExprDelete(pWhen);
127 nt->pColumns = sqliteIdListDup(pColumns);
128 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000129 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000130 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000131
132 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000133 ** build the sqlite_master entry
134 */
drhe0bc4042002-06-25 01:09:11 +0000135 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000136 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000137 { OP_NewRecno, 0, 0, 0 },
138 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000139 { OP_String, 0, 0, 0 }, /* 2: trigger name */
140 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000141 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000142 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000143 { OP_MakeRecord, 5, 0, 0 },
144 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000145 };
146 int addr;
147 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000148
149 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000150 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000151 if( v==0 ) goto trigger_cleanup;
drhcabb0812002-09-14 13:47:32 +0000152 sqliteBeginWriteOperation(pParse, 0, 0);
drhd24cc422003-03-27 12:51:24 +0000153 sqliteOpenMasterTable(v, tab->iDb);
drhc977f7f2002-05-21 11:38:11 +0000154 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhd24cc422003-03-27 12:51:24 +0000155 sqliteVdbeChangeP3(v, addr, tab->iDb ? TEMP_MASTER_NAME : MASTER_NAME,
drhe0bc4042002-06-25 01:09:11 +0000156 P3_STATIC);
157 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
158 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000159 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhd24cc422003-03-27 12:51:24 +0000160 if( tab->iDb==0 ){
161 sqliteChangeCookie(db, v);
drhe0bc4042002-06-25 01:09:11 +0000162 }
163 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000164 sqliteEndWriteOperation(pParse);
165 }
166
danielk1977633ed082002-05-17 00:05:58 +0000167 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000168 /* Stick it in the hash-table */
drhd24cc422003-03-27 12:51:24 +0000169 sqliteHashInsert(&(db->aDb[nt->iDb].trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000170
171 /* Attach it to the table object */
172 nt->pNext = tab->pTrigger;
173 tab->pTrigger = nt;
drh0be9df02003-03-30 00:19:49 +0000174 sqliteSrcListDelete(pTableName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000175 return;
danielk1977f29ce552002-05-19 23:43:12 +0000176 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000177 sqliteFree(nt->name);
178 sqliteFree(nt->table);
179 sqliteFree(nt);
180 }
181
182trigger_cleanup:
183
drhe5f9c642003-01-13 23:27:31 +0000184 sqliteFree(zName);
drhd24cc422003-03-27 12:51:24 +0000185 sqliteSrcListDelete(pTableName);
danielk1977633ed082002-05-17 00:05:58 +0000186 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000187 sqliteExprDelete(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000188 sqliteDeleteTriggerStep(pStepList);
189}
danielk1977c3f9bad2002-05-15 08:30:12 +0000190
drh4b59ab52002-08-24 18:24:51 +0000191/*
192** Make a copy of all components of the given trigger step. This has
193** the effect of copying all Expr.token.z values into memory obtained
194** from sqliteMalloc(). As initially created, the Expr.token.z values
195** all point to the input string that was fed to the parser. But that
196** string is ephemeral - it will go away as soon as the sqlite_exec()
197** call that started the parser exits. This routine makes a persistent
198** copy of all the Expr.token.z strings so that the TriggerStep structure
199** will be valid even after the sqlite_exec() call returns.
200*/
201static void sqlitePersistTriggerStep(TriggerStep *p){
202 if( p->target.z ){
203 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
204 p->target.dyn = 1;
205 }
206 if( p->pSelect ){
207 Select *pNew = sqliteSelectDup(p->pSelect);
208 sqliteSelectDelete(p->pSelect);
209 p->pSelect = pNew;
210 }
211 if( p->pWhere ){
212 Expr *pNew = sqliteExprDup(p->pWhere);
213 sqliteExprDelete(p->pWhere);
214 p->pWhere = pNew;
215 }
216 if( p->pExprList ){
217 ExprList *pNew = sqliteExprListDup(p->pExprList);
218 sqliteExprListDelete(p->pExprList);
219 p->pExprList = pNew;
220 }
221 if( p->pIdList ){
222 IdList *pNew = sqliteIdListDup(p->pIdList);
223 sqliteIdListDelete(p->pIdList);
224 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000225 }
226}
227
drhc977f7f2002-05-21 11:38:11 +0000228/*
229** Turn a SELECT statement (that the pSelect parameter points to) into
230** a trigger step. Return a pointer to a TriggerStep structure.
231**
232** The parser calls this routine when it finds a SELECT statement in
233** body of a TRIGGER.
234*/
235TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000236 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000237 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000238
danielk1977633ed082002-05-17 00:05:58 +0000239 pTriggerStep->op = TK_SELECT;
240 pTriggerStep->pSelect = pSelect;
241 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000242 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000243
danielk1977633ed082002-05-17 00:05:58 +0000244 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000245}
246
drhc977f7f2002-05-21 11:38:11 +0000247/*
248** Build a trigger step out of an INSERT statement. Return a pointer
249** to the new trigger step.
250**
251** The parser calls this routine when it sees an INSERT inside the
252** body of a trigger.
253*/
danielk1977633ed082002-05-17 00:05:58 +0000254TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000255 Token *pTableName, /* Name of the table into which we insert */
256 IdList *pColumn, /* List of columns in pTableName to insert into */
257 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
258 Select *pSelect, /* A SELECT statement that supplies values */
259 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000260){
261 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000262 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000263
danielk1977633ed082002-05-17 00:05:58 +0000264 assert(pEList == 0 || pSelect == 0);
265 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000266
danielk1977633ed082002-05-17 00:05:58 +0000267 pTriggerStep->op = TK_INSERT;
268 pTriggerStep->pSelect = pSelect;
269 pTriggerStep->target = *pTableName;
270 pTriggerStep->pIdList = pColumn;
271 pTriggerStep->pExprList = pEList;
272 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000273 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000274
danielk1977633ed082002-05-17 00:05:58 +0000275 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000276}
277
drhc977f7f2002-05-21 11:38:11 +0000278/*
279** Construct a trigger step that implements an UPDATE statement and return
280** a pointer to that trigger step. The parser calls this routine when it
281** sees an UPDATE statement inside the body of a CREATE TRIGGER.
282*/
danielk1977633ed082002-05-17 00:05:58 +0000283TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000284 Token *pTableName, /* Name of the table to be updated */
285 ExprList *pEList, /* The SET clause: list of column and new values */
286 Expr *pWhere, /* The WHERE clause */
287 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
288){
danielk1977633ed082002-05-17 00:05:58 +0000289 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000290 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000291
danielk1977633ed082002-05-17 00:05:58 +0000292 pTriggerStep->op = TK_UPDATE;
293 pTriggerStep->target = *pTableName;
294 pTriggerStep->pExprList = pEList;
295 pTriggerStep->pWhere = pWhere;
296 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000297 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000298
danielk1977633ed082002-05-17 00:05:58 +0000299 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000300}
301
drhc977f7f2002-05-21 11:38:11 +0000302/*
303** Construct a trigger step that implements a DELETE statement and return
304** a pointer to that trigger step. The parser calls this routine when it
305** sees a DELETE statement inside the body of a CREATE TRIGGER.
306*/
307TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000308 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
309 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000310
danielk1977633ed082002-05-17 00:05:58 +0000311 pTriggerStep->op = TK_DELETE;
312 pTriggerStep->target = *pTableName;
313 pTriggerStep->pWhere = pWhere;
314 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000315 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000316
danielk1977633ed082002-05-17 00:05:58 +0000317 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000318}
319
danielk1977633ed082002-05-17 00:05:58 +0000320/*
321** Recursively delete a Trigger structure
322*/
drh1d1f3052002-05-21 13:18:25 +0000323void sqliteDeleteTrigger(Trigger *pTrigger){
drh4b59ab52002-08-24 18:24:51 +0000324 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000325 sqliteFree(pTrigger->name);
326 sqliteFree(pTrigger->table);
327 sqliteExprDelete(pTrigger->pWhen);
328 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000329 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000330}
331
332/*
danielk1977633ed082002-05-17 00:05:58 +0000333 * This function is called to drop a trigger from the database schema.
334 *
335 * This may be called directly from the parser, or from within
336 * sqliteDropTable(). In the latter case the "nested" argument is true.
337 *
338 * Note that this function does not delete the trigger entirely. Instead it
339 * removes it from the internal schema and places it in the trigDrop hash
340 * table. This is so that the trigger can be restored into the database schema
341 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000342 */
drhd24cc422003-03-27 12:51:24 +0000343void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000344 Trigger *pTrigger;
345 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000346 Vdbe *v;
drhd24cc422003-03-27 12:51:24 +0000347 int i;
348 const char *zDb;
349 const char *zName;
350 int nName;
351 sqlite *db = pParse->db;
danielk1977c3f9bad2002-05-15 08:30:12 +0000352
drhd24cc422003-03-27 12:51:24 +0000353 if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
354 assert( pName->nSrc==1 );
355 zDb = pName->a[0].zDatabase;
356 zName = pName->a[0].zName;
357 nName = strlen(zName);
358 for(i=0; i<db->nDb; i++){
drh812d7a22003-03-27 13:50:00 +0000359 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
360 if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
361 pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
drhd24cc422003-03-27 12:51:24 +0000362 if( pTrigger ) break;
danielk1977c3f9bad2002-05-15 08:30:12 +0000363 }
drhd24cc422003-03-27 12:51:24 +0000364 if( !pTrigger ){
365 sqliteSetString(&pParse->zErrMsg, "no such trigger: ", zName, 0);
366 goto drop_trigger_cleanup;
367 }
368 assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );
369 if( pTrigger->iDb>=2 ){
370 sqliteSetString(&pParse->zErrMsg, "triggers may not be removed from "
371 "auxiliary database \"", db->aDb[pTrigger->iDb].zName, "\"", 0);
372 pParse->nErr++;
373 goto drop_trigger_cleanup;
374 }
375 pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName);
drhed6c8672003-01-12 18:02:16 +0000376 assert(pTable);
drhd24cc422003-03-27 12:51:24 +0000377 assert( pTable->iDb==pTrigger->iDb );
drhe5f9c642003-01-13 23:27:31 +0000378#ifndef SQLITE_OMIT_AUTHORIZATION
379 {
380 int code = SQLITE_DROP_TRIGGER;
drhd24cc422003-03-27 12:51:24 +0000381 if( pTable->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
drhe5f9c642003-01-13 23:27:31 +0000382 if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
drhd24cc422003-03-27 12:51:24 +0000383 sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->iDb),0) ){
drh0be9df02003-03-30 00:19:49 +0000384 goto drop_trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000385 }
drhed6c8672003-01-12 18:02:16 +0000386 }
drhe5f9c642003-01-13 23:27:31 +0000387#endif
danielk1977c3f9bad2002-05-15 08:30:12 +0000388
389 /*
drhe0bc4042002-06-25 01:09:11 +0000390 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000391 */
danielk1977633ed082002-05-17 00:05:58 +0000392 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000393 if( pTable->pTrigger == pTrigger ){
394 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000395 }else{
danielk1977633ed082002-05-17 00:05:58 +0000396 Trigger *cc = pTable->pTrigger;
397 while( cc ){
398 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000399 cc->pNext = cc->pNext->pNext;
400 break;
401 }
402 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000403 }
404 assert(cc);
405 }
drhd24cc422003-03-27 12:51:24 +0000406 sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
drhe0bc4042002-06-25 01:09:11 +0000407 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000408 }
409
drhe0bc4042002-06-25 01:09:11 +0000410 /* Generate code to destroy the database record of the trigger.
411 */
412 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000413 int base;
414 static VdbeOp dropTrigger[] = {
drhe0bc4042002-06-25 01:09:11 +0000415 { OP_Rewind, 0, ADDR(8), 0},
416 { OP_String, 0, 0, 0}, /* 1 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000417 { OP_MemStore, 1, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000418 { OP_MemLoad, 1, 0, 0}, /* 3 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000419 { OP_Column, 0, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000420 { OP_Ne, 0, ADDR(7), 0},
danielk1977c3f9bad2002-05-15 08:30:12 +0000421 { OP_Delete, 0, 0, 0},
drhe0bc4042002-06-25 01:09:11 +0000422 { OP_Next, 0, ADDR(3), 0}, /* 7 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000423 };
424
drhcabb0812002-09-14 13:47:32 +0000425 sqliteBeginWriteOperation(pParse, 0, 0);
drhd24cc422003-03-27 12:51:24 +0000426 sqliteOpenMasterTable(v, pTable->iDb);
drhe0bc4042002-06-25 01:09:11 +0000427 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
428 sqliteVdbeChangeP3(v, base+1, zName, 0);
drhd24cc422003-03-27 12:51:24 +0000429 if( pTable->iDb==0 ){
430 sqliteChangeCookie(db, v);
drhdc379452002-05-15 12:45:43 +0000431 }
drhe0bc4042002-06-25 01:09:11 +0000432 sqliteVdbeAddOp(v, OP_Close, 0, 0);
433 sqliteEndWriteOperation(pParse);
danielk1977c3f9bad2002-05-15 08:30:12 +0000434 }
435
drhd24cc422003-03-27 12:51:24 +0000436drop_trigger_cleanup:
437 sqliteSrcListDelete(pName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000438}
439
drhc977f7f2002-05-21 11:38:11 +0000440/*
441** pEList is the SET clause of an UPDATE statement. Each entry
442** in pEList is of the format <id>=<expr>. If any of the entries
443** in pEList have an <id> which matches an identifier in pIdList,
444** then return TRUE. If pIdList==NULL, then it is considered a
445** wildcard that matches anything. Likewise if pEList==NULL then
446** it matches anything so always return true. Return false only
447** if there is no match.
448*/
449static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000450 int e;
451 if( !pIdList || !pEList ) return 1;
452 for(e=0; e<pEList->nExpr; e++){
453 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000454 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000455 return 0;
456}
457
458/* A global variable that is TRUE if we should always set up temp tables for
459 * for triggers, even if there are no triggers to code. This is used to test
460 * how much overhead the triggers algorithm is causing.
461 *
462 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
463 * The pragma is not documented since it is not really part of the interface
464 * to SQLite, just the test procedure.
465*/
466int always_code_trigger_setup = 0;
467
468/*
469 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
470 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
471 * found in the list specified as pTrigger.
472 */
473int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000474 Parse *pParse, /* Used to check for recursive triggers */
475 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000476 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
477 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
478 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000479 ExprList *pChanges /* Columns that change in an UPDATE statement */
480){
danielk1977633ed082002-05-17 00:05:58 +0000481 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000482
danielk1977633ed082002-05-17 00:05:58 +0000483 if( always_code_trigger_setup ){
484 return 1;
485 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000486
danielk1977633ed082002-05-17 00:05:58 +0000487 pTriggerCursor = pTrigger;
488 while( pTriggerCursor ){
489 if( pTriggerCursor->op == op &&
490 pTriggerCursor->tr_tm == tr_tm &&
491 pTriggerCursor->foreach == foreach &&
492 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000493 TriggerStack * ss;
494 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000495 while( ss && ss->pTrigger != pTrigger ){
496 ss = ss->pNext;
497 }
498 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000499 }
danielk1977633ed082002-05-17 00:05:58 +0000500 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000501 }
502
503 return 0;
504}
505
drhc977f7f2002-05-21 11:38:11 +0000506/*
507** Generate VDBE code for zero or more statements inside the body of a
508** trigger.
509*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000510static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000511 Parse *pParse, /* The parser context */
512 TriggerStep *pStepList, /* List of statements inside the trigger body */
513 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000514){
515 TriggerStep * pTriggerStep = pStepList;
516 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000517
danielk1977633ed082002-05-17 00:05:58 +0000518 while( pTriggerStep ){
519 int saveNTab = pParse->nTab;
520 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
521 pParse->trigStack->orconf = orconf;
522 switch( pTriggerStep->op ){
523 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000524 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
525 assert(ss);
526 assert(ss->pSrc);
527 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
528 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000529 break;
530 }
531 case TK_UPDATE: {
drh113088e2003-03-20 01:16:58 +0000532 SrcList *pSrc;
533 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
drhbd5a4512002-05-23 22:07:02 +0000534 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000535 sqliteUpdate(pParse, pSrc,
danielk19776f349032002-06-11 02:25:40 +0000536 sqliteExprListDup(pTriggerStep->pExprList),
537 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000538 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000539 break;
540 }
541 case TK_INSERT: {
drh113088e2003-03-20 01:16:58 +0000542 SrcList *pSrc;
543 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
544 sqliteInsert(pParse, pSrc,
545 sqliteExprListDup(pTriggerStep->pExprList),
546 sqliteSelectDup(pTriggerStep->pSelect),
547 sqliteIdListDup(pTriggerStep->pIdList), orconf);
danielk1977633ed082002-05-17 00:05:58 +0000548 break;
549 }
550 case TK_DELETE: {
drh113088e2003-03-20 01:16:58 +0000551 SrcList *pSrc;
drhbd5a4512002-05-23 22:07:02 +0000552 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000553 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
554 sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000555 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000556 break;
557 }
558 default:
559 assert(0);
560 }
561 pParse->nTab = saveNTab;
562 pTriggerStep = pTriggerStep->pNext;
563 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000564
danielk1977633ed082002-05-17 00:05:58 +0000565 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000566}
567
danielk1977633ed082002-05-17 00:05:58 +0000568/*
569** This is called to code FOR EACH ROW triggers.
570**
571** When the code that this function generates is executed, the following
572** must be true:
drhc977f7f2002-05-21 11:38:11 +0000573**
574** 1. No cursors may be open in the main database. (But newIdx and oldIdx
575** can be indices of cursors in temporary tables. See below.)
576**
danielk1977633ed082002-05-17 00:05:58 +0000577** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
578** a temporary vdbe cursor (index newIdx) must be open and pointing at
579** a row containing values to be substituted for new.* expressions in the
580** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000581**
danielk1977633ed082002-05-17 00:05:58 +0000582** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
583** a temporary vdbe cursor (index oldIdx) must be open and pointing at
584** a row containing values to be substituted for old.* expressions in the
585** trigger program(s).
586**
587*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000588int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000589 Parse *pParse, /* Parse context */
590 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
591 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
592 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
593 Table *pTab, /* The table to code triggers from */
594 int newIdx, /* The indice of the "new" row to access */
595 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000596 int orconf, /* ON CONFLICT policy */
597 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000598){
danielk1977c3f9bad2002-05-15 08:30:12 +0000599 Trigger * pTrigger;
600 TriggerStack * pTriggerStack;
601
danielk1977c3f9bad2002-05-15 08:30:12 +0000602 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
603 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
604
danielk1977633ed082002-05-17 00:05:58 +0000605 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000606
danielk1977633ed082002-05-17 00:05:58 +0000607 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000608 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000609 int fire_this = 0;
610
611 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000612 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
613 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000614 fire_this = 1;
615 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000616 while( pTriggerStack ){
617 if( pTriggerStack->pTrigger == pTrigger ){
618 fire_this = 0;
619 }
drh9adf9ac2002-05-15 11:44:13 +0000620 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000621 }
danielk1977f29ce552002-05-19 23:43:12 +0000622 if( op == TK_UPDATE && pTrigger->pColumns &&
623 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000624 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000625 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000626 }
627
drhe4697f52002-05-23 02:09:03 +0000628 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000629 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000630 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000631 Expr * whenExpr;
632
drhad3cab52002-05-24 02:04:32 +0000633 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000634
635 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000636 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000637 pTriggerStack->newIdx = newIdx;
638 pTriggerStack->oldIdx = oldIdx;
639 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000640 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000641 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000642 pParse->trigStack = pTriggerStack;
643
644 /* code the WHEN clause */
645 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
646 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000647 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000648 pParse->trigStack = pParse->trigStack->pNext;
649 sqliteFree(pTriggerStack);
650 sqliteExprDelete(whenExpr);
651 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000652 }
drhf5905aa2002-05-26 20:54:33 +0000653 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000654 sqliteExprDelete(whenExpr);
655
danielk1977633ed082002-05-17 00:05:58 +0000656 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000657
658 /* Pop the entry off the trigger stack */
659 pParse->trigStack = pParse->trigStack->pNext;
660 sqliteFree(pTriggerStack);
661
662 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
663 }
664 pTrigger = pTrigger->pNext;
665 }
666
667 return 0;
668}
669
670/*
danielk1977633ed082002-05-17 00:05:58 +0000671 * This function is called to code ON UPDATE and ON DELETE triggers on
672 * views.
673 *
674 * This function deletes the data pointed at by the pWhere and pChanges
675 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000676 */
danielk1977633ed082002-05-17 00:05:58 +0000677void sqliteViewTriggers(
678 Parse *pParse,
679 Table *pTab, /* The view to code triggers on */
680 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
681 int orconf, /* The ON CONFLICT policy specified as part of the
682 statement causing these triggers */
683 ExprList *pChanges /* If this is an statement causing triggers to fire
684 is an UPDATE, then this list holds the columns
685 to update and the expressions to update them to.
686 See comments for sqliteUpdate(). */
687){
danielk1977c3f9bad2002-05-15 08:30:12 +0000688 int oldIdx = -1;
689 int newIdx = -1;
690 int *aXRef = 0;
691 Vdbe *v;
692 int endOfLoop;
693 int startOfLoop;
694 Select theSelect;
695 Token tblNameToken;
696
697 assert(pTab->pSelect);
698
699 tblNameToken.z = pTab->zName;
700 tblNameToken.n = strlen(pTab->zName);
701
702 theSelect.isDistinct = 0;
703 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drh113088e2003-03-20 01:16:58 +0000704 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000705 theSelect.pWhere = pWhere; pWhere = 0;
706 theSelect.pGroupBy = 0;
707 theSelect.pHaving = 0;
708 theSelect.pOrderBy = 0;
709 theSelect.op = TK_SELECT; /* ?? */
710 theSelect.pPrior = 0;
711 theSelect.nLimit = -1;
712 theSelect.nOffset = -1;
713 theSelect.zSelect = 0;
714 theSelect.base = 0;
715
716 v = sqliteGetVdbe(pParse);
717 assert(v);
drhcabb0812002-09-14 13:47:32 +0000718 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000719
720 /* Allocate temp tables */
721 oldIdx = pParse->nTab++;
722 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000723 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000724 newIdx = pParse->nTab++;
725 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
726 }
727
728 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000729 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000730 goto trigger_cleanup;
731 }
732
733 /* loop thru the view snapshot, executing triggers for each row */
734 endOfLoop = sqliteVdbeMakeLabel(v);
735 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
736
737 /* Loop thru the view snapshot, executing triggers for each row */
738 startOfLoop = sqliteVdbeCurrentAddr(v);
739
740 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000741 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000742 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000743
744 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
745 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000746 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000747 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000748 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000749
750 for(ii=0; ii<pChanges->nExpr; ii++){
751 int jj;
752 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000753 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000754 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000755 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000756
757 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000758 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000759
760 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000761 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
762 aXRef[jj] = ii;
763 break;
764 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000765 }
766 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000767 sqliteSetString(&pParse->zErrMsg, "no such column: ",
768 pChanges->a[ii].zName, 0);
769 pParse->nErr++;
770 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000771 }
772 }
773
774 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
775
danielk1977633ed082002-05-17 00:05:58 +0000776 for(ii = 0; ii<pTab->nCol; ii++){
777 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000778 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000779 }else{
drh9adf9ac2002-05-15 11:44:13 +0000780 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000781 }
782 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000783
784 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
785 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
786 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
787
788 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000789 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000790 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000791 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000792 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000793 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000794 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000795 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000796 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000797 }
798
799 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
800
801 sqliteVdbeResolveLabel(v, endOfLoop);
802 sqliteEndWriteOperation(pParse);
803
804trigger_cleanup:
805 sqliteFree(aXRef);
806 sqliteExprListDelete(pChanges);
807 sqliteExprDelete(pWhere);
808 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000809 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000810 sqliteExprDelete(theSelect.pWhere);
811 return;
812}