diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index b97766654d2..4ade09d2c9a 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -3159,6 +3159,25 @@ SELECT * from loc1; 2 | skidoo triggered ! (2 rows) +EXPLAIN (verbose, costs off) +UPDATE rem1 set f1 = 10; -- all columns should be transmitted + QUERY PLAN +----------------------------------------------------------------------- + Update on public.rem1 + Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1 + -> Foreign Scan on public.rem1 + Output: 10, f2, ctid, rem1.* + Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE +(5 rows) + +UPDATE rem1 set f1 = 10; +SELECT * from loc1; + f1 | f2 +----+-------------------------------- + 10 | skidoo triggered ! triggered ! + 10 | skidoo triggered ! triggered ! +(2 rows) + DELETE FROM rem1; -- Add a second trigger, to check that the changes are propagated correctly -- from trigger to trigger @@ -3271,7 +3290,7 @@ NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (13,"test triggered !") ctid -------- - (0,27) + (0,29) (1 row) -- =================================================================== @@ -3657,12 +3676,12 @@ AFTER UPDATE OR DELETE ON bar2 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); explain (verbose, costs off) update bar set f2 = f2 + 100; - QUERY PLAN --------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------- Update on public.bar Update on public.bar Foreign Update on public.bar2 - Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2, f3 + Remote SQL: UPDATE public.loct2 SET f1 = $2, f2 = $3, f3 = $4 WHERE ctid = $1 RETURNING f1, f2, f3 -> Seq Scan on public.bar Output: bar.f1, (bar.f2 + 100), bar.ctid -> Foreign Scan on public.bar2 diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 54d4d3a4816..e279f1d0b9d 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -1201,12 +1201,19 @@ postgresPlanForeignModify(PlannerInfo *root, /* * In an INSERT, we transmit all columns that are defined in the foreign - * table. In an UPDATE, we transmit only columns that were explicitly - * targets of the UPDATE, so as to avoid unnecessary data transmission. - * (We can't do that for INSERT since we would miss sending default values - * for columns not listed in the source statement.) + * table. In an UPDATE, if there are BEFORE ROW UPDATE triggers on the + * foreign table, we transmit all columns like INSERT; else we transmit + * only columns that were explicitly targets of the UPDATE, so as to avoid + * unnecessary data transmission. (We can't do that for INSERT since we + * would miss sending default values for columns not listed in the source + * statement, and for UPDATE if there are BEFORE ROW UPDATE triggers since + * those triggers might change values for non-target columns, in which + * case we would miss sending changed values for those columns.) */ - if (operation == CMD_INSERT) + if (operation == CMD_INSERT || + (operation == CMD_UPDATE && + rel->trigdesc && + rel->trigdesc->trig_update_before_row)) { TupleDesc tupdesc = RelationGetDescr(rel); int attnum; diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index a439239bff6..1a4718d1c62 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -677,6 +677,11 @@ SELECT * from loc1; UPDATE rem1 set f2 = 'skidoo' RETURNING f2; SELECT * from loc1; +EXPLAIN (verbose, costs off) +UPDATE rem1 set f1 = 10; -- all columns should be transmitted +UPDATE rem1 set f1 = 10; +SELECT * from loc1; + DELETE FROM rem1; -- Add a second trigger, to check that the changes are propagated correctly