blob: a2fc91f518aa70c89e368cdc35e2431cf8bbe2b3 [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;
drhe22a3342003-04-22 20:30:37 +0000101 const char *zDb = db->aDb[tab->iDb].zName;
102 const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
drhf0f258b2003-04-21 18:48:45 +0000103 if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
drhe22a3342003-04-22 20:30:37 +0000104 if( sqliteAuthCheck(pParse, code, zName, tab->zName, zDbTrig) ){
drhd24cc422003-03-27 12:51:24 +0000105 goto trigger_cleanup;
106 }
drhe22a3342003-04-22 20:30:37 +0000107 if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0, zDb)){
drhd24cc422003-03-27 12:51:24 +0000108 goto trigger_cleanup;
109 }
110 }
111#endif
danielk1977d702fcc2002-05-26 23:24:40 +0000112
113 if (tr_tm == TK_INSTEAD){
114 tr_tm = TK_BEFORE;
danielk1977c3f9bad2002-05-15 08:30:12 +0000115 }
116
117 /* Build the Trigger object */
drh9adf9ac2002-05-15 11:44:13 +0000118 nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
drhe4697f52002-05-23 02:09:03 +0000119 if( nt==0 ) goto trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000120 nt->name = zName;
121 zName = 0;
drhd24cc422003-03-27 12:51:24 +0000122 nt->table = sqliteStrDup(pTableName->a[0].zName);
drhe4697f52002-05-23 02:09:03 +0000123 if( sqlite_malloc_failed ) goto trigger_cleanup;
drhf0f258b2003-04-21 18:48:45 +0000124 nt->iDb = iDb;
danielk1977c3f9bad2002-05-15 08:30:12 +0000125 nt->op = op;
126 nt->tr_tm = tr_tm;
drh4b59ab52002-08-24 18:24:51 +0000127 nt->pWhen = sqliteExprDup(pWhen);
drh4b59ab52002-08-24 18:24:51 +0000128 nt->pColumns = sqliteIdListDup(pColumns);
danielk1977c3f9bad2002-05-15 08:30:12 +0000129 nt->foreach = foreach;
drhf0f258b2003-04-21 18:48:45 +0000130 assert( pParse->pNewTrigger==0 );
131 pParse->pNewTrigger = nt;
132
133trigger_cleanup:
134 sqliteFree(zName);
135 sqliteSrcListDelete(pTableName);
136 sqliteIdListDelete(pColumns);
137 sqliteExprDelete(pWhen);
138}
139
140/*
141** This routine is called after all of the trigger actions have been parsed
142** in order to complete the process of building the trigger.
143*/
144void sqliteFinishTrigger(
145 Parse *pParse, /* Parser context */
146 TriggerStep *pStepList, /* The triggered program */
147 Token *pAll /* Token that describes the complete CREATE TRIGGER */
148){
149 Trigger *nt; /* The trigger whose construction is finishing up */
150 sqlite *db = pParse->db; /* The database */
151
152 if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
153 nt = pParse->pNewTrigger;
154 pParse->pNewTrigger = 0;
danielk1977633ed082002-05-17 00:05:58 +0000155 nt->step_list = pStepList;
drha69d9162003-04-17 22:57:53 +0000156 while( pStepList ){
157 pStepList->pTrig = nt;
158 pStepList = pStepList->pNext;
159 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000160
161 /* if we are not initializing, and this trigger is not on a TEMP table,
drh9adf9ac2002-05-15 11:44:13 +0000162 ** build the sqlite_master entry
163 */
drhe0bc4042002-06-25 01:09:11 +0000164 if( !pParse->initFlag ){
drhc977f7f2002-05-21 11:38:11 +0000165 static VdbeOp insertTrig[] = {
drhc977f7f2002-05-21 11:38:11 +0000166 { OP_NewRecno, 0, 0, 0 },
167 { OP_String, 0, 0, "trigger" },
drhe0bc4042002-06-25 01:09:11 +0000168 { OP_String, 0, 0, 0 }, /* 2: trigger name */
169 { OP_String, 0, 0, 0 }, /* 3: table name */
drhc977f7f2002-05-21 11:38:11 +0000170 { OP_Integer, 0, 0, 0 },
drhe0bc4042002-06-25 01:09:11 +0000171 { OP_String, 0, 0, 0 }, /* 5: SQL */
drhc977f7f2002-05-21 11:38:11 +0000172 { OP_MakeRecord, 5, 0, 0 },
173 { OP_PutIntKey, 0, 0, 0 },
drhc977f7f2002-05-21 11:38:11 +0000174 };
175 int addr;
176 Vdbe *v;
danielk1977c3f9bad2002-05-15 08:30:12 +0000177
178 /* Make an entry in the sqlite_master table */
drhc977f7f2002-05-21 11:38:11 +0000179 v = sqliteGetVdbe(pParse);
drhf0f258b2003-04-21 18:48:45 +0000180 if( v==0 ) goto triggerfinish_cleanup;
drhcabb0812002-09-14 13:47:32 +0000181 sqliteBeginWriteOperation(pParse, 0, 0);
drhf0f258b2003-04-21 18:48:45 +0000182 sqliteOpenMasterTable(v, nt->iDb==1);
drhc977f7f2002-05-21 11:38:11 +0000183 addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
drhe0bc4042002-06-25 01:09:11 +0000184 sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
185 sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
drh4b59ab52002-08-24 18:24:51 +0000186 sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
drhf0f258b2003-04-21 18:48:45 +0000187 if( nt->iDb==0 ){
drhd24cc422003-03-27 12:51:24 +0000188 sqliteChangeCookie(db, v);
drhe0bc4042002-06-25 01:09:11 +0000189 }
190 sqliteVdbeAddOp(v, OP_Close, 0, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000191 sqliteEndWriteOperation(pParse);
192 }
193
danielk1977633ed082002-05-17 00:05:58 +0000194 if( !pParse->explain ){
drhf0f258b2003-04-21 18:48:45 +0000195 Table *pTab;
196 sqliteHashInsert(&db->aDb[nt->iDb].trigHash,
197 nt->name, strlen(nt->name)+1, nt);
198 pTab = sqliteLocateTable(pParse, nt->table, 0);
199 assert( pTab!=0 );
200 nt->pNext = pTab->pTrigger;
201 pTab->pTrigger = nt;
danielk1977f29ce552002-05-19 23:43:12 +0000202 }else{
drhf0f258b2003-04-21 18:48:45 +0000203 sqliteDeleteTrigger(nt);
danielk1977c3f9bad2002-05-15 08:30:12 +0000204 }
205
drhf0f258b2003-04-21 18:48:45 +0000206triggerfinish_cleanup:
207 sqliteDeleteTrigger(pParse->pNewTrigger);
208 pParse->pNewTrigger = 0;
drh4b59ab52002-08-24 18:24:51 +0000209 sqliteDeleteTriggerStep(pStepList);
210}
danielk1977c3f9bad2002-05-15 08:30:12 +0000211
drh4b59ab52002-08-24 18:24:51 +0000212/*
213** Make a copy of all components of the given trigger step. This has
214** the effect of copying all Expr.token.z values into memory obtained
215** from sqliteMalloc(). As initially created, the Expr.token.z values
216** all point to the input string that was fed to the parser. But that
217** string is ephemeral - it will go away as soon as the sqlite_exec()
218** call that started the parser exits. This routine makes a persistent
219** copy of all the Expr.token.z strings so that the TriggerStep structure
220** will be valid even after the sqlite_exec() call returns.
221*/
222static void sqlitePersistTriggerStep(TriggerStep *p){
223 if( p->target.z ){
224 p->target.z = sqliteStrNDup(p->target.z, p->target.n);
225 p->target.dyn = 1;
226 }
227 if( p->pSelect ){
228 Select *pNew = sqliteSelectDup(p->pSelect);
229 sqliteSelectDelete(p->pSelect);
230 p->pSelect = pNew;
231 }
232 if( p->pWhere ){
233 Expr *pNew = sqliteExprDup(p->pWhere);
234 sqliteExprDelete(p->pWhere);
235 p->pWhere = pNew;
236 }
237 if( p->pExprList ){
238 ExprList *pNew = sqliteExprListDup(p->pExprList);
239 sqliteExprListDelete(p->pExprList);
240 p->pExprList = pNew;
241 }
242 if( p->pIdList ){
243 IdList *pNew = sqliteIdListDup(p->pIdList);
244 sqliteIdListDelete(p->pIdList);
245 p->pIdList = pNew;
danielk1977c3f9bad2002-05-15 08:30:12 +0000246 }
247}
248
drhc977f7f2002-05-21 11:38:11 +0000249/*
250** Turn a SELECT statement (that the pSelect parameter points to) into
251** a trigger step. Return a pointer to a TriggerStep structure.
252**
253** The parser calls this routine when it finds a SELECT statement in
254** body of a TRIGGER.
255*/
256TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
danielk1977633ed082002-05-17 00:05:58 +0000257 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 pTriggerStep->op = TK_SELECT;
261 pTriggerStep->pSelect = pSelect;
262 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000263 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000264
danielk1977633ed082002-05-17 00:05:58 +0000265 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000266}
267
drhc977f7f2002-05-21 11:38:11 +0000268/*
269** Build a trigger step out of an INSERT statement. Return a pointer
270** to the new trigger step.
271**
272** The parser calls this routine when it sees an INSERT inside the
273** body of a trigger.
274*/
danielk1977633ed082002-05-17 00:05:58 +0000275TriggerStep *sqliteTriggerInsertStep(
drhc977f7f2002-05-21 11:38:11 +0000276 Token *pTableName, /* Name of the table into which we insert */
277 IdList *pColumn, /* List of columns in pTableName to insert into */
278 ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
279 Select *pSelect, /* A SELECT statement that supplies values */
280 int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
danielk1977633ed082002-05-17 00:05:58 +0000281){
282 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000283 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000284
danielk1977633ed082002-05-17 00:05:58 +0000285 assert(pEList == 0 || pSelect == 0);
286 assert(pEList != 0 || pSelect != 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000287
danielk1977633ed082002-05-17 00:05:58 +0000288 pTriggerStep->op = TK_INSERT;
289 pTriggerStep->pSelect = pSelect;
290 pTriggerStep->target = *pTableName;
291 pTriggerStep->pIdList = pColumn;
292 pTriggerStep->pExprList = pEList;
293 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000294 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000295
danielk1977633ed082002-05-17 00:05:58 +0000296 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000297}
298
drhc977f7f2002-05-21 11:38:11 +0000299/*
300** Construct a trigger step that implements an UPDATE statement and return
301** a pointer to that trigger step. The parser calls this routine when it
302** sees an UPDATE statement inside the body of a CREATE TRIGGER.
303*/
danielk1977633ed082002-05-17 00:05:58 +0000304TriggerStep *sqliteTriggerUpdateStep(
drhc977f7f2002-05-21 11:38:11 +0000305 Token *pTableName, /* Name of the table to be updated */
306 ExprList *pEList, /* The SET clause: list of column and new values */
307 Expr *pWhere, /* The WHERE clause */
308 int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
309){
danielk1977633ed082002-05-17 00:05:58 +0000310 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
drhe4697f52002-05-23 02:09:03 +0000311 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000312
danielk1977633ed082002-05-17 00:05:58 +0000313 pTriggerStep->op = TK_UPDATE;
314 pTriggerStep->target = *pTableName;
315 pTriggerStep->pExprList = pEList;
316 pTriggerStep->pWhere = pWhere;
317 pTriggerStep->orconf = orconf;
drh4b59ab52002-08-24 18:24:51 +0000318 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000319
danielk1977633ed082002-05-17 00:05:58 +0000320 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000321}
322
drhc977f7f2002-05-21 11:38:11 +0000323/*
324** Construct a trigger step that implements a DELETE statement and return
325** a pointer to that trigger step. The parser calls this routine when it
326** sees a DELETE statement inside the body of a CREATE TRIGGER.
327*/
328TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
drhe4697f52002-05-23 02:09:03 +0000329 TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
330 if( pTriggerStep==0 ) return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000331
danielk1977633ed082002-05-17 00:05:58 +0000332 pTriggerStep->op = TK_DELETE;
333 pTriggerStep->target = *pTableName;
334 pTriggerStep->pWhere = pWhere;
335 pTriggerStep->orconf = OE_Default;
drh4b59ab52002-08-24 18:24:51 +0000336 sqlitePersistTriggerStep(pTriggerStep);
danielk1977c3f9bad2002-05-15 08:30:12 +0000337
danielk1977633ed082002-05-17 00:05:58 +0000338 return pTriggerStep;
danielk1977c3f9bad2002-05-15 08:30:12 +0000339}
340
danielk1977633ed082002-05-17 00:05:58 +0000341/*
342** Recursively delete a Trigger structure
343*/
drh1d1f3052002-05-21 13:18:25 +0000344void sqliteDeleteTrigger(Trigger *pTrigger){
drhf0f258b2003-04-21 18:48:45 +0000345 if( pTrigger==0 ) return;
drh4b59ab52002-08-24 18:24:51 +0000346 sqliteDeleteTriggerStep(pTrigger->step_list);
danielk1977633ed082002-05-17 00:05:58 +0000347 sqliteFree(pTrigger->name);
348 sqliteFree(pTrigger->table);
349 sqliteExprDelete(pTrigger->pWhen);
350 sqliteIdListDelete(pTrigger->pColumns);
danielk1977633ed082002-05-17 00:05:58 +0000351 sqliteFree(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000352}
353
354/*
danielk1977633ed082002-05-17 00:05:58 +0000355 * This function is called to drop a trigger from the database schema.
356 *
357 * This may be called directly from the parser, or from within
358 * sqliteDropTable(). In the latter case the "nested" argument is true.
359 *
360 * Note that this function does not delete the trigger entirely. Instead it
361 * removes it from the internal schema and places it in the trigDrop hash
362 * table. This is so that the trigger can be restored into the database schema
363 * if the transaction is rolled back.
danielk1977c3f9bad2002-05-15 08:30:12 +0000364 */
drhd24cc422003-03-27 12:51:24 +0000365void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
danielk1977633ed082002-05-17 00:05:58 +0000366 Trigger *pTrigger;
367 Table *pTable;
drhe0bc4042002-06-25 01:09:11 +0000368 Vdbe *v;
drhd24cc422003-03-27 12:51:24 +0000369 int i;
370 const char *zDb;
371 const char *zName;
372 int nName;
373 sqlite *db = pParse->db;
danielk1977c3f9bad2002-05-15 08:30:12 +0000374
drhd24cc422003-03-27 12:51:24 +0000375 if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
376 assert( pName->nSrc==1 );
377 zDb = pName->a[0].zDatabase;
378 zName = pName->a[0].zName;
379 nName = strlen(zName);
380 for(i=0; i<db->nDb; i++){
drh812d7a22003-03-27 13:50:00 +0000381 int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
382 if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
383 pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
drhd24cc422003-03-27 12:51:24 +0000384 if( pTrigger ) break;
danielk1977c3f9bad2002-05-15 08:30:12 +0000385 }
drhd24cc422003-03-27 12:51:24 +0000386 if( !pTrigger ){
drhda93d232003-03-31 02:12:46 +0000387 sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
drhd24cc422003-03-27 12:51:24 +0000388 goto drop_trigger_cleanup;
389 }
drhf0f258b2003-04-21 18:48:45 +0000390 assert( pTrigger->iDb<db->nDb );
drhd24cc422003-03-27 12:51:24 +0000391 if( pTrigger->iDb>=2 ){
drhda93d232003-03-31 02:12:46 +0000392 sqliteErrorMsg(pParse, "triggers may not be removed from "
393 "auxiliary database %s", db->aDb[pTrigger->iDb].zName);
drhd24cc422003-03-27 12:51:24 +0000394 goto drop_trigger_cleanup;
395 }
396 pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName);
drhed6c8672003-01-12 18:02:16 +0000397 assert(pTable);
drhf0f258b2003-04-21 18:48:45 +0000398 assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
drhe5f9c642003-01-13 23:27:31 +0000399#ifndef SQLITE_OMIT_AUTHORIZATION
400 {
401 int code = SQLITE_DROP_TRIGGER;
drhe22a3342003-04-22 20:30:37 +0000402 const char *zDb = db->aDb[pTrigger->iDb].zName;
403 const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
drhf0f258b2003-04-21 18:48:45 +0000404 if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
drhe22a3342003-04-22 20:30:37 +0000405 if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
406 sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
drh0be9df02003-03-30 00:19:49 +0000407 goto drop_trigger_cleanup;
drhe5f9c642003-01-13 23:27:31 +0000408 }
drhed6c8672003-01-12 18:02:16 +0000409 }
drhe5f9c642003-01-13 23:27:31 +0000410#endif
danielk1977c3f9bad2002-05-15 08:30:12 +0000411
drhf0f258b2003-04-21 18:48:45 +0000412 /* Generate code to destroy the database record of the trigger.
413 */
414 if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
415 int base;
416 static VdbeOp dropTrigger[] = {
417 { OP_Rewind, 0, ADDR(8), 0},
418 { OP_String, 0, 0, 0}, /* 1 */
419 { OP_MemStore, 1, 1, 0},
420 { OP_MemLoad, 1, 0, 0}, /* 3 */
421 { OP_Column, 0, 1, 0},
422 { OP_Ne, 0, ADDR(7), 0},
423 { OP_Delete, 0, 0, 0},
424 { OP_Next, 0, ADDR(3), 0}, /* 7 */
425 };
426
427 sqliteBeginWriteOperation(pParse, 0, 0);
428 sqliteOpenMasterTable(v, pTrigger->iDb);
429 base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
430 sqliteVdbeChangeP3(v, base+1, zName, 0);
431 if( pTrigger->iDb==0 ){
432 sqliteChangeCookie(db, v);
433 }
434 sqliteVdbeAddOp(v, OP_Close, 0, 0);
435 sqliteEndWriteOperation(pParse);
436 }
437
danielk1977c3f9bad2002-05-15 08:30:12 +0000438 /*
drhe0bc4042002-06-25 01:09:11 +0000439 * If this is not an "explain", then delete the trigger structure.
danielk1977c3f9bad2002-05-15 08:30:12 +0000440 */
danielk1977633ed082002-05-17 00:05:58 +0000441 if( !pParse->explain ){
danielk1977633ed082002-05-17 00:05:58 +0000442 if( pTable->pTrigger == pTrigger ){
443 pTable->pTrigger = pTrigger->pNext;
danielk1977f29ce552002-05-19 23:43:12 +0000444 }else{
danielk1977633ed082002-05-17 00:05:58 +0000445 Trigger *cc = pTable->pTrigger;
446 while( cc ){
447 if( cc->pNext == pTrigger ){
drh9adf9ac2002-05-15 11:44:13 +0000448 cc->pNext = cc->pNext->pNext;
449 break;
450 }
451 cc = cc->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000452 }
453 assert(cc);
454 }
drhd24cc422003-03-27 12:51:24 +0000455 sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
drhe0bc4042002-06-25 01:09:11 +0000456 sqliteDeleteTrigger(pTrigger);
danielk1977c3f9bad2002-05-15 08:30:12 +0000457 }
458
drhd24cc422003-03-27 12:51:24 +0000459drop_trigger_cleanup:
460 sqliteSrcListDelete(pName);
danielk1977c3f9bad2002-05-15 08:30:12 +0000461}
462
drhc977f7f2002-05-21 11:38:11 +0000463/*
464** pEList is the SET clause of an UPDATE statement. Each entry
465** in pEList is of the format <id>=<expr>. If any of the entries
466** in pEList have an <id> which matches an identifier in pIdList,
467** then return TRUE. If pIdList==NULL, then it is considered a
468** wildcard that matches anything. Likewise if pEList==NULL then
469** it matches anything so always return true. Return false only
470** if there is no match.
471*/
472static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
drhad2d8302002-05-24 20:31:36 +0000473 int e;
474 if( !pIdList || !pEList ) return 1;
475 for(e=0; e<pEList->nExpr; e++){
476 if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
danielk1977f29ce552002-05-19 23:43:12 +0000477 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000478 return 0;
479}
480
481/* A global variable that is TRUE if we should always set up temp tables for
482 * for triggers, even if there are no triggers to code. This is used to test
483 * how much overhead the triggers algorithm is causing.
484 *
485 * This flag can be set or cleared using the "trigger_overhead_test" pragma.
486 * The pragma is not documented since it is not really part of the interface
487 * to SQLite, just the test procedure.
488*/
489int always_code_trigger_setup = 0;
490
491/*
492 * Returns true if a trigger matching op, tr_tm and foreach that is NOT already
493 * on the Parse objects trigger-stack (to prevent recursive trigger firing) is
494 * found in the list specified as pTrigger.
495 */
496int sqliteTriggersExist(
drhc977f7f2002-05-21 11:38:11 +0000497 Parse *pParse, /* Used to check for recursive triggers */
498 Trigger *pTrigger, /* A list of triggers associated with a table */
danielk1977633ed082002-05-17 00:05:58 +0000499 int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
500 int tr_tm, /* one of TK_BEFORE, TK_AFTER */
501 int foreach, /* one of TK_ROW or TK_STATEMENT */
drhc977f7f2002-05-21 11:38:11 +0000502 ExprList *pChanges /* Columns that change in an UPDATE statement */
503){
danielk1977633ed082002-05-17 00:05:58 +0000504 Trigger * pTriggerCursor;
danielk1977c3f9bad2002-05-15 08:30:12 +0000505
danielk1977633ed082002-05-17 00:05:58 +0000506 if( always_code_trigger_setup ){
507 return 1;
508 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000509
danielk1977633ed082002-05-17 00:05:58 +0000510 pTriggerCursor = pTrigger;
511 while( pTriggerCursor ){
512 if( pTriggerCursor->op == op &&
513 pTriggerCursor->tr_tm == tr_tm &&
514 pTriggerCursor->foreach == foreach &&
515 checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000516 TriggerStack * ss;
517 ss = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000518 while( ss && ss->pTrigger != pTrigger ){
519 ss = ss->pNext;
520 }
521 if( !ss )return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000522 }
danielk1977633ed082002-05-17 00:05:58 +0000523 pTriggerCursor = pTriggerCursor->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000524 }
525
526 return 0;
527}
528
drhc977f7f2002-05-21 11:38:11 +0000529/*
530** Generate VDBE code for zero or more statements inside the body of a
531** trigger.
532*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000533static int codeTriggerProgram(
drhc977f7f2002-05-21 11:38:11 +0000534 Parse *pParse, /* The parser context */
535 TriggerStep *pStepList, /* List of statements inside the trigger body */
536 int orconfin /* Conflict algorithm. (OE_Abort, etc) */
danielk1977633ed082002-05-17 00:05:58 +0000537){
538 TriggerStep * pTriggerStep = pStepList;
539 int orconf;
danielk1977c3f9bad2002-05-15 08:30:12 +0000540
danielk1977633ed082002-05-17 00:05:58 +0000541 while( pTriggerStep ){
542 int saveNTab = pParse->nTab;
drha69d9162003-04-17 22:57:53 +0000543 int saveUseDb = pParse->useDb;
danielk1977633ed082002-05-17 00:05:58 +0000544 orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
545 pParse->trigStack->orconf = orconf;
drha69d9162003-04-17 22:57:53 +0000546 pParse->useDb = pTriggerStep->pTrig->iDb;
drhf0f258b2003-04-21 18:48:45 +0000547 if( pParse->useDb==1 ) pParse->useDb = -1;
danielk1977633ed082002-05-17 00:05:58 +0000548 switch( pTriggerStep->op ){
549 case TK_SELECT: {
danielk19776f349032002-06-11 02:25:40 +0000550 Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
551 assert(ss);
552 assert(ss->pSrc);
553 sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
554 sqliteSelectDelete(ss);
danielk1977633ed082002-05-17 00:05:58 +0000555 break;
556 }
557 case TK_UPDATE: {
drh113088e2003-03-20 01:16:58 +0000558 SrcList *pSrc;
559 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
drhbd5a4512002-05-23 22:07:02 +0000560 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000561 sqliteUpdate(pParse, pSrc,
danielk19776f349032002-06-11 02:25:40 +0000562 sqliteExprListDup(pTriggerStep->pExprList),
563 sqliteExprDup(pTriggerStep->pWhere), orconf);
drhbd5a4512002-05-23 22:07:02 +0000564 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000565 break;
566 }
567 case TK_INSERT: {
drh113088e2003-03-20 01:16:58 +0000568 SrcList *pSrc;
569 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
570 sqliteInsert(pParse, pSrc,
571 sqliteExprListDup(pTriggerStep->pExprList),
572 sqliteSelectDup(pTriggerStep->pSelect),
573 sqliteIdListDup(pTriggerStep->pIdList), orconf);
danielk1977633ed082002-05-17 00:05:58 +0000574 break;
575 }
576 case TK_DELETE: {
drh113088e2003-03-20 01:16:58 +0000577 SrcList *pSrc;
drhbd5a4512002-05-23 22:07:02 +0000578 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
drh113088e2003-03-20 01:16:58 +0000579 pSrc = sqliteSrcListAppend(0, &pTriggerStep->target, 0);
580 sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
drhbd5a4512002-05-23 22:07:02 +0000581 sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
danielk1977633ed082002-05-17 00:05:58 +0000582 break;
583 }
584 default:
585 assert(0);
586 }
587 pParse->nTab = saveNTab;
drha69d9162003-04-17 22:57:53 +0000588 pParse->useDb = saveUseDb;
danielk1977633ed082002-05-17 00:05:58 +0000589 pTriggerStep = pTriggerStep->pNext;
590 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000591
danielk1977633ed082002-05-17 00:05:58 +0000592 return 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000593}
594
danielk1977633ed082002-05-17 00:05:58 +0000595/*
596** This is called to code FOR EACH ROW triggers.
597**
598** When the code that this function generates is executed, the following
599** must be true:
drhc977f7f2002-05-21 11:38:11 +0000600**
601** 1. No cursors may be open in the main database. (But newIdx and oldIdx
602** can be indices of cursors in temporary tables. See below.)
603**
danielk1977633ed082002-05-17 00:05:58 +0000604** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
605** a temporary vdbe cursor (index newIdx) must be open and pointing at
606** a row containing values to be substituted for new.* expressions in the
607** trigger program(s).
drhc977f7f2002-05-21 11:38:11 +0000608**
danielk1977633ed082002-05-17 00:05:58 +0000609** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
610** a temporary vdbe cursor (index oldIdx) must be open and pointing at
611** a row containing values to be substituted for old.* expressions in the
612** trigger program(s).
613**
614*/
danielk1977c3f9bad2002-05-15 08:30:12 +0000615int sqliteCodeRowTrigger(
danielk1977633ed082002-05-17 00:05:58 +0000616 Parse *pParse, /* Parse context */
617 int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
618 ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
619 int tr_tm, /* One of TK_BEFORE, TK_AFTER */
620 Table *pTab, /* The table to code triggers from */
621 int newIdx, /* The indice of the "new" row to access */
622 int oldIdx, /* The indice of the "old" row to access */
danielk19776f349032002-06-11 02:25:40 +0000623 int orconf, /* ON CONFLICT policy */
624 int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
drhc977f7f2002-05-21 11:38:11 +0000625){
danielk1977c3f9bad2002-05-15 08:30:12 +0000626 Trigger * pTrigger;
627 TriggerStack * pTriggerStack;
628
danielk1977c3f9bad2002-05-15 08:30:12 +0000629 assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
630 assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);
631
danielk1977633ed082002-05-17 00:05:58 +0000632 assert(newIdx != -1 || oldIdx != -1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000633
danielk1977633ed082002-05-17 00:05:58 +0000634 pTrigger = pTab->pTrigger;
danielk1977f29ce552002-05-19 23:43:12 +0000635 while( pTrigger ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000636 int fire_this = 0;
637
638 /* determine whether we should code this trigger */
danielk1977f29ce552002-05-19 23:43:12 +0000639 if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
640 pTrigger->foreach == TK_ROW ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000641 fire_this = 1;
642 pTriggerStack = pParse->trigStack;
danielk1977f29ce552002-05-19 23:43:12 +0000643 while( pTriggerStack ){
644 if( pTriggerStack->pTrigger == pTrigger ){
645 fire_this = 0;
646 }
drh9adf9ac2002-05-15 11:44:13 +0000647 pTriggerStack = pTriggerStack->pNext;
danielk1977c3f9bad2002-05-15 08:30:12 +0000648 }
danielk1977f29ce552002-05-19 23:43:12 +0000649 if( op == TK_UPDATE && pTrigger->pColumns &&
650 !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
drh9adf9ac2002-05-15 11:44:13 +0000651 fire_this = 0;
danielk1977f29ce552002-05-19 23:43:12 +0000652 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000653 }
654
drhe4697f52002-05-23 02:09:03 +0000655 if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000656 int endTrigger;
drhad3cab52002-05-24 02:04:32 +0000657 SrcList dummyTablist;
danielk1977c3f9bad2002-05-15 08:30:12 +0000658 Expr * whenExpr;
659
drhad3cab52002-05-24 02:04:32 +0000660 dummyTablist.nSrc = 0;
danielk1977c3f9bad2002-05-15 08:30:12 +0000661
662 /* Push an entry on to the trigger stack */
danielk1977c3f9bad2002-05-15 08:30:12 +0000663 pTriggerStack->pTrigger = pTrigger;
danielk1977633ed082002-05-17 00:05:58 +0000664 pTriggerStack->newIdx = newIdx;
665 pTriggerStack->oldIdx = oldIdx;
666 pTriggerStack->pTab = pTab;
danielk1977c3f9bad2002-05-15 08:30:12 +0000667 pTriggerStack->pNext = pParse->trigStack;
danielk19776f349032002-06-11 02:25:40 +0000668 pTriggerStack->ignoreJump = ignoreJump;
danielk1977c3f9bad2002-05-15 08:30:12 +0000669 pParse->trigStack = pTriggerStack;
670
671 /* code the WHEN clause */
672 endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
673 whenExpr = sqliteExprDup(pTrigger->pWhen);
danielk1977f29ce552002-05-19 23:43:12 +0000674 if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000675 pParse->trigStack = pParse->trigStack->pNext;
676 sqliteFree(pTriggerStack);
677 sqliteExprDelete(whenExpr);
678 return 1;
danielk1977c3f9bad2002-05-15 08:30:12 +0000679 }
drhf5905aa2002-05-26 20:54:33 +0000680 sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
danielk1977c3f9bad2002-05-15 08:30:12 +0000681 sqliteExprDelete(whenExpr);
682
danielk1977633ed082002-05-17 00:05:58 +0000683 codeTriggerProgram(pParse, pTrigger->step_list, orconf);
danielk1977c3f9bad2002-05-15 08:30:12 +0000684
685 /* Pop the entry off the trigger stack */
686 pParse->trigStack = pParse->trigStack->pNext;
687 sqliteFree(pTriggerStack);
688
689 sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
690 }
691 pTrigger = pTrigger->pNext;
692 }
693
694 return 0;
695}
696
697/*
danielk1977633ed082002-05-17 00:05:58 +0000698 * This function is called to code ON UPDATE and ON DELETE triggers on
699 * views.
700 *
701 * This function deletes the data pointed at by the pWhere and pChanges
702 * arguments before it completes.
danielk1977c3f9bad2002-05-15 08:30:12 +0000703 */
danielk1977633ed082002-05-17 00:05:58 +0000704void sqliteViewTriggers(
705 Parse *pParse,
706 Table *pTab, /* The view to code triggers on */
707 Expr *pWhere, /* The WHERE clause of the statement causing triggers*/
708 int orconf, /* The ON CONFLICT policy specified as part of the
709 statement causing these triggers */
710 ExprList *pChanges /* If this is an statement causing triggers to fire
711 is an UPDATE, then this list holds the columns
712 to update and the expressions to update them to.
713 See comments for sqliteUpdate(). */
714){
danielk1977c3f9bad2002-05-15 08:30:12 +0000715 int oldIdx = -1;
716 int newIdx = -1;
717 int *aXRef = 0;
718 Vdbe *v;
719 int endOfLoop;
720 int startOfLoop;
721 Select theSelect;
722 Token tblNameToken;
723
724 assert(pTab->pSelect);
725
726 tblNameToken.z = pTab->zName;
727 tblNameToken.n = strlen(pTab->zName);
728
729 theSelect.isDistinct = 0;
730 theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0);
drh113088e2003-03-20 01:16:58 +0000731 theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000732 theSelect.pWhere = pWhere; pWhere = 0;
733 theSelect.pGroupBy = 0;
734 theSelect.pHaving = 0;
735 theSelect.pOrderBy = 0;
736 theSelect.op = TK_SELECT; /* ?? */
737 theSelect.pPrior = 0;
738 theSelect.nLimit = -1;
739 theSelect.nOffset = -1;
740 theSelect.zSelect = 0;
741 theSelect.base = 0;
742
743 v = sqliteGetVdbe(pParse);
744 assert(v);
drhcabb0812002-09-14 13:47:32 +0000745 sqliteBeginWriteOperation(pParse, 1, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000746
747 /* Allocate temp tables */
748 oldIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000749 sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
danielk1977633ed082002-05-17 00:05:58 +0000750 if( pChanges ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000751 newIdx = pParse->nTab++;
drh70ce3f02003-04-15 19:22:22 +0000752 sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
danielk1977c3f9bad2002-05-15 08:30:12 +0000753 }
754
755 /* Snapshot the view */
danielk1977633ed082002-05-17 00:05:58 +0000756 if( sqliteSelect(pParse, &theSelect, SRT_Table, oldIdx, 0, 0, 0) ){
danielk1977c3f9bad2002-05-15 08:30:12 +0000757 goto trigger_cleanup;
758 }
759
760 /* loop thru the view snapshot, executing triggers for each row */
761 endOfLoop = sqliteVdbeMakeLabel(v);
762 sqliteVdbeAddOp(v, OP_Rewind, oldIdx, endOfLoop);
763
764 /* Loop thru the view snapshot, executing triggers for each row */
765 startOfLoop = sqliteVdbeCurrentAddr(v);
766
767 /* Build the updated row if required */
danielk1977633ed082002-05-17 00:05:58 +0000768 if( pChanges ){
drh1d1f3052002-05-21 13:18:25 +0000769 int ii;
danielk1977c3f9bad2002-05-15 08:30:12 +0000770
771 aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
772 if( aXRef==0 ) goto trigger_cleanup;
danielk1977633ed082002-05-17 00:05:58 +0000773 for(ii = 0; ii < pTab->nCol; ii++){
danielk1977c3f9bad2002-05-15 08:30:12 +0000774 aXRef[ii] = -1;
danielk1977633ed082002-05-17 00:05:58 +0000775 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000776
777 for(ii=0; ii<pChanges->nExpr; ii++){
778 int jj;
779 if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0,
danielk1977f29ce552002-05-19 23:43:12 +0000780 pChanges->a[ii].pExpr) ){
drh9adf9ac2002-05-15 11:44:13 +0000781 goto trigger_cleanup;
danielk1977f29ce552002-05-19 23:43:12 +0000782 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000783
784 if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
drh9adf9ac2002-05-15 11:44:13 +0000785 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000786
787 for(jj=0; jj<pTab->nCol; jj++){
drh9adf9ac2002-05-15 11:44:13 +0000788 if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
789 aXRef[jj] = ii;
790 break;
791 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000792 }
793 if( jj>=pTab->nCol ){
drhda93d232003-03-31 02:12:46 +0000794 sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[ii].zName);
drh9adf9ac2002-05-15 11:44:13 +0000795 goto trigger_cleanup;
danielk1977c3f9bad2002-05-15 08:30:12 +0000796 }
797 }
798
799 sqliteVdbeAddOp(v, OP_Integer, 13, 0);
800
danielk1977633ed082002-05-17 00:05:58 +0000801 for(ii = 0; ii<pTab->nCol; ii++){
802 if( aXRef[ii] < 0 ){
drh9adf9ac2002-05-15 11:44:13 +0000803 sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
danielk1977f29ce552002-05-19 23:43:12 +0000804 }else{
drh9adf9ac2002-05-15 11:44:13 +0000805 sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
danielk1977633ed082002-05-17 00:05:58 +0000806 }
807 }
danielk1977c3f9bad2002-05-15 08:30:12 +0000808
809 sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
810 sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
811 sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
812
813 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE,
danielk19776f349032002-06-11 02:25:40 +0000814 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000815 sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER,
danielk19776f349032002-06-11 02:25:40 +0000816 pTab, newIdx, oldIdx, orconf, endOfLoop);
danielk1977f29ce552002-05-19 23:43:12 +0000817 }else{
danielk1977c3f9bad2002-05-15 08:30:12 +0000818 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000819 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000820 sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx,
danielk19776f349032002-06-11 02:25:40 +0000821 orconf, endOfLoop);
danielk1977c3f9bad2002-05-15 08:30:12 +0000822 }
823
824 sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
825
826 sqliteVdbeResolveLabel(v, endOfLoop);
827 sqliteEndWriteOperation(pParse);
828
829trigger_cleanup:
830 sqliteFree(aXRef);
831 sqliteExprListDelete(pChanges);
832 sqliteExprDelete(pWhere);
833 sqliteExprListDelete(theSelect.pEList);
drhad3cab52002-05-24 02:04:32 +0000834 sqliteSrcListDelete(theSelect.pSrc);
danielk1977c3f9bad2002-05-15 08:30:12 +0000835 sqliteExprDelete(theSelect.pWhere);
836 return;
837}