I wrote: > I wonder whether it is worth creating a C trigger function > (probably in regress.c) specifically to exercise this situation.
Actually, that doesn't seem too bad at all. I propose applying and back-patching the attached. BTW, I noticed while doing this that the adjacent "funny_dup17" trigger is dead code, and has been since commit 1547ee01 of 1999-09-29. I'm inclined to rip it out, because anyone looking at regress.c would naturally assume that anything in there is being exercised. regards, tom lane
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index fffc009..fbd176b 100644 *** a/src/backend/commands/trigger.c --- b/src/backend/commands/trigger.c *************** ExecBRUpdateTriggers(EState *estate, EPQ *** 2815,2821 **** return NULL; /* "do nothing" */ } } ! if (trigtuple != fdw_trigtuple) heap_freetuple(trigtuple); if (newtuple != slottuple) --- 2815,2821 ---- return NULL; /* "do nothing" */ } } ! if (trigtuple != fdw_trigtuple && trigtuple != newtuple) heap_freetuple(trigtuple); if (newtuple != slottuple) diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index ce8fa21..4771069 100644 *** a/src/test/regress/expected/triggers.out --- b/src/test/regress/expected/triggers.out *************** DROP TABLE fkeys2; *** 153,158 **** --- 153,184 ---- -- select count(*) from dup17 where x = 13; -- -- DROP TABLE dup17; + -- Check behavior when trigger returns unmodified trigtuple + create table trigtest (f1 int, f2 text); + create trigger trigger_return_old + before insert or delete or update on trigtest + for each row execute procedure trigger_return_old(); + insert into trigtest values(1, 'foo'); + select * from trigtest; + f1 | f2 + ----+----- + 1 | foo + (1 row) + + update trigtest set f2 = f2 || 'bar'; + select * from trigtest; + f1 | f2 + ----+----- + 1 | foo + (1 row) + + delete from trigtest; + select * from trigtest; + f1 | f2 + ----+---- + (0 rows) + + drop table trigtest; create sequence ttdummy_seq increment 10 start 0 minvalue 0; create table tttest ( price_id int4, diff --git a/src/test/regress/input/create_function_1.source b/src/test/regress/input/create_function_1.source index cde78eb..6b6bcd8 100644 *** a/src/test/regress/input/create_function_1.source --- b/src/test/regress/input/create_function_1.source *************** CREATE FUNCTION funny_dup17 () *** 42,47 **** --- 42,52 ---- AS '@libdir@/regress@DLSUFFIX@' LANGUAGE C; + CREATE FUNCTION trigger_return_old () + RETURNS trigger + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C; + CREATE FUNCTION ttdummy () RETURNS trigger AS '@libdir@/regress@DLSUFFIX@' diff --git a/src/test/regress/output/create_function_1.source b/src/test/regress/output/create_function_1.source index ab601be..9154b4a 100644 *** a/src/test/regress/output/create_function_1.source --- b/src/test/regress/output/create_function_1.source *************** CREATE FUNCTION funny_dup17 () *** 39,44 **** --- 39,48 ---- RETURNS trigger AS '@libdir@/regress@DLSUFFIX@' LANGUAGE C; + CREATE FUNCTION trigger_return_old () + RETURNS trigger + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C; CREATE FUNCTION ttdummy () RETURNS trigger AS '@libdir@/regress@DLSUFFIX@' diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index 13e7207..521b181 100644 *** a/src/test/regress/regress.c --- b/src/test/regress/regress.c *************** funny_dup17(PG_FUNCTION_ARGS) *** 444,449 **** --- 444,465 ---- return PointerGetDatum(tuple); } + PG_FUNCTION_INFO_V1(trigger_return_old); + + Datum + trigger_return_old(PG_FUNCTION_ARGS) + { + TriggerData *trigdata = (TriggerData *) fcinfo->context; + HeapTuple tuple; + + if (!CALLED_AS_TRIGGER(fcinfo)) + elog(ERROR, "trigger_return_old: not fired by trigger manager"); + + tuple = trigdata->tg_trigtuple; + + return PointerGetDatum(tuple); + } + #define TTDUMMY_INFINITY 999999 static SPIPlanPtr splan = NULL; diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index ae8349c..2bad469 100644 *** a/src/test/regress/sql/triggers.sql --- b/src/test/regress/sql/triggers.sql *************** DROP TABLE fkeys2; *** 138,143 **** --- 138,159 ---- -- -- DROP TABLE dup17; + -- Check behavior when trigger returns unmodified trigtuple + create table trigtest (f1 int, f2 text); + + create trigger trigger_return_old + before insert or delete or update on trigtest + for each row execute procedure trigger_return_old(); + + insert into trigtest values(1, 'foo'); + select * from trigtest; + update trigtest set f2 = f2 || 'bar'; + select * from trigtest; + delete from trigtest; + select * from trigtest; + + drop table trigtest; + create sequence ttdummy_seq increment 10 start 0 minvalue 0; create table tttest (