From 1b7f3cc02d6129b678ab651716c19d2bf8f7f6ab Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 23 Nov 2002 03:59:09 +0000 Subject: This patch implements FOR EACH STATEMENT triggers, per my email to -hackers a couple days ago. Notes/caveats: - added regression tests for the new functionality, all regression tests pass on my machine - added pg_dump support - updated PL/PgSQL to support per-statement triggers; didn't look at the other procedural languages. - there's (even) more code duplication in trigger.c than there was previously. Any suggestions on how to refactor the ExecXXXTriggers() functions to reuse more code would be welcome -- I took a brief look at it, but couldn't see an easy way to do it (there are several subtly-different versions of the code in question) - updated the documentation. I also took the liberty of removing a big chunk of duplicated syntax documentation in the Programmer's Guide on triggers, and moving that information to the CREATE TRIGGER reference page. - I also included some spelling fixes and similar small cleanups I noticed while making the changes. If you'd like me to split those into a separate patch, let me know. Neil Conway --- src/backend/executor/execMain.c | 63 +++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 15 deletions(-) (limited to 'src/backend/executor/execMain.c') diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 65afe082031..779d44a8e01 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -13,7 +13,7 @@ * * These three procedures are the external interfaces to the executor. * In each case, the query descriptor and the execution state is required - * as arguments + * as arguments * * ExecutorStart() must be called at the beginning of any execution of any * query plan and ExecutorEnd() should always be called at the end of @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.186 2002/11/13 00:44:08 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.187 2002/11/23 03:59:07 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -908,12 +908,12 @@ ExecutePlan(EState *estate, ScanDirection direction, DestReceiver *destfunc) { - JunkFilter *junkfilter; - TupleTableSlot *slot; - ItemPointer tupleid = NULL; - ItemPointerData tuple_ctid; - long current_tuple_count; - TupleTableSlot *result; + JunkFilter *junkfilter; + TupleTableSlot *slot; + ItemPointer tupleid = NULL; + ItemPointerData tuple_ctid; + long current_tuple_count; + TupleTableSlot *result; /* * initialize local variables @@ -927,6 +927,24 @@ ExecutePlan(EState *estate, */ estate->es_direction = direction; + /* + * Process BEFORE EACH STATEMENT triggers + */ + switch (operation) + { + case CMD_UPDATE: + ExecBSUpdateTriggers(estate, estate->es_result_relation_info); + break; + case CMD_DELETE: + ExecBSDeleteTriggers(estate, estate->es_result_relation_info); + break; + case CMD_INSERT: + ExecBSInsertTriggers(estate, estate->es_result_relation_info); + break; + default: + /* do nothing */ + } + /* * Loop until we've processed the proper number of tuples from the * plan. @@ -1124,6 +1142,24 @@ lnext: ; break; } + /* + * Process AFTER EACH STATEMENT triggers + */ + switch (operation) + { + case CMD_UPDATE: + ExecASUpdateTriggers(estate, estate->es_result_relation_info); + break; + case CMD_DELETE: + ExecASDeleteTriggers(estate, estate->es_result_relation_info); + break; + case CMD_INSERT: + ExecASInsertTriggers(estate, estate->es_result_relation_info); + break; + default: + /* do nothing */ + } + /* * here, result is either a slot containing a tuple in the case of a * SELECT or NULL otherwise. @@ -1205,7 +1241,7 @@ ExecInsert(TupleTableSlot *slot, /* BEFORE ROW INSERT Triggers */ if (resultRelInfo->ri_TrigDesc && - resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) + resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) { HeapTuple newtuple; @@ -1256,8 +1292,7 @@ ExecInsert(TupleTableSlot *slot, ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); /* AFTER ROW INSERT Triggers */ - if (resultRelInfo->ri_TrigDesc) - ExecARInsertTriggers(estate, resultRelInfo, tuple); + ExecARInsertTriggers(estate, resultRelInfo, tuple); } /* ---------------------------------------------------------------- @@ -1346,8 +1381,7 @@ ldelete:; */ /* AFTER ROW DELETE Triggers */ - if (resultRelInfo->ri_TrigDesc) - ExecARDeleteTriggers(estate, resultRelInfo, tupleid); + ExecARDeleteTriggers(estate, resultRelInfo, tupleid); } /* ---------------------------------------------------------------- @@ -1498,8 +1532,7 @@ lreplace:; ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); /* AFTER ROW UPDATE Triggers */ - if (resultRelInfo->ri_TrigDesc) - ExecARUpdateTriggers(estate, resultRelInfo, tupleid, tuple); + ExecARUpdateTriggers(estate, resultRelInfo, tupleid, tuple); } static char * -- cgit v1.2.3