blob: 71a784aaefa197292ca7367bec999767dd89bd95 [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 ){
drhda93d232003-03-31 02:12:46 +000069 sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
70 "database %s", db->aDb[tab->iDb].zName);
drhd24cc422003-03-27 12:51:24 +000071 goto trigger_cleanup;
72 }
73
drhe5f9c642003-01-13 23:27:31 +000074 zName = sqliteStrNDup(pName->z, pName->n);
drhd24cc422003-03-27 12:51:24 +000075 if( sqliteHashFind(&(db->aDb[tab->iDb].trigHash), zName,pName->n+1) ){
drhda93d232003-03-31 02:12:46 +000076 sqliteErrorMsg(pParse, "trigger %T already exists", pName);
drhe5f9c642003-01-13 23:27:31 +000077 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000078 }
drhd24cc422003-03-27 12:51:24 +000079 if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
drhda93d232003-03-31 02:12:46 +000080 sqliteErrorMsg(pParse, "cannot create trigger on system table");
drhd24cc422003-03-27 12:51:24 +000081 pParse->nErr++;
82 goto trigger_cleanup;
danielk1977d702fcc2002-05-26 23:24:40 +000083 }
drhd24cc422003-03-27 12:51:24 +000084 if( tab->pSelect && tr_tm != TK_INSTEAD ){
drhda93d232003-03-31 02:12:46 +000085 sqliteErrorMsg(pParse, "cannot create %s trigger on view: %S",
86 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
drhd24cc422003-03-27 12:51:24 +000087 goto trigger_cleanup;
88 }
89 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
drhda93d232003-03-31 02:12:46 +000090 sqliteErrorMsg(pParse, "cannot create INSTEAD OF"
91 " trigger on table: %S", pTableName, 0);
drhd24cc422003-03-27 12:51:24 +000092 goto trigger_cleanup;
93 }
94#ifndef SQLITE_OMIT_AUTHORIZATION
95 {
96 int code = SQLITE_CREATE_TRIGGER;
97 if( tab->iDb==1 ) code = SQLITE_CREATE_TEMP_TRIGGER;
98 if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
99 goto trigger_cleanup;
100 }
101 if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0)){
102 goto trigger_cleanup;
103 }
104 }
105#endif
danielk1977d702fcc2002-05-26 23:24:40 +0000106
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;
drhe5f9c642003-01-13 23:27:31 +0000114 nt->name = zName;
115 zName = 0;
drhd24cc422003-03-27 12:51:24 +0000116 nt->table = sqliteStrDup(pTableName->a[0].zName);
drhe4697f52002-05-23 02:09:03 +0000117 if( sqlite_malloc_failed ) goto trigger_cleanup;
drhd24cc422003-03-27 12:51:24 +0000118 nt->iDb = tab->iDb;
danielk1977c3f9bad2002-05-15 08:30:12 +0000119 nt->op = op;
120 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000121 nt->pWhen = sqliteExprDup(pWhen);
122 sqliteExprDelete(pWhen);
123 nt->pColumns = sqliteIdListDup(pColumns);
124 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000125 nt->foreach = foreach;
danielk1977633ed082002-05-17 00:05:58 +0000126 nt->step_list = pStepList;
danielk1977c3f9bad2002-05-15 08:30:12 +0000127
128 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000129 ** build the sqlite_master entry
130 */
drhe0bc4042002-06-25 01:09:11 +0000131 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000132 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000133 { OP_NewRecno, 0, 0, 0 },
134 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000135 { OP_String, 0, 0, 0 }, /* 2: trigger name */
136 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000137 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000138 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000139 { OP_MakeRecord, 5, 0, 0 },
140 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000141 };
142 int addr;
143 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000144
145 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000146 v = sqliteGetVdbe(pParse);
drhe4697f52002-05-23 02:09:03 +0000147 if( v==0 ) goto trigger_cleanup;
drhcabb0812002-09-14 13:47:32 +0000148 sqliteBeginWriteOperation(pParse, 0, 0);
drhd24cc422003-03-27 12:51:24 +0000149 sqliteOpenMasterTable(v, tab->iDb);
drhc977f7f2002-05-21 11:38:11 +0000150 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhd24cc422003-03-27 12:51:24 +0000151 sqliteVdbeChangeP3(v, addr, tab->iDb ? TEMP_MASTER_NAME : MASTER_NAME,
drhe0bc4042002-06-25 01:09:11 +0000152 P3_STATIC);
153 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
154 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000155 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhd24cc422003-03-27 12:51:24 +0000156 if( tab->iDb==0 ){
157 sqliteChangeCookie(db, v);
drhe0bc4042002-06-25 01:09:11 +0000158 }
159 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000160 sqliteEndWriteOperation(pParse);
161 }
162
danielk1977633ed082002-05-17 00:05:58 +0000163 if( !pParse->explain ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000164 /* Stick it in the hash-table */
drhd24cc422003-03-27 12:51:24 +0000165 sqliteHashInsert(&(db->aDb[nt->iDb].trigHash), nt->name, pName->n + 1, nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000166
167 /* Attach it to the table object */
168 nt->pNext = tab->pTrigger;
169 tab->pTrigger = nt;
drh0be9df02003-03-30 00:19:49 +0000170 sqliteSrcListDelete(pTableName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000171 return;
danielk1977f29ce552002-05-19 23:43:12 +0000172 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000173 sqliteFree(nt->name);
174 sqliteFree(nt->table);
175 sqliteFree(nt);
176 }
177
178trigger_cleanup:
179
drhe5f9c642003-01-13 23:27:31 +0000180 sqliteFree(zName);
drhd24cc422003-03-27 12:51:24 +0000181 sqliteSrcListDelete(pTableName);
danielk1977633ed082002-05-17 00:05:58 +0000182 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000183 sqliteExprDelete(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000184 sqliteDeleteTriggerStep(pStepList);
185}
danielk1977c3f9bad2002-05-15 08:30:12 +0000186
drh4b59ab52002-08-24 18:24:51 +0000187/*
188** Make a copy of all components of the given trigger step. This has
189** the effect of copying all Expr.token.z values into memory obtained
190** from sqliteMalloc(). As initially created, the Expr.token.z values
191** all point to the input string that was fed to the parser. But that
192** string is ephemeral - it will go away as soon as the sqlite_exec()
193** call that started the parser exits. This routine makes a persistent
194** copy of all the Expr.token.z strings so that the TriggerStep structure
195** will be valid even after the sqlite_exec() call returns.
196*/
197static void sqlitePersistTriggerStep(TriggerStep *p){
198 if( p->target.z ){
199 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
200 p->target.dyn = 1;
201 }
202 if( p->pSelect ){
203 Select *pNew = sqliteSelectDup(p->pSelect);
204 sqliteSelectDelete(p->pSelect);
205 p->pSelect = pNew;
206 }
207 if( p->pWhere ){
208 Expr *pNew = sqliteExprDup(p->pWhere);
209 sqliteExprDelete(p->pWhere);
210 p->pWhere = pNew;
211 }
212 if( p->pExprList ){
213 ExprList *pNew = sqliteExprListDup(p->pExprList);
214 sqliteExprListDelete(p->pExprList);
215 p->pExprList = pNew;
216 }
217 if( p->pIdList ){
218 IdList *pNew = sqliteIdListDup(p->pIdList);
219 sqliteIdListDelete(p->pIdList);
220 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000221 }
222}
223
drhc977f7f2002-05-21 11:38:11 +0000224/*
225** Turn a SELECT statement (that the pSelect parameter points to) into
226** a trigger step. Return a pointer to a TriggerStep structure.
227**
228** The parser calls this routine when it finds a SELECT statement in
229** body of a TRIGGER.
230*/
231TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000232 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000233 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000234
danielk1977633ed082002-05-17 00:05:58 +0000235 pTriggerStep->op = TK_SELECT;
236 pTriggerStep->pSelect = pSelect;
237 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000238 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000239
danielk1977633ed082002-05-17 00:05:58 +0000240 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000241}
242
drhc977f7f2002-05-21 11:38:11 +0000243/*
244** Build a trigger step out of an INSERT statement. Return a pointer
245** to the new trigger step.
246**
247** The parser calls this routine when it sees an INSERT inside the
248** body of a trigger.
249*/
danielk1977633ed082002-05-17 00:05:58 +0000250TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000251 Token *pTableName, /* Name of the table into which we insert */
252 IdList *pColumn, /* List of columns in pTableName to insert into */
253 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
254 Select *pSelect, /* A SELECT statement that supplies values */
255 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000256){
257 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000258 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000259
danielk1977633ed082002-05-17 00:05:58 +0000260 assert(pEList == 0 || pSelect == 0);
261 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000262
danielk1977633ed082002-05-17 00:05:58 +0000263 pTriggerStep->op = TK_INSERT;
264 pTriggerStep->pSelect = pSelect;
265 pTriggerStep->target = *pTableName;
266 pTriggerStep->pIdList = pColumn;
267 pTriggerStep->pExprList = pEList;
268 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000269 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000270
danielk1977633ed082002-05-17 00:05:58 +0000271 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000272}
273
drhc977f7f2002-05-21 11:38:11 +0000274/*
275** Construct a trigger step that implements an UPDATE statement and return
276** a pointer to that trigger step. The parser calls this routine when it
277** sees an UPDATE statement inside the body of a CREATE TRIGGER.
278*/
danielk1977633ed082002-05-17 00:05:58 +0000279TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000280 Token *pTableName, /* Name of the table to be updated */
281 ExprList *pEList, /* The SET clause: list of column and new values */
282 Expr *pWhere, /* The WHERE clause */
283 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
284){
danielk1977633ed082002-05-17 00:05:58 +0000285 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000286 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000287
danielk1977633ed082002-05-17 00:05:58 +0000288 pTriggerStep->op = TK_UPDATE;
289 pTriggerStep->target = *pTableName;
290 pTriggerStep->pExprList = pEList;
291 pTriggerStep->pWhere = pWhere;
292 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000293 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000294
danielk1977633ed082002-05-17 00:05:58 +0000295 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000296}
297
drhc977f7f2002-05-21 11:38:11 +0000298/*
299** Construct a trigger step that implements a DELETE statement and return
300** a pointer to that trigger step. The parser calls this routine when it
301** sees a DELETE statement inside the body of a CREATE TRIGGER.
302*/
303TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000304 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
305 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000306
danielk1977633ed082002-05-17 00:05:58 +0000307 pTriggerStep->op = TK_DELETE;
308 pTriggerStep->target = *pTableName;
309 pTriggerStep->pWhere = pWhere;
310 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000311 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000312
danielk1977633ed082002-05-17 00:05:58 +0000313 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000314}
315
danielk1977633ed082002-05-17 00:05:58 +0000316/*
317** Recursively delete a Trigger structure
318*/
drh1d1f3052002-05-21 13:18:25 +0000319void sqliteDeleteTrigger(Trigger *pTrigger){
drh4b59ab52002-08-24 18:24:51 +0000320 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000321 sqliteFree(pTrigger->name);
322 sqliteFree(pTrigger->table);
323 sqliteExprDelete(pTrigger->pWhen);
324 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000325 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000326}
327
328/*
danielk1977633ed082002-05-17 00:05:58 +0000329 * This function is called to drop a trigger from the database schema.
330 *
331 * This may be called directly from the parser, or from within
332 * sqliteDropTable(). In the latter case the "nested" argument is true.
333 *
334 * Note that this function does not delete the trigger entirely. Instead it
335 * removes it from the internal schema and places it in the trigDrop hash
336 * table. This is so that the trigger can be restored into the database schema
337 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000338 */
drhd24cc422003-03-27 12:51:24 +0000339void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000340 Trigger *pTrigger;
341 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000342 Vdbe *v;
drhd24cc422003-03-27 12:51:24 +0000343 int i;
344 const char *zDb;
345 const char *zName;
346 int nName;
347 sqlite *db = pParse->db;
danielk1977c3f9bad2002-05-15 08:30:12 +0000348
drhd24cc422003-03-27 12:51:24 +0000349 if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
350 assert( pName->nSrc==1 );
351 zDb = pName->a[0].zDatabase;
352 zName = pName->a[0].zName;
353 nName = strlen(zName);
354 for(i=0; i<db->nDb; i++){
drh812d7a22003-03-27 13:50:00 +0000355 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
356 if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
357 pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
drhd24cc422003-03-27 12:51:24 +0000358 if( pTrigger ) break;
danielk1977c3f9bad2002-05-15 08:30:12 +0000359 }
drhd24cc422003-03-27 12:51:24 +0000360 if( !pTrigger ){
drhda93d232003-03-31 02:12:46 +0000361 sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
drhd24cc422003-03-27 12:51:24 +0000362 goto drop_trigger_cleanup;
363 }
364 assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );
365 if( pTrigger->iDb>=2 ){
drhda93d232003-03-31 02:12:46 +0000366 sqliteErrorMsg(pParse, "triggers may not be removed from "
367 "auxiliary database %s", db->aDb[pTrigger->iDb].zName);
drhd24cc422003-03-27 12:51:24 +0000368 goto drop_trigger_cleanup;
369 }
370 pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName);
drhed6c8672003-01-12 18:02:16 +0000371 assert(pTable);
drhd24cc422003-03-27 12:51:24 +0000372 assert( pTable->iDb==pTrigger->iDb );
drhe5f9c642003-01-13 23:27:31 +0000373#ifndef SQLITE_OMIT_AUTHORIZATION
374 {
375 int code = SQLITE_DROP_TRIGGER;
drhd24cc422003-03-27 12:51:24 +0000376 if( pTable->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
drhe5f9c642003-01-13 23:27:31 +0000377 if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
drhd24cc422003-03-27 12:51:24 +0000378 sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->iDb),0) ){
drh0be9df02003-03-30 00:19:49 +0000379 goto drop_trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000380 }
drhed6c8672003-01-12 18:02:16 +0000381 }
drhe5f9c642003-01-13 23:27:31 +0000382#endif
danielk1977c3f9bad2002-05-15 08:30:12 +0000383
384 /*
drhe0bc4042002-06-25 01:09:11 +0000385 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000386 */
danielk1977633ed082002-05-17 00:05:58 +0000387 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000388 if( pTable->pTrigger == pTrigger ){
389 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000390 }else{
danielk1977633ed082002-05-17 00:05:58 +0000391 Trigger *cc = pTable->pTrigger;
392 while( cc ){
393 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000394 cc->pNext = cc->pNext->pNext;
395 break;
396 }
397 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000398 }
399 assert(cc);
400 }
drhd24cc422003-03-27 12:51:24 +0000401 sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
drhe0bc4042002-06-25 01:09:11 +0000402 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000403 }
404
drhe0bc4042002-06-25 01:09:11 +0000405 /* Generate code to destroy the database record of the trigger.
406 */
407 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000408 int base;
409 static VdbeOp dropTrigger[] = {
drhe0bc4042002-06-25 01:09:11 +0000410 { OP_Rewind, 0, ADDR(8), 0},
411 { OP_String, 0, 0, 0}, /* 1 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000412 { OP_MemStore, 1, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000413 { OP_MemLoad, 1, 0, 0}, /* 3 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000414 { OP_Column, 0, 1, 0},
drhe0bc4042002-06-25 01:09:11 +0000415 { OP_Ne, 0, ADDR(7), 0},
danielk1977c3f9bad2002-05-15 08:30:12 +0000416 { OP_Delete, 0, 0, 0},
drhe0bc4042002-06-25 01:09:11 +0000417 { OP_Next, 0, ADDR(3), 0}, /* 7 */
danielk1977c3f9bad2002-05-15 08:30:12 +0000418 };
419
drhcabb0812002-09-14 13:47:32 +0000420 sqliteBeginWriteOperation(pParse, 0, 0);
drhd24cc422003-03-27 12:51:24 +0000421 sqliteOpenMasterTable(v, pTable->iDb);
drhe0bc4042002-06-25 01:09:11 +0000422 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
423 sqliteVdbeChangeP3(v, base+1, zName, 0);
drhd24cc422003-03-27 12:51:24 +0000424 if( pTable->iDb==0 ){
425 sqliteChangeCookie(db, v);
drhdc379452002-05-15 12:45:43 +0000426 }
drhe0bc4042002-06-25 01:09:11 +0000427 sqliteVdbeAddOp(v, OP_Close, 0, 0);
428 sqliteEndWriteOperation(pParse);
danielk1977c3f9bad2002-05-15 08:30:12 +0000429 }
430
drhd24cc422003-03-27 12:51:24 +0000431drop_trigger_cleanup:
432 sqliteSrcListDelete(pName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000433}
434
drhc977f7f2002-05-21 11:38:11 +0000435/*
436** pEList is the SET clause of an UPDATE statement. Each entry
437** in pEList is of the format <id>=<expr>. If any of the entries
438** in pEList have an <id> which matches an identifier in pIdList,
439** then return TRUE. If pIdList==NULL, then it is considered a
440** wildcard that matches anything. Likewise if pEList==NULL then
441** it matches anything so always return true. Return false only
442** if there is no match.
443*/
444static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000445 int e;
446 if( !pIdList || !pEList ) return 1;
447 for(e=0; e<pEList->nExpr; e++){
448 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000449 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000450 return 0;
451}
452
453/* A global variable that is TRUE if we should always set up temp tables for
454 * for triggers, even if there are no triggers to code. This is used to test
455 * how much overhead the triggers algorithm is causing.
456 *
457 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
458 * The pragma is not documented since it is not really part of the interface
459 * to SQLite, just the test procedure.
460*/
461int always_code_trigger_setup = 0;
462
463/*
464 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
465 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
466 * found in the list specified as pTrigger.
467 */
468int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000469 Parse *pParse, /* Used to check for recursive triggers */
470 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000471 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
472 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
473 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000474 ExprList *pChanges /* Columns that change in an UPDATE statement */
475){
danielk1977633ed082002-05-17 00:05:58 +0000476 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000477
danielk1977633ed082002-05-17 00:05:58 +0000478 if( always_code_trigger_setup ){
479 return 1;
480 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000481
danielk1977633ed082002-05-17 00:05:58 +0000482 pTriggerCursor = pTrigger;
483 while( pTriggerCursor ){
484 if( pTriggerCursor->op == op &&
485 pTriggerCursor->tr_tm == tr_tm &&
486 pTriggerCursor->foreach == foreach &&
487 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000488 TriggerStack * ss;
489 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000490 while( ss && ss->pTrigger != pTrigger ){
491 ss = ss->pNext;
492 }
493 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000494 }
danielk1977633ed082002-05-17 00:05:58 +0000495 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000496 }
497
498 return 0;
499}
500
drhc977f7f2002-05-21 11:38:11 +0000501/*
502** Generate VDBE code for zero or more statements inside the body of a
503** trigger.
504*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000505static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000506 Parse *pParse, /* The parser context */
507 TriggerStep *pStepList, /* List of statements inside the trigger body */
508 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000509){
510 TriggerStep * pTriggerStep = pStepList;
511 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000512
danielk1977633ed082002-05-17 00:05:58 +0000513 while( pTriggerStep ){
514 int saveNTab = pParse->nTab;
515 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
516 pParse->trigStack->orconf = orconf;
517 switch( pTriggerStep->op ){
518 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000519 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
520 assert(ss);
521 assert(ss->pSrc);
522 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
523 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000524 break;
525 }
526 case TK_UPDATE: {
drh113088e2003-03-20 01:16:58 +0000527 SrcList *pSrc;
528 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
drhbd5a4512002-05-23 22:07:02 +0000529 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000530 sqliteUpdate(pParse, pSrc,
danielk19776f349032002-06-11 02:25:40 +0000531 sqliteExprListDup(pTriggerStep->pExprList),
532 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000533 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000534 break;
535 }
536 case TK_INSERT: {
drh113088e2003-03-20 01:16:58 +0000537 SrcList *pSrc;
538 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
539 sqliteInsert(pParse, pSrc,
540 sqliteExprListDup(pTriggerStep->pExprList),
541 sqliteSelectDup(pTriggerStep->pSelect),
542 sqliteIdListDup(pTriggerStep->pIdList), orconf);
danielk1977633ed082002-05-17 00:05:58 +0000543 break;
544 }
545 case TK_DELETE: {
drh113088e2003-03-20 01:16:58 +0000546 SrcList *pSrc;
drhbd5a4512002-05-23 22:07:02 +0000547 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000548 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
549 sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000550 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000551 break;
552 }
553 default:
554 assert(0);
555 }
556 pParse->nTab = saveNTab;
557 pTriggerStep = pTriggerStep->pNext;
558 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000559
danielk1977633ed082002-05-17 00:05:58 +0000560 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000561}
562
danielk1977633ed082002-05-17 00:05:58 +0000563/*
564** This is called to code FOR EACH ROW triggers.
565**
566** When the code that this function generates is executed, the following
567** must be true:
drhc977f7f2002-05-21 11:38:11 +0000568**
569** 1. No cursors may be open in the main database. (But newIdx and oldIdx
570** can be indices of cursors in temporary tables. See below.)
571**
danielk1977633ed082002-05-17 00:05:58 +0000572** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
573** a temporary vdbe cursor (index newIdx) must be open and pointing at
574** a row containing values to be substituted for new.* expressions in the
575** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000576**
danielk1977633ed082002-05-17 00:05:58 +0000577** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
578** a temporary vdbe cursor (index oldIdx) must be open and pointing at
579** a row containing values to be substituted for old.* expressions in the
580** trigger program(s).
581**
582*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000583int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000584 Parse *pParse, /* Parse context */
585 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
586 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
587 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
588 Table *pTab, /* The table to code triggers from */
589 int newIdx, /* The indice of the "new" row to access */
590 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000591 int orconf, /* ON CONFLICT policy */
592 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000593){
danielk1977c3f9bad2002-05-15 08:30:12 +0000594 Trigger * pTrigger;
595 TriggerStack * pTriggerStack;
596
danielk1977c3f9bad2002-05-15 08:30:12 +0000597 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
598 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
599
danielk1977633ed082002-05-17 00:05:58 +0000600 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000601
danielk1977633ed082002-05-17 00:05:58 +0000602 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000603 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000604 int fire_this = 0;
605
606 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000607 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
608 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000609 fire_this = 1;
610 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000611 while( pTriggerStack ){
612 if( pTriggerStack->pTrigger == pTrigger ){
613 fire_this = 0;
614 }
drh9adf9ac2002-05-15 11:44:13 +0000615 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000616 }
danielk1977f29ce552002-05-19 23:43:12 +0000617 if( op == TK_UPDATE && pTrigger->pColumns &&
618 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000619 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000620 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000621 }
622
drhe4697f52002-05-23 02:09:03 +0000623 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000624 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000625 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000626 Expr * whenExpr;
627
drhad3cab52002-05-24 02:04:32 +0000628 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000629
630 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000631 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000632 pTriggerStack->newIdx = newIdx;
633 pTriggerStack->oldIdx = oldIdx;
634 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000635 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000636 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000637 pParse->trigStack = pTriggerStack;
638
639 /* code the WHEN clause */
640 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
641 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000642 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000643 pParse->trigStack = pParse->trigStack->pNext;
644 sqliteFree(pTriggerStack);
645 sqliteExprDelete(whenExpr);
646 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000647 }
drhf5905aa2002-05-26 20:54:33 +0000648 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000649 sqliteExprDelete(whenExpr);
650
danielk1977633ed082002-05-17 00:05:58 +0000651 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000652
653 /* Pop the entry off the trigger stack */
654 pParse->trigStack = pParse->trigStack->pNext;
655 sqliteFree(pTriggerStack);
656
657 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
658 }
659 pTrigger = pTrigger->pNext;
660 }
661
662 return 0;
663}
664
665/*
danielk1977633ed082002-05-17 00:05:58 +0000666 * This function is called to code ON UPDATE and ON DELETE triggers on
667 * views.
668 *
669 * This function deletes the data pointed at by the pWhere and pChanges
670 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000671 */
danielk1977633ed082002-05-17 00:05:58 +0000672void sqliteViewTriggers(
673 Parse *pParse,
674 Table *pTab, /* The view to code triggers on */
675 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
676 int orconf, /* The ON CONFLICT policy specified as part of the
677 statement causing these triggers */
678 ExprList *pChanges /* If this is an statement causing triggers to fire
679 is an UPDATE, then this list holds the columns
680 to update and the expressions to update them to.
681 See comments for sqliteUpdate(). */
682){
danielk1977c3f9bad2002-05-15 08:30:12 +0000683 int oldIdx = -1;
684 int newIdx = -1;
685 int *aXRef = 0;
686 Vdbe *v;
687 int endOfLoop;
688 int startOfLoop;
689 Select theSelect;
690 Token tblNameToken;
691
692 assert(pTab->pSelect);
693
694 tblNameToken.z = pTab->zName;
695 tblNameToken.n = strlen(pTab->zName);
696
697 theSelect.isDistinct = 0;
698 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drh113088e2003-03-20 01:16:58 +0000699 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000700 theSelect.pWhere = pWhere; pWhere = 0;
701 theSelect.pGroupBy = 0;
702 theSelect.pHaving = 0;
703 theSelect.pOrderBy = 0;
704 theSelect.op = TK_SELECT; /* ?? */
705 theSelect.pPrior = 0;
706 theSelect.nLimit = -1;
707 theSelect.nOffset = -1;
708 theSelect.zSelect = 0;
709 theSelect.base = 0;
710
711 v = sqliteGetVdbe(pParse);
712 assert(v);
drhcabb0812002-09-14 13:47:32 +0000713 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000714
715 /* Allocate temp tables */
716 oldIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000717 sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000718 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000719 newIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000720 sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000721 }
722
723 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000724 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000725 goto trigger_cleanup;
726 }
727
728 /* loop thru the view snapshot, executing triggers for each row */
729 endOfLoop = sqliteVdbeMakeLabel(v);
730 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
731
732 /* Loop thru the view snapshot, executing triggers for each row */
733 startOfLoop = sqliteVdbeCurrentAddr(v);
734
735 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000736 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000737 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000738
739 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
740 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000741 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000742 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000743 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000744
745 for(ii=0; ii<pChanges->nExpr; ii++){
746 int jj;
747 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000748 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000749 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000750 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000751
752 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000753 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000754
755 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000756 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
757 aXRef[jj] = ii;
758 break;
759 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000760 }
761 if( jj>=pTab->nCol ){
drhda93d232003-03-31 02:12:46 +0000762 sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[ii].zName);
drh9adf9ac2002-05-15 11:44:13 +0000763 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000764 }
765 }
766
767 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
768
danielk1977633ed082002-05-17 00:05:58 +0000769 for(ii = 0; ii<pTab->nCol; ii++){
770 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000771 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000772 }else{
drh9adf9ac2002-05-15 11:44:13 +0000773 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000774 }
775 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000776
777 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
778 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
779 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
780
781 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000782 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000783 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000784 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000785 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000786 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000787 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000788 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000789 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000790 }
791
792 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
793
794 sqliteVdbeResolveLabel(v, endOfLoop);
795 sqliteEndWriteOperation(pParse);
796
797trigger_cleanup:
798 sqliteFree(aXRef);
799 sqliteExprListDelete(pChanges);
800 sqliteExprDelete(pWhere);
801 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000802 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000803 sqliteExprDelete(theSelect.pWhere);
804 return;
805}