]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Simplify the trigger logic for DELETE, INSERT, and UPDATE. (CVS 2157)
authordrh <drh@noemail.net>
Tue, 7 Dec 2004 14:06:13 +0000 (14:06 +0000)
committerdrh <drh@noemail.net>
Tue, 7 Dec 2004 14:06:13 +0000 (14:06 +0000)
FossilOrigin-Name: 8e164ab27771aced9a592ea4b7c27e9f184181a5

manifest
manifest.uuid
src/delete.c
src/insert.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/vdbe.c

index 8e777fa3a89039f1bde9f182f1111f5dccdff993..bcd7b91265937ab1e8d0bb36bd2419cbd769cca4 100644 (file)
--- 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
index df7ec2d0f42b63b09c6f9b49e7dd1da3252b382a..bc050fb56f95ec7342d7dcd3c1ebc2f79e0883e0 100644 (file)
@@ -1 +1 @@
-7b20f2b71f679e72b6cb3b78ccb31b4e7c4bd48b
\ No newline at end of file
+8e164ab27771aced9a592ea4b7c27e9f184181a5
\ No newline at end of file
index a0d30ea9d3ca00c2b820970b5ce185e10c14d2cf..609628c3fd4ebd2e8655a9a6434a3f3f70c35b6d 100644 (file)
@@ -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->iDb<db->nDb );
@@ -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);
       }
index 738c803d95ccd9b968c7a933d5f4b4a137f2a815..025c4205ac5d72df65f48c9e8d4ae9ff1e9cec46 100644 (file)
@@ -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++){
index 43f9afa1feef45a991c17bfcffe90d503edd3df8..c67d56dff00b424a66d41c29ab8af22a13c43bae 100644 (file)
@@ -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 <column-list> trigger,
                              the <column-list> 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*);
index da80459101b9c970e6032436a3dffcfa8120e011..d4469bf1ad13cda32a98e9d3cbab358a14bbac0c 100644 (file)
@@ -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;
-
-  pTriggerCursor = pTrigger;
-  while( pTriggerCursor ){
-    if( pTriggerCursor->op == op && 
-       pTriggerCursor->tr_tm == tr_tm && 
-       pTriggerCursor->foreach == foreach &&
-       checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
-      TriggerStack * ss;
+  Trigger *pTrigger = pTab->pTrigger;
+  int mask = 0;
+
+  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 ){
index 4dd040ee5b6abc889221b181fbca7af2821ce0fb..9b7d9fc8c013eb7fddf3227ff639a3c6117e5498 100644 (file)
@@ -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);
index 48e09089af59ddb6cc0f63fa63aa2ea0c599f236..3931e38a01d74f65a5c1dc4e45242b2afba9e1da 100644 (file)
@@ -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"