blob: ca6dfa6182f33b30206fe56df98b3aabd6d60eaf [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 }
drha69d9162003-04-17 22:57:53 +000068 if( tab->iDb>=2 && !pParse->initFlag ){
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;
drha69d9162003-04-17 22:57:53 +0000127 while( pStepList ){
128 pStepList->pTrig = nt;
129 pStepList = pStepList->pNext;
130 }
131 pStepList = nt->step_list;
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;
drh0be9df02003-03-30 00:19:49 +0000175 sqliteSrcListDelete(pTableName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000176 return;
danielk1977f29ce552002-05-19 23:43:12 +0000177 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000178 sqliteFree(nt->name);
179 sqliteFree(nt->table);
180 sqliteFree(nt);
181 }
182
183trigger_cleanup:
184
drhe5f9c642003-01-13 23:27:31 +0000185 sqliteFree(zName);
drhd24cc422003-03-27 12:51:24 +0000186 sqliteSrcListDelete(pTableName);
danielk1977633ed082002-05-17 00:05:58 +0000187 sqliteIdListDelete(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000188 sqliteExprDelete(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000189 sqliteDeleteTriggerStep(pStepList);
190}
danielk1977c3f9bad2002-05-15 08:30:12 +0000191
drh4b59ab52002-08-24 18:24:51 +0000192/*
193** Make a copy of all components of the given trigger step. This has
194** the effect of copying all Expr.token.z values into memory obtained
195** from sqliteMalloc(). As initially created, the Expr.token.z values
196** all point to the input string that was fed to the parser. But that
197** string is ephemeral - it will go away as soon as the sqlite_exec()
198** call that started the parser exits. This routine makes a persistent
199** copy of all the Expr.token.z strings so that the TriggerStep structure
200** will be valid even after the sqlite_exec() call returns.
201*/
202static void sqlitePersistTriggerStep(TriggerStep *p){
203 if( p->target.z ){
204 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
205 p->target.dyn = 1;
206 }
207 if( p->pSelect ){
208 Select *pNew = sqliteSelectDup(p->pSelect);
209 sqliteSelectDelete(p->pSelect);
210 p->pSelect = pNew;
211 }
212 if( p->pWhere ){
213 Expr *pNew = sqliteExprDup(p->pWhere);
214 sqliteExprDelete(p->pWhere);
215 p->pWhere = pNew;
216 }
217 if( p->pExprList ){
218 ExprList *pNew = sqliteExprListDup(p->pExprList);
219 sqliteExprListDelete(p->pExprList);
220 p->pExprList = pNew;
221 }
222 if( p->pIdList ){
223 IdList *pNew = sqliteIdListDup(p->pIdList);
224 sqliteIdListDelete(p->pIdList);
225 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000226 }
227}
228
drhc977f7f2002-05-21 11:38:11 +0000229/*
230** Turn a SELECT statement (that the pSelect parameter points to) into
231** a trigger step. Return a pointer to a TriggerStep structure.
232**
233** The parser calls this routine when it finds a SELECT statement in
234** body of a TRIGGER.
235*/
236TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000237 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000238 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000239
danielk1977633ed082002-05-17 00:05:58 +0000240 pTriggerStep->op = TK_SELECT;
241 pTriggerStep->pSelect = pSelect;
242 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000243 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000244
danielk1977633ed082002-05-17 00:05:58 +0000245 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000246}
247
drhc977f7f2002-05-21 11:38:11 +0000248/*
249** Build a trigger step out of an INSERT statement. Return a pointer
250** to the new trigger step.
251**
252** The parser calls this routine when it sees an INSERT inside the
253** body of a trigger.
254*/
danielk1977633ed082002-05-17 00:05:58 +0000255TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000256 Token *pTableName, /* Name of the table into which we insert */
257 IdList *pColumn, /* List of columns in pTableName to insert into */
258 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
259 Select *pSelect, /* A SELECT statement that supplies values */
260 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000261){
262 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000263 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000264
danielk1977633ed082002-05-17 00:05:58 +0000265 assert(pEList == 0 || pSelect == 0);
266 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000267
danielk1977633ed082002-05-17 00:05:58 +0000268 pTriggerStep->op = TK_INSERT;
269 pTriggerStep->pSelect = pSelect;
270 pTriggerStep->target = *pTableName;
271 pTriggerStep->pIdList = pColumn;
272 pTriggerStep->pExprList = pEList;
273 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000274 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000275
danielk1977633ed082002-05-17 00:05:58 +0000276 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000277}
278
drhc977f7f2002-05-21 11:38:11 +0000279/*
280** Construct a trigger step that implements an UPDATE statement and return
281** a pointer to that trigger step. The parser calls this routine when it
282** sees an UPDATE statement inside the body of a CREATE TRIGGER.
283*/
danielk1977633ed082002-05-17 00:05:58 +0000284TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000285 Token *pTableName, /* Name of the table to be updated */
286 ExprList *pEList, /* The SET clause: list of column and new values */
287 Expr *pWhere, /* The WHERE clause */
288 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
289){
danielk1977633ed082002-05-17 00:05:58 +0000290 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000291 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000292
danielk1977633ed082002-05-17 00:05:58 +0000293 pTriggerStep->op = TK_UPDATE;
294 pTriggerStep->target = *pTableName;
295 pTriggerStep->pExprList = pEList;
296 pTriggerStep->pWhere = pWhere;
297 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000298 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000299
danielk1977633ed082002-05-17 00:05:58 +0000300 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000301}
302
drhc977f7f2002-05-21 11:38:11 +0000303/*
304** Construct a trigger step that implements a DELETE statement and return
305** a pointer to that trigger step. The parser calls this routine when it
306** sees a DELETE statement inside the body of a CREATE TRIGGER.
307*/
308TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000309 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
310 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000311
danielk1977633ed082002-05-17 00:05:58 +0000312 pTriggerStep->op = TK_DELETE;
313 pTriggerStep->target = *pTableName;
314 pTriggerStep->pWhere = pWhere;
315 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000316 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000317
danielk1977633ed082002-05-17 00:05:58 +0000318 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000319}
320
danielk1977633ed082002-05-17 00:05:58 +0000321/*
322** Recursively delete a Trigger structure
323*/
drh1d1f3052002-05-21 13:18:25 +0000324void sqliteDeleteTrigger(Trigger *pTrigger){
drh4b59ab52002-08-24 18:24:51 +0000325 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000326 sqliteFree(pTrigger->name);
327 sqliteFree(pTrigger->table);
328 sqliteExprDelete(pTrigger->pWhen);
329 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000330 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000331}
332
333/*
danielk1977633ed082002-05-17 00:05:58 +0000334 * This function is called to drop a trigger from the database schema.
335 *
336 * This may be called directly from the parser, or from within
337 * sqliteDropTable(). In the latter case the "nested" argument is true.
338 *
339 * Note that this function does not delete the trigger entirely. Instead it
340 * removes it from the internal schema and places it in the trigDrop hash
341 * table. This is so that the trigger can be restored into the database schema
342 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000343 */
drhd24cc422003-03-27 12:51:24 +0000344void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000345 Trigger *pTrigger;
346 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000347 Vdbe *v;
drhd24cc422003-03-27 12:51:24 +0000348 int i;
349 const char *zDb;
350 const char *zName;
351 int nName;
352 sqlite *db = pParse->db;
danielk1977c3f9bad2002-05-15 08:30:12 +0000353
drhd24cc422003-03-27 12:51:24 +0000354 if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
355 assert( pName->nSrc==1 );
356 zDb = pName->a[0].zDatabase;
357 zName = pName->a[0].zName;
358 nName = strlen(zName);
359 for(i=0; i<db->nDb; i++){
drh812d7a22003-03-27 13:50:00 +0000360 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
361 if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
362 pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
drhd24cc422003-03-27 12:51:24 +0000363 if( pTrigger ) break;
danielk1977c3f9bad2002-05-15 08:30:12 +0000364 }
drhd24cc422003-03-27 12:51:24 +0000365 if( !pTrigger ){
drhda93d232003-03-31 02:12:46 +0000366 sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
drhd24cc422003-03-27 12:51:24 +0000367 goto drop_trigger_cleanup;
368 }
369 assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );
370 if( pTrigger->iDb>=2 ){
drhda93d232003-03-31 02:12:46 +0000371 sqliteErrorMsg(pParse, "triggers may not be removed from "
372 "auxiliary database %s", db->aDb[pTrigger->iDb].zName);
drhd24cc422003-03-27 12:51:24 +0000373 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;
drha69d9162003-04-17 22:57:53 +0000520 int saveUseDb = pParse->useDb;
danielk1977633ed082002-05-17 00:05:58 +0000521 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
522 pParse->trigStack->orconf = orconf;
drha69d9162003-04-17 22:57:53 +0000523 pParse->useDb = pTriggerStep->pTrig->iDb;
danielk1977633ed082002-05-17 00:05:58 +0000524 switch( pTriggerStep->op ){
525 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000526 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
527 assert(ss);
528 assert(ss->pSrc);
529 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
530 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000531 break;
532 }
533 case TK_UPDATE: {
drh113088e2003-03-20 01:16:58 +0000534 SrcList *pSrc;
535 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
drhbd5a4512002-05-23 22:07:02 +0000536 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000537 sqliteUpdate(pParse, pSrc,
danielk19776f349032002-06-11 02:25:40 +0000538 sqliteExprListDup(pTriggerStep->pExprList),
539 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000540 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000541 break;
542 }
543 case TK_INSERT: {
drh113088e2003-03-20 01:16:58 +0000544 SrcList *pSrc;
545 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
546 sqliteInsert(pParse, pSrc,
547 sqliteExprListDup(pTriggerStep->pExprList),
548 sqliteSelectDup(pTriggerStep->pSelect),
549 sqliteIdListDup(pTriggerStep->pIdList), orconf);
danielk1977633ed082002-05-17 00:05:58 +0000550 break;
551 }
552 case TK_DELETE: {
drh113088e2003-03-20 01:16:58 +0000553 SrcList *pSrc;
drhbd5a4512002-05-23 22:07:02 +0000554 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000555 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
556 sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000557 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000558 break;
559 }
560 default:
561 assert(0);
562 }
563 pParse->nTab = saveNTab;
drha69d9162003-04-17 22:57:53 +0000564 pParse->useDb = saveUseDb;
danielk1977633ed082002-05-17 00:05:58 +0000565 pTriggerStep = pTriggerStep->pNext;
566 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000567
danielk1977633ed082002-05-17 00:05:58 +0000568 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000569}
570
danielk1977633ed082002-05-17 00:05:58 +0000571/*
572** This is called to code FOR EACH ROW triggers.
573**
574** When the code that this function generates is executed, the following
575** must be true:
drhc977f7f2002-05-21 11:38:11 +0000576**
577** 1. No cursors may be open in the main database. (But newIdx and oldIdx
578** can be indices of cursors in temporary tables. See below.)
579**
danielk1977633ed082002-05-17 00:05:58 +0000580** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
581** a temporary vdbe cursor (index newIdx) must be open and pointing at
582** a row containing values to be substituted for new.* expressions in the
583** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000584**
danielk1977633ed082002-05-17 00:05:58 +0000585** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
586** a temporary vdbe cursor (index oldIdx) must be open and pointing at
587** a row containing values to be substituted for old.* expressions in the
588** trigger program(s).
589**
590*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000591int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000592 Parse *pParse, /* Parse context */
593 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
594 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
595 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
596 Table *pTab, /* The table to code triggers from */
597 int newIdx, /* The indice of the "new" row to access */
598 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000599 int orconf, /* ON CONFLICT policy */
600 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000601){
danielk1977c3f9bad2002-05-15 08:30:12 +0000602 Trigger * pTrigger;
603 TriggerStack * pTriggerStack;
604
danielk1977c3f9bad2002-05-15 08:30:12 +0000605 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
606 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
607
danielk1977633ed082002-05-17 00:05:58 +0000608 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000609
danielk1977633ed082002-05-17 00:05:58 +0000610 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000611 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000612 int fire_this = 0;
613
614 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000615 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
616 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000617 fire_this = 1;
618 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000619 while( pTriggerStack ){
620 if( pTriggerStack->pTrigger == pTrigger ){
621 fire_this = 0;
622 }
drh9adf9ac2002-05-15 11:44:13 +0000623 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000624 }
danielk1977f29ce552002-05-19 23:43:12 +0000625 if( op == TK_UPDATE && pTrigger->pColumns &&
626 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000627 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000628 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000629 }
630
drhe4697f52002-05-23 02:09:03 +0000631 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000632 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000633 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000634 Expr * whenExpr;
635
drhad3cab52002-05-24 02:04:32 +0000636 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000637
638 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000639 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000640 pTriggerStack->newIdx = newIdx;
641 pTriggerStack->oldIdx = oldIdx;
642 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000643 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000644 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000645 pParse->trigStack = pTriggerStack;
646
647 /* code the WHEN clause */
648 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
649 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000650 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000651 pParse->trigStack = pParse->trigStack->pNext;
652 sqliteFree(pTriggerStack);
653 sqliteExprDelete(whenExpr);
654 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000655 }
drhf5905aa2002-05-26 20:54:33 +0000656 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000657 sqliteExprDelete(whenExpr);
658
danielk1977633ed082002-05-17 00:05:58 +0000659 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000660
661 /* Pop the entry off the trigger stack */
662 pParse->trigStack = pParse->trigStack->pNext;
663 sqliteFree(pTriggerStack);
664
665 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
666 }
667 pTrigger = pTrigger->pNext;
668 }
669
670 return 0;
671}
672
673/*
danielk1977633ed082002-05-17 00:05:58 +0000674 * This function is called to code ON UPDATE and ON DELETE triggers on
675 * views.
676 *
677 * This function deletes the data pointed at by the pWhere and pChanges
678 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000679 */
danielk1977633ed082002-05-17 00:05:58 +0000680void sqliteViewTriggers(
681 Parse *pParse,
682 Table *pTab, /* The view to code triggers on */
683 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
684 int orconf, /* The ON CONFLICT policy specified as part of the
685 statement causing these triggers */
686 ExprList *pChanges /* If this is an statement causing triggers to fire
687 is an UPDATE, then this list holds the columns
688 to update and the expressions to update them to.
689 See comments for sqliteUpdate(). */
690){
danielk1977c3f9bad2002-05-15 08:30:12 +0000691 int oldIdx = -1;
692 int newIdx = -1;
693 int *aXRef = 0;
694 Vdbe *v;
695 int endOfLoop;
696 int startOfLoop;
697 Select theSelect;
698 Token tblNameToken;
699
700 assert(pTab->pSelect);
701
702 tblNameToken.z = pTab->zName;
703 tblNameToken.n = strlen(pTab->zName);
704
705 theSelect.isDistinct = 0;
706 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drh113088e2003-03-20 01:16:58 +0000707 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000708 theSelect.pWhere = pWhere; pWhere = 0;
709 theSelect.pGroupBy = 0;
710 theSelect.pHaving = 0;
711 theSelect.pOrderBy = 0;
712 theSelect.op = TK_SELECT; /* ?? */
713 theSelect.pPrior = 0;
714 theSelect.nLimit = -1;
715 theSelect.nOffset = -1;
716 theSelect.zSelect = 0;
717 theSelect.base = 0;
718
719 v = sqliteGetVdbe(pParse);
720 assert(v);
drhcabb0812002-09-14 13:47:32 +0000721 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000722
723 /* Allocate temp tables */
724 oldIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000725 sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000726 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000727 newIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000728 sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000729 }
730
731 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000732 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000733 goto trigger_cleanup;
734 }
735
736 /* loop thru the view snapshot, executing triggers for each row */
737 endOfLoop = sqliteVdbeMakeLabel(v);
738 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
739
740 /* Loop thru the view snapshot, executing triggers for each row */
741 startOfLoop = sqliteVdbeCurrentAddr(v);
742
743 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000744 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000745 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000746
747 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
748 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000749 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000750 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000751 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000752
753 for(ii=0; ii<pChanges->nExpr; ii++){
754 int jj;
755 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000756 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000757 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000758 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000759
760 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000761 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000762
763 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000764 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
765 aXRef[jj] = ii;
766 break;
767 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000768 }
769 if( jj>=pTab->nCol ){
drhda93d232003-03-31 02:12:46 +0000770 sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[ii].zName);
drh9adf9ac2002-05-15 11:44:13 +0000771 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000772 }
773 }
774
775 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
776
danielk1977633ed082002-05-17 00:05:58 +0000777 for(ii = 0; ii<pTab->nCol; ii++){
778 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000779 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000780 }else{
drh9adf9ac2002-05-15 11:44:13 +0000781 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000782 }
783 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000784
785 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
786 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
787 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
788
789 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000790 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000791 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000792 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000793 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000794 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000795 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000796 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000797 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000798 }
799
800 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
801
802 sqliteVdbeResolveLabel(v, endOfLoop);
803 sqliteEndWriteOperation(pParse);
804
805trigger_cleanup:
806 sqliteFree(aXRef);
807 sqliteExprListDelete(pChanges);
808 sqliteExprDelete(pWhere);
809 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000810 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000811 sqliteExprDelete(theSelect.pWhere);
812 return;
813}