diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index e75a59d2995..2886aebef4b 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2815,7 +2815,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, return NULL; /* "do nothing" */ } } - if (trigtuple != fdw_trigtuple) + 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 1d5405aad9e..007fa74bb62 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -133,6 +133,32 @@ DROP TABLE fkeys2; -- 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 f2b1561cc24..f89038eb5e9 100644 --- a/src/test/regress/input/create_function_1.source +++ b/src/test/regress/input/create_function_1.source @@ -42,6 +42,11 @@ CREATE FUNCTION funny_dup17 () 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 957595c51e4..557d629ad81 100644 --- a/src/test/regress/output/create_function_1.source +++ b/src/test/regress/output/create_function_1.source @@ -39,6 +39,10 @@ CREATE FUNCTION funny_dup17 () 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 b73bccec3d4..a6af6d59c39 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -446,6 +446,22 @@ funny_dup17(PG_FUNCTION_ARGS) 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 2b2236ed7d9..434710ff202 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -131,6 +131,22 @@ DROP TABLE fkeys2; -- -- 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 (