blob: 7124add968cb10638c22b3067d0b99cf0cdf31c2 [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*/
drhf0f258b2003-04-21 18:48:45 +000018void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
drh4b59ab52002-08-24 18:24:51 +000019 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/*
drhf0f258b2003-04-21 18:48:45 +000034** This is called by the parser when it sees a CREATE TRIGGER statement
35** up to the point of the BEGIN before the trigger actions. A Trigger
36** structure is generated based on the information available and stored
37** in pParse->pNewTrigger. After the trigger actions have been parsed, the
38** sqliteFinishTrigger() function is called to complete the trigger
39** construction process.
drh9adf9ac2002-05-15 11:44:13 +000040*/
drhf0f258b2003-04-21 18:48:45 +000041void sqliteBeginTrigger(
drh9adf9ac2002-05-15 11:44:13 +000042 Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
danielk1977633ed082002-05-17 00:05:58 +000043 Token *pName, /* The name of the trigger */
danielk1977d702fcc2002-05-26 23:24:40 +000044 int tr_tm, /* One of TK_BEFORE, TK_AFTER , TK_INSTEAD */
drh9adf9ac2002-05-15 11:44:13 +000045 int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
danielk1977633ed082002-05-17 00:05:58 +000046 IdList *pColumns, /* column list if this is an UPDATE OF trigger */
drhd24cc422003-03-27 12:51:24 +000047 SrcList *pTableName,/* The name of the table/view the trigger applies to */
drh9adf9ac2002-05-15 11:44:13 +000048 int foreach, /* One of TK_ROW or TK_STATEMENT */
49 Expr *pWhen, /* WHEN clause */
drhf0f258b2003-04-21 18:48:45 +000050 int isTemp /* True if the TEMPORARY keyword is present */
drh9adf9ac2002-05-15 11:44:13 +000051){
52 Trigger *nt;
53 Table *tab;
drhf0f258b2003-04-21 18:48:45 +000054 char *zName = 0; /* Name of the trigger */
drhd24cc422003-03-27 12:51:24 +000055 sqlite *db = pParse->db;
drhf0f258b2003-04-21 18:48:45 +000056 int iDb; /* When database to store the trigger in */
drhed6c8672003-01-12 18:02:16 +000057
danielk1977c3f9bad2002-05-15 08:30:12 +000058 /* Check that:
drh9adf9ac2002-05-15 11:44:13 +000059 ** 1. the trigger name does not already exist.
drhf0f258b2003-04-21 18:48:45 +000060 ** 2. the table (or view) does exist in the same database as the trigger.
danielk1977d702fcc2002-05-26 23:24:40 +000061 ** 3. that we are not trying to create a trigger on the sqlite_master table
62 ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
63 ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
drh9adf9ac2002-05-15 11:44:13 +000064 */
drhd24cc422003-03-27 12:51:24 +000065 if( sqlite_malloc_failed ) goto trigger_cleanup;
66 assert( pTableName->nSrc==1 );
drh812d7a22003-03-27 13:50:00 +000067 tab = sqliteSrcListLookup(pParse, pTableName);
drhd24cc422003-03-27 12:51:24 +000068 if( !tab ){
69 goto trigger_cleanup;
70 }
drhf0f258b2003-04-21 18:48:45 +000071 iDb = isTemp ? 1 : tab->iDb;
72 if( iDb>=2 && !pParse->initFlag ){
drhda93d232003-03-31 02:12:46 +000073 sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
74 "database %s", db->aDb[tab->iDb].zName);
drhd24cc422003-03-27 12:51:24 +000075 goto trigger_cleanup;
76 }
77
drhe5f9c642003-01-13 23:27:31 +000078 zName = sqliteStrNDup(pName->z, pName->n);
drhf0f258b2003-04-21 18:48:45 +000079 if( sqliteHashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){
drhda93d232003-03-31 02:12:46 +000080 sqliteErrorMsg(pParse, "trigger %T already exists", pName);
drhe5f9c642003-01-13 23:27:31 +000081 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +000082 }
drhd24cc422003-03-27 12:51:24 +000083 if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
drhda93d232003-03-31 02:12:46 +000084 sqliteErrorMsg(pParse, "cannot create trigger on system table");
drhd24cc422003-03-27 12:51:24 +000085 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 ){
drhda93d232003-03-31 02:12:46 +000089 sqliteErrorMsg(pParse, "cannot create %s trigger on view: %S",
90 (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
drhd24cc422003-03-27 12:51:24 +000091 goto trigger_cleanup;
92 }
93 if( !tab->pSelect && tr_tm == TK_INSTEAD ){
drhda93d232003-03-31 02:12:46 +000094 sqliteErrorMsg(pParse, "cannot create INSTEAD OF"
95 " trigger on table: %S", pTableName, 0);
drhd24cc422003-03-27 12:51:24 +000096 goto trigger_cleanup;
97 }
98#ifndef SQLITE_OMIT_AUTHORIZATION
99 {
100 int code = SQLITE_CREATE_TRIGGER;
drhf0f258b2003-04-21 18:48:45 +0000101 if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
drhd24cc422003-03-27 12:51:24 +0000102 if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
103 goto trigger_cleanup;
104 }
105 if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0)){
106 goto trigger_cleanup;
107 }
108 }
109#endif
danielk1977d702fcc2002-05-26 23:24:40 +0000110
111 if (tr_tm == TK_INSTEAD){
112 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +0000113 }
114
115 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +0000116 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +0000117 if( nt==0 ) goto trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000118 nt->name = zName;
119 zName = 0;
drhd24cc422003-03-27 12:51:24 +0000120 nt->table = sqliteStrDup(pTableName->a[0].zName);
drhe4697f52002-05-23 02:09:03 +0000121 if( sqlite_malloc_failed ) goto trigger_cleanup;
drhf0f258b2003-04-21 18:48:45 +0000122 nt->iDb = iDb;
danielk1977c3f9bad2002-05-15 08:30:12 +0000123 nt->op = op;
124 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000125 nt->pWhen = sqliteExprDup(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000126 nt->pColumns = sqliteIdListDup(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000127 nt->foreach = foreach;
drhf0f258b2003-04-21 18:48:45 +0000128 assert( pParse->pNewTrigger==0 );
129 pParse->pNewTrigger = nt;
130
131trigger_cleanup:
132 sqliteFree(zName);
133 sqliteSrcListDelete(pTableName);
134 sqliteIdListDelete(pColumns);
135 sqliteExprDelete(pWhen);
136}
137
138/*
139** This routine is called after all of the trigger actions have been parsed
140** in order to complete the process of building the trigger.
141*/
142void sqliteFinishTrigger(
143 Parse *pParse, /* Parser context */
144 TriggerStep *pStepList, /* The triggered program */
145 Token *pAll /* Token that describes the complete CREATE TRIGGER */
146){
147 Trigger *nt; /* The trigger whose construction is finishing up */
148 sqlite *db = pParse->db; /* The database */
149
150 if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
151 nt = pParse->pNewTrigger;
152 pParse->pNewTrigger = 0;
danielk1977633ed082002-05-17 00:05:58 +0000153 nt->step_list = pStepList;
drha69d9162003-04-17 22:57:53 +0000154 while( pStepList ){
155 pStepList->pTrig = nt;
156 pStepList = pStepList->pNext;
157 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000158
159 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000160 ** build the sqlite_master entry
161 */
drhe0bc4042002-06-25 01:09:11 +0000162 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000163 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000164 { OP_NewRecno, 0, 0, 0 },
165 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000166 { OP_String, 0, 0, 0 }, /* 2: trigger name */
167 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000168 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000169 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000170 { OP_MakeRecord, 5, 0, 0 },
171 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000172 };
173 int addr;
174 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000175
176 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000177 v = sqliteGetVdbe(pParse);
drhf0f258b2003-04-21 18:48:45 +0000178 if( v==0 ) goto triggerfinish_cleanup;
drhcabb0812002-09-14 13:47:32 +0000179 sqliteBeginWriteOperation(pParse, 0, 0);
drhf0f258b2003-04-21 18:48:45 +0000180 sqliteOpenMasterTable(v, nt->iDb==1);
drhc977f7f2002-05-21 11:38:11 +0000181 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhe0bc4042002-06-25 01:09:11 +0000182 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
183 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000184 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhf0f258b2003-04-21 18:48:45 +0000185 if( nt->iDb==0 ){
drhd24cc422003-03-27 12:51:24 +0000186 sqliteChangeCookie(db, v);
drhe0bc4042002-06-25 01:09:11 +0000187 }
188 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000189 sqliteEndWriteOperation(pParse);
190 }
191
danielk1977633ed082002-05-17 00:05:58 +0000192 if( !pParse->explain ){
drhf0f258b2003-04-21 18:48:45 +0000193 Table *pTab;
194 sqliteHashInsert(&db->aDb[nt->iDb].trigHash,
195 nt->name, strlen(nt->name)+1, nt);
196 pTab = sqliteLocateTable(pParse, nt->table, 0);
197 assert( pTab!=0 );
198 nt->pNext = pTab->pTrigger;
199 pTab->pTrigger = nt;
danielk1977f29ce552002-05-19 23:43:12 +0000200 }else{
drhf0f258b2003-04-21 18:48:45 +0000201 sqliteDeleteTrigger(nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000202 }
203
drhf0f258b2003-04-21 18:48:45 +0000204triggerfinish_cleanup:
205 sqliteDeleteTrigger(pParse->pNewTrigger);
206 pParse->pNewTrigger = 0;
drh4b59ab52002-08-24 18:24:51 +0000207 sqliteDeleteTriggerStep(pStepList);
208}
danielk1977c3f9bad2002-05-15 08:30:12 +0000209
drh4b59ab52002-08-24 18:24:51 +0000210/*
211** Make a copy of all components of the given trigger step. This has
212** the effect of copying all Expr.token.z values into memory obtained
213** from sqliteMalloc(). As initially created, the Expr.token.z values
214** all point to the input string that was fed to the parser. But that
215** string is ephemeral - it will go away as soon as the sqlite_exec()
216** call that started the parser exits. This routine makes a persistent
217** copy of all the Expr.token.z strings so that the TriggerStep structure
218** will be valid even after the sqlite_exec() call returns.
219*/
220static void sqlitePersistTriggerStep(TriggerStep *p){
221 if( p->target.z ){
222 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
223 p->target.dyn = 1;
224 }
225 if( p->pSelect ){
226 Select *pNew = sqliteSelectDup(p->pSelect);
227 sqliteSelectDelete(p->pSelect);
228 p->pSelect = pNew;
229 }
230 if( p->pWhere ){
231 Expr *pNew = sqliteExprDup(p->pWhere);
232 sqliteExprDelete(p->pWhere);
233 p->pWhere = pNew;
234 }
235 if( p->pExprList ){
236 ExprList *pNew = sqliteExprListDup(p->pExprList);
237 sqliteExprListDelete(p->pExprList);
238 p->pExprList = pNew;
239 }
240 if( p->pIdList ){
241 IdList *pNew = sqliteIdListDup(p->pIdList);
242 sqliteIdListDelete(p->pIdList);
243 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000244 }
245}
246
drhc977f7f2002-05-21 11:38:11 +0000247/*
248** Turn a SELECT statement (that the pSelect parameter points to) into
249** a trigger step. Return a pointer to a TriggerStep structure.
250**
251** The parser calls this routine when it finds a SELECT statement in
252** body of a TRIGGER.
253*/
254TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000255 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000256 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000257
danielk1977633ed082002-05-17 00:05:58 +0000258 pTriggerStep->op = TK_SELECT;
259 pTriggerStep->pSelect = pSelect;
260 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000261 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000262
danielk1977633ed082002-05-17 00:05:58 +0000263 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000264}
265
drhc977f7f2002-05-21 11:38:11 +0000266/*
267** Build a trigger step out of an INSERT statement. Return a pointer
268** to the new trigger step.
269**
270** The parser calls this routine when it sees an INSERT inside the
271** body of a trigger.
272*/
danielk1977633ed082002-05-17 00:05:58 +0000273TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000274 Token *pTableName, /* Name of the table into which we insert */
275 IdList *pColumn, /* List of columns in pTableName to insert into */
276 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
277 Select *pSelect, /* A SELECT statement that supplies values */
278 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000279){
280 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000281 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000282
danielk1977633ed082002-05-17 00:05:58 +0000283 assert(pEList == 0 || pSelect == 0);
284 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000285
danielk1977633ed082002-05-17 00:05:58 +0000286 pTriggerStep->op = TK_INSERT;
287 pTriggerStep->pSelect = pSelect;
288 pTriggerStep->target = *pTableName;
289 pTriggerStep->pIdList = pColumn;
290 pTriggerStep->pExprList = pEList;
291 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000292 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000293
danielk1977633ed082002-05-17 00:05:58 +0000294 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000295}
296
drhc977f7f2002-05-21 11:38:11 +0000297/*
298** Construct a trigger step that implements an UPDATE statement and return
299** a pointer to that trigger step. The parser calls this routine when it
300** sees an UPDATE statement inside the body of a CREATE TRIGGER.
301*/
danielk1977633ed082002-05-17 00:05:58 +0000302TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000303 Token *pTableName, /* Name of the table to be updated */
304 ExprList *pEList, /* The SET clause: list of column and new values */
305 Expr *pWhere, /* The WHERE clause */
306 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
307){
danielk1977633ed082002-05-17 00:05:58 +0000308 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000309 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000310
danielk1977633ed082002-05-17 00:05:58 +0000311 pTriggerStep->op = TK_UPDATE;
312 pTriggerStep->target = *pTableName;
313 pTriggerStep->pExprList = pEList;
314 pTriggerStep->pWhere = pWhere;
315 pTriggerStep->orconf = orconf;
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
drhc977f7f2002-05-21 11:38:11 +0000321/*
322** Construct a trigger step that implements a DELETE statement and return
323** a pointer to that trigger step. The parser calls this routine when it
324** sees a DELETE statement inside the body of a CREATE TRIGGER.
325*/
326TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000327 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
328 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000329
danielk1977633ed082002-05-17 00:05:58 +0000330 pTriggerStep->op = TK_DELETE;
331 pTriggerStep->target = *pTableName;
332 pTriggerStep->pWhere = pWhere;
333 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000334 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000335
danielk1977633ed082002-05-17 00:05:58 +0000336 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000337}
338
danielk1977633ed082002-05-17 00:05:58 +0000339/*
340** Recursively delete a Trigger structure
341*/
drh1d1f3052002-05-21 13:18:25 +0000342void sqliteDeleteTrigger(Trigger *pTrigger){
drhf0f258b2003-04-21 18:48:45 +0000343 if( pTrigger==0 ) return;
drh4b59ab52002-08-24 18:24:51 +0000344 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000345 sqliteFree(pTrigger->name);
346 sqliteFree(pTrigger->table);
347 sqliteExprDelete(pTrigger->pWhen);
348 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000349 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000350}
351
352/*
danielk1977633ed082002-05-17 00:05:58 +0000353 * This function is called to drop a trigger from the database schema.
354 *
355 * This may be called directly from the parser, or from within
356 * sqliteDropTable(). In the latter case the "nested" argument is true.
357 *
358 * Note that this function does not delete the trigger entirely. Instead it
359 * removes it from the internal schema and places it in the trigDrop hash
360 * table. This is so that the trigger can be restored into the database schema
361 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000362 */
drhd24cc422003-03-27 12:51:24 +0000363void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000364 Trigger *pTrigger;
365 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000366 Vdbe *v;
drhd24cc422003-03-27 12:51:24 +0000367 int i;
368 const char *zDb;
369 const char *zName;
370 int nName;
371 sqlite *db = pParse->db;
danielk1977c3f9bad2002-05-15 08:30:12 +0000372
drhd24cc422003-03-27 12:51:24 +0000373 if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
374 assert( pName->nSrc==1 );
375 zDb = pName->a[0].zDatabase;
376 zName = pName->a[0].zName;
377 nName = strlen(zName);
378 for(i=0; i<db->nDb; i++){
drh812d7a22003-03-27 13:50:00 +0000379 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
380 if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
381 pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
drhd24cc422003-03-27 12:51:24 +0000382 if( pTrigger ) break;
danielk1977c3f9bad2002-05-15 08:30:12 +0000383 }
drhd24cc422003-03-27 12:51:24 +0000384 if( !pTrigger ){
drhda93d232003-03-31 02:12:46 +0000385 sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
drhd24cc422003-03-27 12:51:24 +0000386 goto drop_trigger_cleanup;
387 }
drhf0f258b2003-04-21 18:48:45 +0000388 assert( pTrigger->iDb<db->nDb );
drhd24cc422003-03-27 12:51:24 +0000389 if( pTrigger->iDb>=2 ){
drhda93d232003-03-31 02:12:46 +0000390 sqliteErrorMsg(pParse, "triggers may not be removed from "
391 "auxiliary database %s", db->aDb[pTrigger->iDb].zName);
drhd24cc422003-03-27 12:51:24 +0000392 goto drop_trigger_cleanup;
393 }
394 pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName);
drhed6c8672003-01-12 18:02:16 +0000395 assert(pTable);
drhf0f258b2003-04-21 18:48:45 +0000396 assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
drhe5f9c642003-01-13 23:27:31 +0000397#ifndef SQLITE_OMIT_AUTHORIZATION
398 {
399 int code = SQLITE_DROP_TRIGGER;
drhf0f258b2003-04-21 18:48:45 +0000400 if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
drhe5f9c642003-01-13 23:27:31 +0000401 if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
drhf0f258b2003-04-21 18:48:45 +0000402 sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTrigger->iDb),0) ){
drh0be9df02003-03-30 00:19:49 +0000403 goto drop_trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000404 }
drhed6c8672003-01-12 18:02:16 +0000405 }
drhe5f9c642003-01-13 23:27:31 +0000406#endif
danielk1977c3f9bad2002-05-15 08:30:12 +0000407
drhf0f258b2003-04-21 18:48:45 +0000408 /* Generate code to destroy the database record of the trigger.
409 */
410 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
411 int base;
412 static VdbeOp dropTrigger[] = {
413 { OP_Rewind, 0, ADDR(8), 0},
414 { OP_String, 0, 0, 0}, /* 1 */
415 { OP_MemStore, 1, 1, 0},
416 { OP_MemLoad, 1, 0, 0}, /* 3 */
417 { OP_Column, 0, 1, 0},
418 { OP_Ne, 0, ADDR(7), 0},
419 { OP_Delete, 0, 0, 0},
420 { OP_Next, 0, ADDR(3), 0}, /* 7 */
421 };
422
423 sqliteBeginWriteOperation(pParse, 0, 0);
424 sqliteOpenMasterTable(v, pTrigger->iDb);
425 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
426 sqliteVdbeChangeP3(v, base+1, zName, 0);
427 if( pTrigger->iDb==0 ){
428 sqliteChangeCookie(db, v);
429 }
430 sqliteVdbeAddOp(v, OP_Close, 0, 0);
431 sqliteEndWriteOperation(pParse);
432 }
433
danielk1977c3f9bad2002-05-15 08:30:12 +0000434 /*
drhe0bc4042002-06-25 01:09:11 +0000435 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000436 */
danielk1977633ed082002-05-17 00:05:58 +0000437 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000438 if( pTable->pTrigger == pTrigger ){
439 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000440 }else{
danielk1977633ed082002-05-17 00:05:58 +0000441 Trigger *cc = pTable->pTrigger;
442 while( cc ){
443 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000444 cc->pNext = cc->pNext->pNext;
445 break;
446 }
447 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000448 }
449 assert(cc);
450 }
drhd24cc422003-03-27 12:51:24 +0000451 sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
drhe0bc4042002-06-25 01:09:11 +0000452 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000453 }
454
drhd24cc422003-03-27 12:51:24 +0000455drop_trigger_cleanup:
456 sqliteSrcListDelete(pName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000457}
458
drhc977f7f2002-05-21 11:38:11 +0000459/*
460** pEList is the SET clause of an UPDATE statement. Each entry
461** in pEList is of the format <id>=<expr>. If any of the entries
462** in pEList have an <id> which matches an identifier in pIdList,
463** then return TRUE. If pIdList==NULL, then it is considered a
464** wildcard that matches anything. Likewise if pEList==NULL then
465** it matches anything so always return true. Return false only
466** if there is no match.
467*/
468static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000469 int e;
470 if( !pIdList || !pEList ) return 1;
471 for(e=0; e<pEList->nExpr; e++){
472 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000473 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000474 return 0;
475}
476
477/* A global variable that is TRUE if we should always set up temp tables for
478 * for triggers, even if there are no triggers to code. This is used to test
479 * how much overhead the triggers algorithm is causing.
480 *
481 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
482 * The pragma is not documented since it is not really part of the interface
483 * to SQLite, just the test procedure.
484*/
485int always_code_trigger_setup = 0;
486
487/*
488 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
489 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
490 * found in the list specified as pTrigger.
491 */
492int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000493 Parse *pParse, /* Used to check for recursive triggers */
494 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000495 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
496 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
497 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000498 ExprList *pChanges /* Columns that change in an UPDATE statement */
499){
danielk1977633ed082002-05-17 00:05:58 +0000500 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000501
danielk1977633ed082002-05-17 00:05:58 +0000502 if( always_code_trigger_setup ){
503 return 1;
504 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000505
danielk1977633ed082002-05-17 00:05:58 +0000506 pTriggerCursor = pTrigger;
507 while( pTriggerCursor ){
508 if( pTriggerCursor->op == op &&
509 pTriggerCursor->tr_tm == tr_tm &&
510 pTriggerCursor->foreach == foreach &&
511 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000512 TriggerStack * ss;
513 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000514 while( ss && ss->pTrigger != pTrigger ){
515 ss = ss->pNext;
516 }
517 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000518 }
danielk1977633ed082002-05-17 00:05:58 +0000519 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000520 }
521
522 return 0;
523}
524
drhc977f7f2002-05-21 11:38:11 +0000525/*
526** Generate VDBE code for zero or more statements inside the body of a
527** trigger.
528*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000529static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000530 Parse *pParse, /* The parser context */
531 TriggerStep *pStepList, /* List of statements inside the trigger body */
532 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000533){
534 TriggerStep * pTriggerStep = pStepList;
535 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000536
danielk1977633ed082002-05-17 00:05:58 +0000537 while( pTriggerStep ){
538 int saveNTab = pParse->nTab;
drha69d9162003-04-17 22:57:53 +0000539 int saveUseDb = pParse->useDb;
danielk1977633ed082002-05-17 00:05:58 +0000540 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
541 pParse->trigStack->orconf = orconf;
drha69d9162003-04-17 22:57:53 +0000542 pParse->useDb = pTriggerStep->pTrig->iDb;
drhf0f258b2003-04-21 18:48:45 +0000543 if( pParse->useDb==1 ) pParse->useDb = -1;
danielk1977633ed082002-05-17 00:05:58 +0000544 switch( pTriggerStep->op ){
545 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000546 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
547 assert(ss);
548 assert(ss->pSrc);
549 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
550 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000551 break;
552 }
553 case TK_UPDATE: {
drh113088e2003-03-20 01:16:58 +0000554 SrcList *pSrc;
555 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
drhbd5a4512002-05-23 22:07:02 +0000556 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000557 sqliteUpdate(pParse, pSrc,
danielk19776f349032002-06-11 02:25:40 +0000558 sqliteExprListDup(pTriggerStep->pExprList),
559 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000560 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000561 break;
562 }
563 case TK_INSERT: {
drh113088e2003-03-20 01:16:58 +0000564 SrcList *pSrc;
565 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
566 sqliteInsert(pParse, pSrc,
567 sqliteExprListDup(pTriggerStep->pExprList),
568 sqliteSelectDup(pTriggerStep->pSelect),
569 sqliteIdListDup(pTriggerStep->pIdList), orconf);
danielk1977633ed082002-05-17 00:05:58 +0000570 break;
571 }
572 case TK_DELETE: {
drh113088e2003-03-20 01:16:58 +0000573 SrcList *pSrc;
drhbd5a4512002-05-23 22:07:02 +0000574 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000575 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
576 sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000577 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000578 break;
579 }
580 default:
581 assert(0);
582 }
583 pParse->nTab = saveNTab;
drha69d9162003-04-17 22:57:53 +0000584 pParse->useDb = saveUseDb;
danielk1977633ed082002-05-17 00:05:58 +0000585 pTriggerStep = pTriggerStep->pNext;
586 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000587
danielk1977633ed082002-05-17 00:05:58 +0000588 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000589}
590
danielk1977633ed082002-05-17 00:05:58 +0000591/*
592** This is called to code FOR EACH ROW triggers.
593**
594** When the code that this function generates is executed, the following
595** must be true:
drhc977f7f2002-05-21 11:38:11 +0000596**
597** 1. No cursors may be open in the main database. (But newIdx and oldIdx
598** can be indices of cursors in temporary tables. See below.)
599**
danielk1977633ed082002-05-17 00:05:58 +0000600** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
601** a temporary vdbe cursor (index newIdx) must be open and pointing at
602** a row containing values to be substituted for new.* expressions in the
603** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000604**
danielk1977633ed082002-05-17 00:05:58 +0000605** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
606** a temporary vdbe cursor (index oldIdx) must be open and pointing at
607** a row containing values to be substituted for old.* expressions in the
608** trigger program(s).
609**
610*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000611int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000612 Parse *pParse, /* Parse context */
613 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
614 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
615 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
616 Table *pTab, /* The table to code triggers from */
617 int newIdx, /* The indice of the "new" row to access */
618 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000619 int orconf, /* ON CONFLICT policy */
620 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000621){
danielk1977c3f9bad2002-05-15 08:30:12 +0000622 Trigger * pTrigger;
623 TriggerStack * pTriggerStack;
624
danielk1977c3f9bad2002-05-15 08:30:12 +0000625 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
626 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
627
danielk1977633ed082002-05-17 00:05:58 +0000628 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000629
danielk1977633ed082002-05-17 00:05:58 +0000630 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000631 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000632 int fire_this = 0;
633
634 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000635 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
636 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000637 fire_this = 1;
638 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000639 while( pTriggerStack ){
640 if( pTriggerStack->pTrigger == pTrigger ){
641 fire_this = 0;
642 }
drh9adf9ac2002-05-15 11:44:13 +0000643 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000644 }
danielk1977f29ce552002-05-19 23:43:12 +0000645 if( op == TK_UPDATE && pTrigger->pColumns &&
646 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000647 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000648 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000649 }
650
drhe4697f52002-05-23 02:09:03 +0000651 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000652 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000653 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000654 Expr * whenExpr;
655
drhad3cab52002-05-24 02:04:32 +0000656 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000657
658 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000659 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000660 pTriggerStack->newIdx = newIdx;
661 pTriggerStack->oldIdx = oldIdx;
662 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000663 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000664 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000665 pParse->trigStack = pTriggerStack;
666
667 /* code the WHEN clause */
668 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
669 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000670 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000671 pParse->trigStack = pParse->trigStack->pNext;
672 sqliteFree(pTriggerStack);
673 sqliteExprDelete(whenExpr);
674 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000675 }
drhf5905aa2002-05-26 20:54:33 +0000676 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000677 sqliteExprDelete(whenExpr);
678
danielk1977633ed082002-05-17 00:05:58 +0000679 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000680
681 /* Pop the entry off the trigger stack */
682 pParse->trigStack = pParse->trigStack->pNext;
683 sqliteFree(pTriggerStack);
684
685 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
686 }
687 pTrigger = pTrigger->pNext;
688 }
689
690 return 0;
691}
692
693/*
danielk1977633ed082002-05-17 00:05:58 +0000694 * This function is called to code ON UPDATE and ON DELETE triggers on
695 * views.
696 *
697 * This function deletes the data pointed at by the pWhere and pChanges
698 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000699 */
danielk1977633ed082002-05-17 00:05:58 +0000700void sqliteViewTriggers(
701 Parse *pParse,
702 Table *pTab, /* The view to code triggers on */
703 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
704 int orconf, /* The ON CONFLICT policy specified as part of the
705 statement causing these triggers */
706 ExprList *pChanges /* If this is an statement causing triggers to fire
707 is an UPDATE, then this list holds the columns
708 to update and the expressions to update them to.
709 See comments for sqliteUpdate(). */
710){
danielk1977c3f9bad2002-05-15 08:30:12 +0000711 int oldIdx = -1;
712 int newIdx = -1;
713 int *aXRef = 0;
714 Vdbe *v;
715 int endOfLoop;
716 int startOfLoop;
717 Select theSelect;
718 Token tblNameToken;
719
720 assert(pTab->pSelect);
721
722 tblNameToken.z = pTab->zName;
723 tblNameToken.n = strlen(pTab->zName);
724
725 theSelect.isDistinct = 0;
726 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drh113088e2003-03-20 01:16:58 +0000727 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000728 theSelect.pWhere = pWhere; pWhere = 0;
729 theSelect.pGroupBy = 0;
730 theSelect.pHaving = 0;
731 theSelect.pOrderBy = 0;
732 theSelect.op = TK_SELECT; /* ?? */
733 theSelect.pPrior = 0;
734 theSelect.nLimit = -1;
735 theSelect.nOffset = -1;
736 theSelect.zSelect = 0;
737 theSelect.base = 0;
738
739 v = sqliteGetVdbe(pParse);
740 assert(v);
drhcabb0812002-09-14 13:47:32 +0000741 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000742
743 /* Allocate temp tables */
744 oldIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000745 sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000746 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000747 newIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000748 sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000749 }
750
751 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000752 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000753 goto trigger_cleanup;
754 }
755
756 /* loop thru the view snapshot, executing triggers for each row */
757 endOfLoop = sqliteVdbeMakeLabel(v);
758 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
759
760 /* Loop thru the view snapshot, executing triggers for each row */
761 startOfLoop = sqliteVdbeCurrentAddr(v);
762
763 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000764 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000765 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000766
767 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
768 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000769 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000770 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000771 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000772
773 for(ii=0; ii<pChanges->nExpr; ii++){
774 int jj;
775 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000776 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000777 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000778 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000779
780 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000781 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000782
783 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000784 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
785 aXRef[jj] = ii;
786 break;
787 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000788 }
789 if( jj>=pTab->nCol ){
drhda93d232003-03-31 02:12:46 +0000790 sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[ii].zName);
drh9adf9ac2002-05-15 11:44:13 +0000791 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000792 }
793 }
794
795 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
796
danielk1977633ed082002-05-17 00:05:58 +0000797 for(ii = 0; ii<pTab->nCol; ii++){
798 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000799 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000800 }else{
drh9adf9ac2002-05-15 11:44:13 +0000801 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000802 }
803 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000804
805 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
806 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
807 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
808
809 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000810 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000811 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000812 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000813 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000814 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000815 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000816 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000817 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000818 }
819
820 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
821
822 sqliteVdbeResolveLabel(v, endOfLoop);
823 sqliteEndWriteOperation(pParse);
824
825trigger_cleanup:
826 sqliteFree(aXRef);
827 sqliteExprListDelete(pChanges);
828 sqliteExprDelete(pWhere);
829 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000830 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000831 sqliteExprDelete(theSelect.pWhere);
832 return;
833}