*** a/contrib/postgres_fdw/expected/postgres_fdw.out --- b/contrib/postgres_fdw/expected/postgres_fdw.out *************** *** 6459,6464 **** DROP TRIGGER trig_row_after ON rem1; --- 6459,6493 ---- DROP TRIGGER trig_stmt_before ON rem1; DROP TRIGGER trig_stmt_after ON rem1; DELETE from rem1; + CREATE TRIGGER trig_row_after1 + AFTER INSERT OR UPDATE OR DELETE ON rem1 + FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + CREATE TRIGGER trig_row_after2 + AFTER INSERT OR UPDATE OR DELETE ON rem1 + FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + insert into rem1 values(1,'insert'); + NOTICE: trig_row_after1(23, skidoo) AFTER ROW INSERT ON rem1 + NOTICE: NEW: (1,insert) + NOTICE: trig_row_after2(23, skidoo) AFTER ROW INSERT ON rem1 + NOTICE: NEW: (1,insert) + update rem1 set f2 = 'update' where f1 = 1; + NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 + NOTICE: OLD: (1,insert),NEW: (1,update) + NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 + NOTICE: OLD: (1,insert),NEW: (1,update) + update rem1 set f2 = f2 || f2; + NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 + NOTICE: OLD: (1,update),NEW: (1,updateupdate) + NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 + NOTICE: OLD: (1,update),NEW: (1,updateupdate) + delete from rem1; + NOTICE: trig_row_after1(23, skidoo) AFTER ROW DELETE ON rem1 + NOTICE: OLD: (1,updateupdate) + NOTICE: trig_row_after2(23, skidoo) AFTER ROW DELETE ON rem1 + NOTICE: OLD: (1,updateupdate) + -- cleanup + DROP TRIGGER trig_row_after1 ON rem1; + DROP TRIGGER trig_row_after2 ON rem1; -- Test WHEN conditions CREATE TRIGGER trig_row_before_insupd BEFORE INSERT OR UPDATE ON rem1 *************** *** 6689,6695 **** NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (13,"test triggered !") ctid -------- ! (0,29) (1 row) -- cleanup --- 6718,6724 ---- NOTICE: NEW: (13,"test triggered !") ctid -------- ! (0,32) (1 row) -- cleanup *** a/contrib/postgres_fdw/sql/postgres_fdw.sql --- b/contrib/postgres_fdw/sql/postgres_fdw.sql *************** *** 1485,1490 **** DROP TRIGGER trig_stmt_after ON rem1; --- 1485,1506 ---- DELETE from rem1; + CREATE TRIGGER trig_row_after1 + AFTER INSERT OR UPDATE OR DELETE ON rem1 + FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + + CREATE TRIGGER trig_row_after2 + AFTER INSERT OR UPDATE OR DELETE ON rem1 + FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + + insert into rem1 values(1,'insert'); + update rem1 set f2 = 'update' where f1 = 1; + update rem1 set f2 = f2 || f2; + delete from rem1; + + -- cleanup + DROP TRIGGER trig_row_after1 ON rem1; + DROP TRIGGER trig_row_after2 ON rem1; -- Test WHEN conditions *** a/doc/src/sgml/trigger.sgml --- b/doc/src/sgml/trigger.sgml *************** *** 511,518 **** typedef struct TriggerData HeapTuple tg_trigtuple; HeapTuple tg_newtuple; Trigger *tg_trigger; ! Buffer tg_trigtuplebuf; ! Buffer tg_newtuplebuf; Tuplestorestate *tg_oldtable; Tuplestorestate *tg_newtable; } TriggerData; --- 511,518 ---- HeapTuple tg_trigtuple; HeapTuple tg_newtuple; Trigger *tg_trigger; ! TupleTableSlot *tg_trigslot; ! TupleTableSlot *tg_newslot; Tuplestorestate *tg_oldtable; Tuplestorestate *tg_newtable; } TriggerData; *************** *** 714,734 **** typedef struct Trigger ! tg_trigtuplebuf ! The buffer containing tg_trigtuple, or InvalidBuffer if there ! is no such tuple or it is not stored in a disk buffer. ! tg_newtuplebuf ! The buffer containing tg_newtuple, or InvalidBuffer if there ! is no such tuple or it is not stored in a disk buffer. --- 714,734 ---- ! tg_trigslot ! The slot containing tg_trigtuple, ! or a NULL pointer if there is no such tuple. ! tg_newslot ! The slot containing tg_newtuple, ! or a NULL pointer if there is no such tuple. *** a/src/backend/commands/trigger.c --- b/src/backend/commands/trigger.c *************** *** 4255,4266 **** AfterTriggerExecute(EState *estate, LocTriggerData.tg_trigtuple = ExecFetchSlotHeapTuple(trig_tuple_slot1, true, &should_free_trig); ! LocTriggerData.tg_newslot = trig_tuple_slot2; ! LocTriggerData.tg_newtuple = ! ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) == ! TRIGGER_EVENT_UPDATE) ? ! ExecFetchSlotHeapTuple(trig_tuple_slot2, true, &should_free_new) : NULL; ! break; default: --- 4255,4271 ---- LocTriggerData.tg_trigtuple = ExecFetchSlotHeapTuple(trig_tuple_slot1, true, &should_free_trig); ! if ((evtshared->ats_event & TRIGGER_EVENT_OPMASK) == ! TRIGGER_EVENT_UPDATE) ! { ! LocTriggerData.tg_newslot = trig_tuple_slot2; ! LocTriggerData.tg_newtuple = ! ExecFetchSlotHeapTuple(trig_tuple_slot2, true, &should_free_new); ! } ! else ! { ! LocTriggerData.tg_newtuple = NULL; ! } break; default: *************** *** 4355,4364 **** AfterTriggerExecute(EState *estate, if (should_free_new) heap_freetuple(LocTriggerData.tg_newtuple); ! if (LocTriggerData.tg_trigslot) ! ExecClearTuple(LocTriggerData.tg_trigslot); ! if (LocTriggerData.tg_newslot) ! ExecClearTuple(LocTriggerData.tg_newslot); /* * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count --- 4360,4373 ---- if (should_free_new) heap_freetuple(LocTriggerData.tg_newtuple); ! /* don't clear slots' contents if foreign table */ ! if (trig_tuple_slot1 == NULL) ! { ! if (LocTriggerData.tg_trigslot) ! ExecClearTuple(LocTriggerData.tg_trigslot); ! if (LocTriggerData.tg_newslot) ! ExecClearTuple(LocTriggerData.tg_newslot); ! } /* * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count