diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index fffc0095a79..fbd176b5d03 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 1b99dec27dc..99be9ac6e9e 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -119,6 +119,32 @@ SELECT trigger_name, event_manipulation, event_object_schema, event_object_table DROP TABLE pkeys; DROP TABLE fkeys; DROP TABLE fkeys2; +-- 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 825974d2ac1..04511050b14 100644 --- a/src/test/regress/input/create_function_1.source +++ b/src/test/regress/input/create_function_1.source @@ -37,6 +37,11 @@ CREATE FUNCTION autoinc () AS '@libdir@/autoinc@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 6c3f5e9c64b..18d2a150168 100644 --- a/src/test/regress/output/create_function_1.source +++ b/src/test/regress/output/create_function_1.source @@ -35,6 +35,10 @@ CREATE FUNCTION autoinc () RETURNS trigger AS '@libdir@/autoinc@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 064351f7b07..a0058ed6a82 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -203,6 +203,21 @@ reverse_name(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(new_string); } +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 diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index b7643826e8f..3354f4899f7 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -103,6 +103,22 @@ DROP TABLE pkeys; DROP TABLE fkeys; DROP TABLE fkeys2; +-- 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 (