diff --git a/manifest b/manifest index 8e777fa3a8..bcd7b91265 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sunused\ssqlite3_context.isStep\selement.\s(CVS\s2156) -D 2004-12-07T12:29:18 +C Simplify\sthe\strigger\slogic\sfor\sDELETE,\sINSERT,\sand\sUPDATE.\s(CVS\s2157) +D 2004-12-07T14:06:13 F Makefile.in da09f379b80c8cd78d78abaa0f32ca90a124e884 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -34,12 +34,12 @@ F src/btree.h 861e40b759a195ba63819740e484390012cf81ab F src/build.c 306e49e1f6f19741a40c1bbc23140027aa4f8cc9 F src/cursor.c f883813759742068890b1f699335872bfa8fdf41 F src/date.c 65536e7ea04fdde6e0551264fca15966966e171f -F src/delete.c 9083377a4c5b152b4466021592f32e3e8a3819e3 +F src/delete.c 4a70ac0bd0159fe38efdaf2cb44723256b0f7b37 F src/expr.c 7987e5f50c189d4c2550f247f8039c06ea272345 F src/func.c b668e5ad043176049454c95a6a780367a0e8f6bb F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 -F src/insert.c 9524a6c3e86cbdbae3313f6a083bb9a3e7a2462b +F src/insert.c 094972ccacff759042b0692b558a8ac114e5d417 F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b F src/main.c fc383dc9cf03847b96e5ed9942696467725cfdfd F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 @@ -62,7 +62,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 36cc9da999596578566e167d310e99f2005a7f03 F src/shell.c e8f4f486cbf6e60d81173146ac8a6522c930fa51 F src/sqlite.h.in fa75850f412808afd38fddc1fd6456f4efc6fb97 -F src/sqliteInt.h 1dc643cf84f1d83bd45e314f724bb824ee24c000 +F src/sqliteInt.h 3343e12d160d49fcca224c29ee39f5e6d6f980db F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c 68b45ae5a96424abdc1732cb03b1efbb0c1821b3 F src/test1.c b7d94c54e58f95452387a5cabdf98b2be8059f29 @@ -71,12 +71,12 @@ F src/test3.c 6f1ec93e13632a004b527049535079eda84c459d F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5 F src/tokenize.c 2ad3d1ae1a0a70746db0b31a0a74f58050a3c39a -F src/trigger.c 0c91b56182560263733e4b035acdb939bd1cf0e2 -F src/update.c d79d1936c5603b3ce2ee22557618b6baad67efba +F src/trigger.c 98f3b07c08ba01b34cff139ef9687883d325ae8e +F src/update.c 67a95e5c24cbedb7f943cd95c1082c112b401f25 F src/utf.c e45ce11be6922408cd381561721f6cca7d3b992a F src/util.c 4a8db4e97a3cfda12ad8dda3e77dd2d00ad1de5e F src/vacuum.c 705256e1111521fa04f0029de7f1667bc131d015 -F src/vdbe.c fb9260cd92556d1a32538af1b1b761232337aff1 +F src/vdbe.c aaec606fb513102314ca351006cea6656791bdcf F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbeInt.h 0f74561e629af86172de7cdf0ecaea014c51696c F src/vdbeapi.c 74be7f96c0a1ac275661f8b32276ac521d9ce37c @@ -262,7 +262,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c -P 46584348f3cc10c0c6e9ba42110a6c03caf1497e -R 993dd8bd273e62b479ee8b37d9936fc4 +P 7b20f2b71f679e72b6cb3b78ccb31b4e7c4bd48b +R d980a20ed4665faa1df32ccf64263d38 U drh -Z 96d5b22a935bba53de9bbed3780ad692 +Z dcfe3e605fa32f759f8dbe1e7c83903c diff --git a/manifest.uuid b/manifest.uuid index df7ec2d0f4..bc050fb56f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7b20f2b71f679e72b6cb3b78ccb31b4e7c4bd48b \ No newline at end of file +8e164ab27771aced9a592ea4b7c27e9f184181a5 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index a0d30ea9d3..609628c3fd 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.91 2004/11/23 01:47:30 drh Exp $ +** $Id: delete.c,v 1.92 2004/12/07 14:06:13 drh Exp $ */ #include "sqliteInt.h" @@ -87,9 +87,7 @@ void sqlite3DeleteFrom( #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ - int row_triggers_exist = 0; /* True if any triggers exist */ - int before_triggers; /* True if there are BEFORE triggers */ - int after_triggers; /* True if there are AFTER triggers */ + int triggers_exist = 0; /* True if any triggers exist */ #endif sContext.pParse = 0; @@ -112,16 +110,10 @@ void sqlite3DeleteFrom( ** deleted from is a view */ #ifndef SQLITE_OMIT_TRIGGER - before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_DELETE, TK_BEFORE, TK_ROW, 0); - after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_DELETE, TK_AFTER, TK_ROW, 0); - row_triggers_exist = before_triggers || after_triggers; + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); isView = pTab->pSelect!=0; #else -# define before_triggers 0 -# define after_triggers 0 -# define row_triggers_exist 0 +# define triggers_exist 0 # define isView 0 #endif #ifdef SQLITE_OMIT_VIEW @@ -129,7 +121,7 @@ void sqlite3DeleteFrom( # define isView 0 #endif - if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto delete_from_cleanup; } assert( pTab->iDbnDb ); @@ -146,7 +138,7 @@ void sqlite3DeleteFrom( /* Allocate a cursor used to store the old.* data for a trigger. */ - if( row_triggers_exist ){ + if( triggers_exist ){ oldIdx = pParse->nTab++; } @@ -171,7 +163,7 @@ void sqlite3DeleteFrom( goto delete_from_cleanup; } if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); + sqlite3BeginWriteOperation(pParse, triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. @@ -193,7 +185,7 @@ void sqlite3DeleteFrom( ** It is easier just to erase the whole table. Note, however, that ** this means that the row change count will be incorrect. */ - if( pWhere==0 && !row_triggers_exist ){ + if( pWhere==0 && !triggers_exist ){ if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ @@ -245,7 +237,7 @@ void sqlite3DeleteFrom( /* Open the pseudo-table used to store OLD if there are triggers. */ - if( row_triggers_exist ){ + if( triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); } @@ -260,7 +252,7 @@ void sqlite3DeleteFrom( /* This is the beginning of the delete loop when there are ** row triggers. */ - if( row_triggers_exist ){ + if( triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); if( !isView ){ @@ -274,8 +266,8 @@ void sqlite3DeleteFrom( sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } - (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, - oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, + (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, + -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, addr); } @@ -290,7 +282,7 @@ void sqlite3DeleteFrom( /* This is the beginning of the delete loop when there are no ** row triggers */ - if( !row_triggers_exist ){ + if( !triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); } @@ -301,14 +293,14 @@ void sqlite3DeleteFrom( /* If there are row triggers, close all cursors then invoke ** the AFTER triggers */ - if( row_triggers_exist ){ + if( triggers_exist ){ if( !isView ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } - (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, + (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default, addr); } @@ -319,7 +311,7 @@ void sqlite3DeleteFrom( sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); /* Close the cursors after the loop if there are no row triggers */ - if( !row_triggers_exist ){ + if( !triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } diff --git a/src/insert.c b/src/insert.c index 738c803d95..025c4205ac 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.126 2004/11/13 03:48:07 drh Exp $ +** $Id: insert.c,v 1.127 2004/12/07 14:06:13 drh Exp $ */ #include "sqliteInt.h" @@ -194,9 +194,7 @@ void sqlite3Insert( #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to insert into a view */ - int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ - int before_triggers; /* True if there are BEFORE triggers */ - int after_triggers; /* True if there are AFTER triggers */ + int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ #endif #ifndef SQLITE_OMIT_AUTOINCREMENT @@ -226,16 +224,10 @@ void sqlite3Insert( ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER - before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_INSERT, TK_BEFORE, TK_ROW, 0); - after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_INSERT, TK_AFTER, TK_ROW, 0); - row_triggers_exist = before_triggers || after_triggers; + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0); isView = pTab->pSelect!=0; #else -# define before_triggers 0 -# define after_triggers 0 -# define row_triggers_exist 0 +# define triggers_exist 0 # define isView 0 #endif #ifdef SQLITE_OMIT_VIEW @@ -247,7 +239,7 @@ void sqlite3Insert( * (a) the table is not read-only, * (b) that if it is a view then ON INSERT triggers exist */ - if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto insert_cleanup; } if( pTab==0 ) goto insert_cleanup; @@ -270,10 +262,10 @@ void sqlite3Insert( v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); - sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb); + sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, pTab->iDb); /* if there are row triggers, allocate a temp table for new.* references. */ - if( row_triggers_exist ){ + if( triggers_exist ){ newIdx = pParse->nTab++; } @@ -335,7 +327,7 @@ void sqlite3Insert( ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ - if( row_triggers_exist ){ + if( triggers_exist ){ useTempTable = 1; }else{ int addr = 0; @@ -456,7 +448,7 @@ void sqlite3Insert( /* Open the temp table for FOR EACH ROW triggers */ - if( row_triggers_exist ){ + if( triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); } @@ -470,7 +462,7 @@ void sqlite3Insert( } /* Open tables and indices if there are no row triggers */ - if( !row_triggers_exist ){ + if( !triggers_exist ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } @@ -492,7 +484,7 @@ void sqlite3Insert( /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqlite3VdbeMakeLabel(v); - if( before_triggers ){ + if( triggers_exist & TRIGGER_BEFORE ){ /* build the NEW.* reference row. Note that if there is an INTEGER ** PRIMARY KEY into which a NULL is being inserted, that NULL will be @@ -547,7 +539,7 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); /* Fire BEFORE or INSTEAD OF triggers */ - if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, newIdx, -1, onError, endOfLoop) ){ goto insert_cleanup; } @@ -556,7 +548,7 @@ void sqlite3Insert( /* If any triggers exists, the opening of tables and indices is deferred ** until now. */ - if( row_triggers_exist && !isView ){ + if( triggers_exist && !isView ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } @@ -627,7 +619,7 @@ void sqlite3Insert( sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, 0, onError, endOfLoop); sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, - after_triggers ? newIdx : -1); + (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1); } /* Update the count of rows that are inserted @@ -636,7 +628,7 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0); } - if( row_triggers_exist ){ + if( triggers_exist ){ /* Close all tables opened */ if( !isView ){ sqlite3VdbeAddOp(v, OP_Close, base, 0); @@ -646,8 +638,8 @@ void sqlite3Insert( } /* Code AFTER triggers */ - if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, - onError, endOfLoop) ){ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab, + newIdx, -1, onError, endOfLoop) ){ goto insert_cleanup; } } @@ -665,7 +657,7 @@ void sqlite3Insert( sqlite3VdbeResolveLabel(v, iCleanup); } - if( !row_triggers_exist ){ + if( !triggers_exist ){ /* Close all tables opened */ sqlite3VdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 43f9afa1fe..c67d56dff0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.344 2004/11/23 01:47:30 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.345 2004/12/07 14:06:13 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1100,7 +1100,7 @@ struct Trigger { u8 iDb; /* Database containing this trigger */ u8 iTabDb; /* Database containing Trigger.table */ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */ - u8 tr_tm; /* One of TK_BEFORE, TK_AFTER */ + u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */ IdList *pColumns; /* If this is an UPDATE OF trigger, the is stored here */ @@ -1111,6 +1111,16 @@ struct Trigger { Trigger *pNext; /* Next trigger associated with the table */ }; +/* +** A trigger is either a BEFORE or an AFTER trigger. The following constants +** determine which. +** +** If there are multiple triggers, you might of some BEFORE and some AFTER. +** In that cases, the constants below can be ORed together. +*/ +#define TRIGGER_BEFORE 1 +#define TRIGGER_AFTER 2 + /* * An instance of struct TriggerStep is used to store a single SQL statement * that is a part of a trigger-program. @@ -1399,7 +1409,7 @@ void sqlite3ChangeCookie(sqlite3*, Vdbe*, int); void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); void sqlite3DropTrigger(Parse*, SrcList*); void sqlite3DropTriggerPtr(Parse*, Trigger*, int); - int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*); + int sqlite3TriggersExist(Parse*, Table*, int, ExprList*); int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); diff --git a/src/trigger.c b/src/trigger.c index da80459101..d4469bf1ad 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -111,9 +111,7 @@ void sqlite3BeginTrigger( } /* Do not create a trigger on a system table */ - if( (iDb!=1 && sqlite3StrICmp(pTab->zName, MASTER_NAME)==0) || - (iDb==1 && sqlite3StrICmp(pTab->zName, TEMP_MASTER_NAME)==0) - ){ + if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ sqlite3ErrorMsg(pParse, "cannot create trigger on system table"); pParse->nErr++; goto trigger_cleanup; @@ -167,7 +165,7 @@ void sqlite3BeginTrigger( pTrigger->iDb = iDb; pTrigger->iTabDb = pTab->iDb; pTrigger->op = op; - pTrigger->tr_tm = tr_tm; + pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER; pTrigger->pWhen = sqlite3ExprDup(pWhen); pTrigger->pColumns = sqlite3IdListDup(pColumns); pTrigger->foreach = foreach; @@ -557,37 +555,37 @@ static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){ } /* - * Returns true if a trigger matching op, tr_tm and foreach that is NOT already - * on the Parse objects trigger-stack (to prevent recursive trigger firing) is - * found in the list specified as pTrigger. - */ +** Return a bit vector to indicate what kind of triggers exist for operation +** "op" on table pTab. If pChanges is not NULL then it is a list of columns +** that are being updated. Triggers only match if the ON clause of the +** trigger definition overlaps the set of columns being updated. +** +** The returned bit vector is some combination of TRIGGER_BEFORE and +** TRIGGER_AFTER. +*/ int sqlite3TriggersExist( Parse *pParse, /* Used to check for recursive triggers */ - Trigger *pTrigger, /* A list of triggers associated with a table */ + Table *pTab, /* The table the contains the triggers */ int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ - int tr_tm, /* one of TK_BEFORE, TK_AFTER */ - int foreach, /* one of TK_ROW or TK_STATEMENT */ ExprList *pChanges /* Columns that change in an UPDATE statement */ ){ - Trigger * pTriggerCursor; + Trigger *pTrigger = pTab->pTrigger; + int mask = 0; - pTriggerCursor = pTrigger; - while( pTriggerCursor ){ - if( pTriggerCursor->op == op && - pTriggerCursor->tr_tm == tr_tm && - pTriggerCursor->foreach == foreach && - checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){ - TriggerStack * ss; + while( pTrigger ){ + if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){ + TriggerStack *ss; ss = pParse->trigStack; - while( ss && ss->pTrigger != pTrigger ){ + while( ss && ss->pTrigger!=pTab->pTrigger ){ ss = ss->pNext; } - if( !ss )return 1; + if( ss==0 ){ + mask |= pTrigger->tr_tm; + } } - pTriggerCursor = pTriggerCursor->pNext; + pTrigger = pTrigger->pNext; } - - return 0; + return mask; } /* @@ -713,7 +711,7 @@ int sqlite3CodeRowTrigger( Parse *pParse, /* Parse context */ int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */ ExprList *pChanges, /* Changes list for any UPDATE OF triggers */ - int tr_tm, /* One of TK_BEFORE, TK_AFTER */ + int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */ Table *pTab, /* The table to code triggers from */ int newIdx, /* The indice of the "new" row to access */ int oldIdx, /* The indice of the "old" row to access */ @@ -725,7 +723,7 @@ int sqlite3CodeRowTrigger( TriggerStack trigStackEntry; assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); - assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER ); + assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER ); assert(newIdx != -1 || oldIdx != -1); @@ -734,8 +732,7 @@ int sqlite3CodeRowTrigger( int fire_this = 0; /* determine whether we should code this trigger */ - if( pTrigger->op == op && pTrigger->tr_tm == tr_tm && - pTrigger->foreach == TK_ROW ){ + if( pTrigger->op == op && pTrigger->tr_tm == tr_tm ){ fire_this = 1; for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){ if( pStack->pTrigger==pTrigger ){ diff --git a/src/update.c b/src/update.c index 4dd040ee5b..9b7d9fc8c0 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.97 2004/11/23 01:47:30 drh Exp $ +** $Id: update.c,v 1.98 2004/12/07 14:06:13 drh Exp $ */ #include "sqliteInt.h" @@ -52,9 +52,7 @@ void sqlite3Update( #ifndef SQLITE_OMIT_TRIGGER int isView; /* Trying to update a view */ - int before_triggers; /* True if there are any BEFORE triggers */ - int after_triggers; /* True if there are any AFTER triggers */ - int row_triggers_exist = 0; /* True if any row triggers exist */ + int triggers_exist = 0; /* True if any row triggers exist */ #endif int newIdx = -1; /* index of trigger "new" temp table */ @@ -74,16 +72,10 @@ void sqlite3Update( ** updated is a view */ #ifndef SQLITE_OMIT_TRIGGER - before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_UPDATE, TK_BEFORE, TK_ROW, pChanges); - after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_UPDATE, TK_AFTER, TK_ROW, pChanges); - row_triggers_exist = before_triggers || after_triggers; + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges); isView = pTab->pSelect!=0; #else -# define before_triggers 0 -# define after_triggers 0 -# define row_triggers_exist 0 +# define triggers_exist 0 # define isView 0 #endif #ifdef SQLITE_OMIT_VIEW @@ -91,7 +83,7 @@ void sqlite3Update( # define isView 0 #endif - if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ goto update_cleanup; } if( isView ){ @@ -106,7 +98,7 @@ void sqlite3Update( /* If there are FOR EACH ROW triggers, allocate cursors for the ** special OLD and NEW tables */ - if( row_triggers_exist ){ + if( triggers_exist ){ newIdx = pParse->nTab++; oldIdx = pParse->nTab++; } @@ -252,7 +244,7 @@ void sqlite3Update( sqlite3VdbeAddOp(v, OP_Integer, 0, 0); } - if( row_triggers_exist ){ + if( triggers_exist ){ /* Create pseudo-tables for NEW and OLD */ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); @@ -312,7 +304,7 @@ void sqlite3Update( /* Fire the BEFORE and INSTEAD OF triggers */ - if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, + if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab, newIdx, oldIdx, onError, addr) ){ goto update_cleanup; } @@ -354,7 +346,7 @@ void sqlite3Update( ** Also, the old data is needed to delete the old index entires. ** So make the cursor point at the old record. */ - if( !row_triggers_exist ){ + if( !triggers_exist ){ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); @@ -414,7 +406,7 @@ void sqlite3Update( /* If there are triggers, close all the cursors after each iteration ** through the loop. The fire the after triggers. */ - if( row_triggers_exist ){ + if( triggers_exist ){ if( !isView ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ) @@ -422,7 +414,7 @@ void sqlite3Update( } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } - if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, + if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, newIdx, oldIdx, onError, addr) ){ goto update_cleanup; } @@ -436,7 +428,7 @@ void sqlite3Update( sqlite3VdbeAddOp(v, OP_ListReset, 0, 0); /* Close all tables if there were no FOR EACH ROW triggers */ - if( !row_triggers_exist ){ + if( !triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); diff --git a/src/vdbe.c b/src/vdbe.c index 48e09089af..3931e38a01 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.432 2004/12/07 12:29:18 drh Exp $ +** $Id: vdbe.c,v 1.433 2004/12/07 14:06:13 drh Exp $ */ #include "sqliteInt.h" #include "os.h"