blob: 4c0c00740a590fefca35661f17adc3a45b06fd41 [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 );
64 tab = sqliteTableNameToTable(pParse, pTableName->a[0].zName,
65 pTableName->a[0].zDatabase);
66 if( !tab ){
67 goto trigger_cleanup;
68 }
69 if( tab->iDb>=2 ){
70 sqliteSetString(&pParse->zErrMsg, "triggers may not be added to "
71 "auxiliary database \"", db->aDb[tab->iDb].zName, "\"", 0);
72 pParse->nErr++;
73 goto trigger_cleanup;
74 }
75
drhe5f9c642003-01-13 23:27:31 +000076 zName = sqliteStrNDup(pName->z, pName->n);
drhd24cc422003-03-27 12:51:24 +000077 if( sqliteHashFind(&(db->aDb[tab->iDb].trigHash), zName,pName->n+1) ){
drhe5f9c642003-01-13 23:27:31 +000078 sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
79 pName->z, pName->n, " already exists", -1, 0);
80 pParse->nErr++;
81 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000082 }
drhd24cc422003-03-27 12:51:24 +000083 if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
84 sqliteSetString(&pParse->zErrMsg,"cannot create trigger on system table",0);
85 pParse->nErr++;
86 goto trigger_cleanup;
danielk1977d702fcc2002-05-26 23:24:40 +000087 }
drhd24cc422003-03-27 12:51:24 +000088 if( tab->pSelect && tr_tm != TK_INSTEAD ){
89 sqliteSetNString(&pParse->zErrMsg, "cannot create ",
90 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", " trigger on view: ",
91 pTableName->a[0].zName, 0);
92 goto trigger_cleanup;
93 }
94 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
95 sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF",
96 " trigger on table: ", pTableName->a[0].zName);
97 goto trigger_cleanup;
98 }
99#ifndef SQLITE_OMIT_AUTHORIZATION
100 {
101 int code = SQLITE_CREATE_TRIGGER;
102 if( tab->iDb==1 ) code = SQLITE_CREATE_TEMP_TRIGGER;
103 if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
104 goto trigger_cleanup;
105 }
106 if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0)){
107 goto trigger_cleanup;
108 }
109 }
110#endif
danielk1977d702fcc2002-05-26 23:24:40 +0000111
112 if (tr_tm == TK_INSTEAD){
113 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +0000114 }
115
116 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +0000117 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +0000118 if( nt==0 ) goto trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000119 nt->name = zName;
120 zName = 0;
drhd24cc422003-03-27 12:51:24 +0000121 nt->table = sqliteStrDup(pTableName->a[0].zName);
drhe4697f52002-05-23 02:09:03 +0000122 if( sqlite_malloc_failed ) goto trigger_cleanup;
drhd24cc422003-03-27 12:51:24 +0000123 nt->iDb = tab->iDb;
danielk1977c3f9bad2002-05-15 08:30:12 +0000124 nt->op = op;
125 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000126 nt->pWhen = sqliteExprDup(pWhen);
127 sqliteExprDelete(pWhen);
128 nt->pColumns = sqliteIdListDup(pColumns);
129 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000130 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000131 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000132
133 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000134 ** build the sqlite_master entry
135 */
drhe0bc4042002-06-25 01:09:11 +0000136 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000137 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000138 { OP_NewRecno, 0, 0, 0 },
139 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000140 { OP_String, 0, 0, 0 }, /* 2: trigger name */
141 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000142 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000143 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000144 { OP_MakeRecord, 5, 0, 0 },
145 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000146 };
147 int addr;
148 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000149
150 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000151 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000152 if( v==0 ) goto trigger_cleanup;
drhcabb0812002-09-14 13:47:32 +0000153 sqliteBeginWriteOperation(pParse, 0, 0);
drhd24cc422003-03-27 12:51:24 +0000154 sqliteOpenMasterTable(v, tab->iDb);
drhc977f7f2002-05-21 11:38:11 +0000155 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhd24cc422003-03-27 12:51:24 +0000156 sqliteVdbeChangeP3(v, addr, tab->iDb ? TEMP_MASTER_NAME : MASTER_NAME,
drhe0bc4042002-06-25 01:09:11 +0000157 P3_STATIC);
158 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
159 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000160 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhd24cc422003-03-27 12:51:24 +0000161 if( tab->iDb==0 ){
162 sqliteChangeCookie(db, v);
drhe0bc4042002-06-25 01:09:11 +0000163 }
164 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000165 sqliteEndWriteOperation(pParse);
166 }
167
danielk1977633ed082002-05-17 00:05:58 +0000168 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000169 /* Stick it in the hash-table */
drhd24cc422003-03-27 12:51:24 +0000170 sqliteHashInsert(&(db->aDb[nt->iDb].trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000171
172 /* Attach it to the table object */
173 nt->pNext = tab->pTrigger;
174 tab->pTrigger = nt;
175 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++){
359 if( zDb && sqliteStrICmp(db->aDb[i].zName, zDb) ) continue;
360 pTrigger = sqliteHashFind(&(db->aDb[i].trigHash), zName, nName+1);
361 if( pTrigger ) break;
danielk1977c3f9bad2002-05-15 08:30:12 +0000362 }
drhd24cc422003-03-27 12:51:24 +0000363 if( !pTrigger ){
364 sqliteSetString(&pParse->zErrMsg, "no such trigger: ", zName, 0);
365 goto drop_trigger_cleanup;
366 }
367 assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );
368 if( pTrigger->iDb>=2 ){
369 sqliteSetString(&pParse->zErrMsg, "triggers may not be removed from "
370 "auxiliary database \"", db->aDb[pTrigger->iDb].zName, "\"", 0);
371 pParse->nErr++;
372 goto drop_trigger_cleanup;
373 }
374 pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName);
drhed6c8672003-01-12 18:02:16 +0000375 assert(pTable);
drhd24cc422003-03-27 12:51:24 +0000376 assert( pTable->iDb==pTrigger->iDb );
drhe5f9c642003-01-13 23:27:31 +0000377#ifndef SQLITE_OMIT_AUTHORIZATION
378 {
379 int code = SQLITE_DROP_TRIGGER;
drhd24cc422003-03-27 12:51:24 +0000380 if( pTable->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
drhe5f9c642003-01-13 23:27:31 +0000381 if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
drhd24cc422003-03-27 12:51:24 +0000382 sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->iDb),0) ){
drhe5f9c642003-01-13 23:27:31 +0000383 return;
384 }
drhed6c8672003-01-12 18:02:16 +0000385 }
drhe5f9c642003-01-13 23:27:31 +0000386#endif
danielk1977c3f9bad2002-05-15 08:30:12 +0000387
388 /*
drhe0bc4042002-06-25 01:09:11 +0000389 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000390 */
danielk1977633ed082002-05-17 00:05:58 +0000391 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000392 if( pTable->pTrigger == pTrigger ){
393 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000394 }else{
danielk1977633ed082002-05-17 00:05:58 +0000395 Trigger *cc = pTable->pTrigger;
396 while( cc ){
397 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000398 cc->pNext = cc->pNext->pNext;
399 break;
400 }
401 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000402 }
403 assert(cc);
404 }
drhd24cc422003-03-27 12:51:24 +0000405 sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
drhe0bc4042002-06-25 01:09:11 +0000406 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000407 }
408
drhe0bc4042002-06-25 01:09:11 +0000409 /* Generate code to destroy the database record of the trigger.
410 */
411 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000412 int base;
413 static VdbeOp dropTrigger[] = {
drhe0bc4042002-06-25 01:09:11 +0000414 { OP_Rewind, 0, ADDR(8), 0},
415 { OP_String, 0, 0, 0}, /* 1 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000416 { OP_MemStore, 1, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000417 { OP_MemLoad, 1, 0, 0}, /* 3 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000418 { OP_Column, 0, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000419 { OP_Ne, 0, ADDR(7), 0},
danielk1977c3f9bad2002-05-15 08:30:12 +0000420 { OP_Delete, 0, 0, 0},
drhe0bc4042002-06-25 01:09:11 +0000421 { OP_Next, 0, ADDR(3), 0}, /* 7 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000422 };
423
drhcabb0812002-09-14 13:47:32 +0000424 sqliteBeginWriteOperation(pParse, 0, 0);
drhd24cc422003-03-27 12:51:24 +0000425 sqliteOpenMasterTable(v, pTable->iDb);
drhe0bc4042002-06-25 01:09:11 +0000426 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
427 sqliteVdbeChangeP3(v, base+1, zName, 0);
drhd24cc422003-03-27 12:51:24 +0000428 if( pTable->iDb==0 ){
429 sqliteChangeCookie(db, v);
drhdc379452002-05-15 12:45:43 +0000430 }
drhe0bc4042002-06-25 01:09:11 +0000431 sqliteVdbeAddOp(v, OP_Close, 0, 0);
432 sqliteEndWriteOperation(pParse);
danielk1977c3f9bad2002-05-15 08:30:12 +0000433 }
434
drhd24cc422003-03-27 12:51:24 +0000435drop_trigger_cleanup:
436 sqliteSrcListDelete(pName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000437}
438
drhc977f7f2002-05-21 11:38:11 +0000439/*
440** pEList is the SET clause of an UPDATE statement. Each entry
441** in pEList is of the format <id>=<expr>. If any of the entries
442** in pEList have an <id> which matches an identifier in pIdList,
443** then return TRUE. If pIdList==NULL, then it is considered a
444** wildcard that matches anything. Likewise if pEList==NULL then
445** it matches anything so always return true. Return false only
446** if there is no match.
447*/
448static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000449 int e;
450 if( !pIdList || !pEList ) return 1;
451 for(e=0; e<pEList->nExpr; e++){
452 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000453 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000454 return 0;
455}
456
457/* A global variable that is TRUE if we should always set up temp tables for
458 * for triggers, even if there are no triggers to code. This is used to test
459 * how much overhead the triggers algorithm is causing.
460 *
461 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
462 * The pragma is not documented since it is not really part of the interface
463 * to SQLite, just the test procedure.
464*/
465int always_code_trigger_setup = 0;
466
467/*
468 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
469 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
470 * found in the list specified as pTrigger.
471 */
472int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000473 Parse *pParse, /* Used to check for recursive triggers */
474 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000475 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
476 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
477 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000478 ExprList *pChanges /* Columns that change in an UPDATE statement */
479){
danielk1977633ed082002-05-17 00:05:58 +0000480 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000481
danielk1977633ed082002-05-17 00:05:58 +0000482 if( always_code_trigger_setup ){
483 return 1;
484 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000485
danielk1977633ed082002-05-17 00:05:58 +0000486 pTriggerCursor = pTrigger;
487 while( pTriggerCursor ){
488 if( pTriggerCursor->op == op &&
489 pTriggerCursor->tr_tm == tr_tm &&
490 pTriggerCursor->foreach == foreach &&
491 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000492 TriggerStack * ss;
493 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000494 while( ss && ss->pTrigger != pTrigger ){
495 ss = ss->pNext;
496 }
497 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000498 }
danielk1977633ed082002-05-17 00:05:58 +0000499 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000500 }
501
502 return 0;
503}
504
drhc977f7f2002-05-21 11:38:11 +0000505/*
506** Generate VDBE code for zero or more statements inside the body of a
507** trigger.
508*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000509static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000510 Parse *pParse, /* The parser context */
511 TriggerStep *pStepList, /* List of statements inside the trigger body */
512 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000513){
514 TriggerStep * pTriggerStep = pStepList;
515 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000516
danielk1977633ed082002-05-17 00:05:58 +0000517 while( pTriggerStep ){
518 int saveNTab = pParse->nTab;
519 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
520 pParse->trigStack->orconf = orconf;
521 switch( pTriggerStep->op ){
522 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000523 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
524 assert(ss);
525 assert(ss->pSrc);
526 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
527 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000528 break;
529 }
530 case TK_UPDATE: {
drh113088e2003-03-20 01:16:58 +0000531 SrcList *pSrc;
532 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
drhbd5a4512002-05-23 22:07:02 +0000533 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000534 sqliteUpdate(pParse, pSrc,
danielk19776f349032002-06-11 02:25:40 +0000535 sqliteExprListDup(pTriggerStep->pExprList),
536 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000537 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000538 break;
539 }
540 case TK_INSERT: {
drh113088e2003-03-20 01:16:58 +0000541 SrcList *pSrc;
542 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
543 sqliteInsert(pParse, pSrc,
544 sqliteExprListDup(pTriggerStep->pExprList),
545 sqliteSelectDup(pTriggerStep->pSelect),
546 sqliteIdListDup(pTriggerStep->pIdList), orconf);
danielk1977633ed082002-05-17 00:05:58 +0000547 break;
548 }
549 case TK_DELETE: {
drh113088e2003-03-20 01:16:58 +0000550 SrcList *pSrc;
drhbd5a4512002-05-23 22:07:02 +0000551 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000552 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
553 sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000554 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000555 break;
556 }
557 default:
558 assert(0);
559 }
560 pParse->nTab = saveNTab;
561 pTriggerStep = pTriggerStep->pNext;
562 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000563
danielk1977633ed082002-05-17 00:05:58 +0000564 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000565}
566
danielk1977633ed082002-05-17 00:05:58 +0000567/*
568** This is called to code FOR EACH ROW triggers.
569**
570** When the code that this function generates is executed, the following
571** must be true:
drhc977f7f2002-05-21 11:38:11 +0000572**
573** 1. No cursors may be open in the main database. (But newIdx and oldIdx
574** can be indices of cursors in temporary tables. See below.)
575**
danielk1977633ed082002-05-17 00:05:58 +0000576** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
577** a temporary vdbe cursor (index newIdx) must be open and pointing at
578** a row containing values to be substituted for new.* expressions in the
579** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000580**
danielk1977633ed082002-05-17 00:05:58 +0000581** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
582** a temporary vdbe cursor (index oldIdx) must be open and pointing at
583** a row containing values to be substituted for old.* expressions in the
584** trigger program(s).
585**
586*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000587int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000588 Parse *pParse, /* Parse context */
589 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
590 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
591 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
592 Table *pTab, /* The table to code triggers from */
593 int newIdx, /* The indice of the "new" row to access */
594 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000595 int orconf, /* ON CONFLICT policy */
596 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000597){
danielk1977c3f9bad2002-05-15 08:30:12 +0000598 Trigger * pTrigger;
599 TriggerStack * pTriggerStack;
600
danielk1977c3f9bad2002-05-15 08:30:12 +0000601 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
602 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
603
danielk1977633ed082002-05-17 00:05:58 +0000604 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000605
danielk1977633ed082002-05-17 00:05:58 +0000606 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000607 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000608 int fire_this = 0;
609
610 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000611 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
612 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000613 fire_this = 1;
614 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000615 while( pTriggerStack ){
616 if( pTriggerStack->pTrigger == pTrigger ){
617 fire_this = 0;
618 }
drh9adf9ac2002-05-15 11:44:13 +0000619 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000620 }
danielk1977f29ce552002-05-19 23:43:12 +0000621 if( op == TK_UPDATE && pTrigger->pColumns &&
622 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000623 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000624 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000625 }
626
drhe4697f52002-05-23 02:09:03 +0000627 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000628 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000629 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000630 Expr * whenExpr;
631
drhad3cab52002-05-24 02:04:32 +0000632 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000633
634 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000635 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000636 pTriggerStack->newIdx = newIdx;
637 pTriggerStack->oldIdx = oldIdx;
638 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000639 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000640 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000641 pParse->trigStack = pTriggerStack;
642
643 /* code the WHEN clause */
644 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
645 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000646 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000647 pParse->trigStack = pParse->trigStack->pNext;
648 sqliteFree(pTriggerStack);
649 sqliteExprDelete(whenExpr);
650 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000651 }
drhf5905aa2002-05-26 20:54:33 +0000652 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000653 sqliteExprDelete(whenExpr);
654
danielk1977633ed082002-05-17 00:05:58 +0000655 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000656
657 /* Pop the entry off the trigger stack */
658 pParse->trigStack = pParse->trigStack->pNext;
659 sqliteFree(pTriggerStack);
660
661 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
662 }
663 pTrigger = pTrigger->pNext;
664 }
665
666 return 0;
667}
668
669/*
danielk1977633ed082002-05-17 00:05:58 +0000670 * This function is called to code ON UPDATE and ON DELETE triggers on
671 * views.
672 *
673 * This function deletes the data pointed at by the pWhere and pChanges
674 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000675 */
danielk1977633ed082002-05-17 00:05:58 +0000676void sqliteViewTriggers(
677 Parse *pParse,
678 Table *pTab, /* The view to code triggers on */
679 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
680 int orconf, /* The ON CONFLICT policy specified as part of the
681 statement causing these triggers */
682 ExprList *pChanges /* If this is an statement causing triggers to fire
683 is an UPDATE, then this list holds the columns
684 to update and the expressions to update them to.
685 See comments for sqliteUpdate(). */
686){
danielk1977c3f9bad2002-05-15 08:30:12 +0000687 int oldIdx = -1;
688 int newIdx = -1;
689 int *aXRef = 0;
690 Vdbe *v;
691 int endOfLoop;
692 int startOfLoop;
693 Select theSelect;
694 Token tblNameToken;
695
696 assert(pTab->pSelect);
697
698 tblNameToken.z = pTab->zName;
699 tblNameToken.n = strlen(pTab->zName);
700
701 theSelect.isDistinct = 0;
702 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drh113088e2003-03-20 01:16:58 +0000703 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000704 theSelect.pWhere = pWhere; pWhere = 0;
705 theSelect.pGroupBy = 0;
706 theSelect.pHaving = 0;
707 theSelect.pOrderBy = 0;
708 theSelect.op = TK_SELECT; /* ?? */
709 theSelect.pPrior = 0;
710 theSelect.nLimit = -1;
711 theSelect.nOffset = -1;
712 theSelect.zSelect = 0;
713 theSelect.base = 0;
714
715 v = sqliteGetVdbe(pParse);
716 assert(v);
drhcabb0812002-09-14 13:47:32 +0000717 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000718
719 /* Allocate temp tables */
720 oldIdx = pParse->nTab++;
721 sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000722 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000723 newIdx = pParse->nTab++;
724 sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
725 }
726
727 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000728 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000729 goto trigger_cleanup;
730 }
731
732 /* loop thru the view snapshot, executing triggers for each row */
733 endOfLoop = sqliteVdbeMakeLabel(v);
734 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
735
736 /* Loop thru the view snapshot, executing triggers for each row */
737 startOfLoop = sqliteVdbeCurrentAddr(v);
738
739 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000740 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000741 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000742
743 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
744 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000745 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000746 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000747 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000748
749 for(ii=0; ii<pChanges->nExpr; ii++){
750 int jj;
751 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000752 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000753 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000754 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000755
756 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000757 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000758
759 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000760 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
761 aXRef[jj] = ii;
762 break;
763 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000764 }
765 if( jj>=pTab->nCol ){
drh9adf9ac2002-05-15 11:44:13 +0000766 sqliteSetString(&pParse->zErrMsg, "no such column: ",
767 pChanges->a[ii].zName, 0);
768 pParse->nErr++;
769 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000770 }
771 }
772
773 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
774
danielk1977633ed082002-05-17 00:05:58 +0000775 for(ii = 0; ii<pTab->nCol; ii++){
776 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000777 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000778 }else{
drh9adf9ac2002-05-15 11:44:13 +0000779 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000780 }
781 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000782
783 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
784 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
785 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
786
787 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000788 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000789 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000790 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000791 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000792 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000793 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000794 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000795 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000796 }
797
798 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
799
800 sqliteVdbeResolveLabel(v, endOfLoop);
801 sqliteEndWriteOperation(pParse);
802
803trigger_cleanup:
804 sqliteFree(aXRef);
805 sqliteExprListDelete(pChanges);
806 sqliteExprDelete(pWhere);
807 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000808 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000809 sqliteExprDelete(theSelect.pWhere);
810 return;
811}