diff options
author | Robert Haas <rhaas@postgresql.org> | 2018-05-16 11:32:38 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2018-05-16 11:32:38 -0400 |
commit | 7fc7dac1a711d0dbd01d2daf6dc97d27d6c6409c (patch) | |
tree | b7d6b20978bc54bd81788f88c77d5db974869d46 /contrib/postgres_fdw | |
parent | 09b12d52db1cf1a4c72d876f3fb6c9d06919e51a (diff) | |
download | postgresql-7fc7dac1a711d0dbd01d2daf6dc97d27d6c6409c.tar.gz postgresql-7fc7dac1a711d0dbd01d2daf6dc97d27d6c6409c.zip |
Pass the correct PlannerInfo to PlanForeignModify/PlanDirectModify.
Previously, we passed the toplevel PlannerInfo, but we actually want
to pass the relevant subroot. One problem with passing the toplevel
PlannerInfo is that the FDW which wants to push down an UPDATE or
DELETE against a join won't find the relevant joinrel there.
As of commit 1bc0100d270e5bcc980a0629b8726a32a497e788, postgres_fdw
tries to do exactly this and can be made to fail an assertion as a
result.
It's possible that this should be regarded as a bug fix and
back-patched to earlier releases, but for lack of a test case that
fails in earlier releases, no back-patch for now.
Etsuro Fujita, reviewed by Amit Langote.
Discussion: http://postgr.es/m/5AF43E02.30000@lab.ntt.co.jp
Diffstat (limited to 'contrib/postgres_fdw')
-rw-r--r-- | contrib/postgres_fdw/expected/postgres_fdw.out | 75 | ||||
-rw-r--r-- | contrib/postgres_fdw/sql/postgres_fdw.sql | 32 |
2 files changed, 107 insertions, 0 deletions
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index bb6b1a8fdf6..e803c0b39ca 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -7370,6 +7370,81 @@ drop table bar cascade; NOTICE: drop cascades to foreign table bar2 drop table loct1; drop table loct2; +-- Test pushing down UPDATE/DELETE joins to the remote server +create table parent (a int, b text); +create table loct1 (a int, b text); +create table loct2 (a int, b text); +create foreign table remt1 (a int, b text) + server loopback options (table_name 'loct1'); +create foreign table remt2 (a int, b text) + server loopback options (table_name 'loct2'); +alter foreign table remt1 inherit parent; +insert into remt1 values (1, 'foo'); +insert into remt1 values (2, 'bar'); +insert into remt2 values (1, 'foo'); +insert into remt2 values (2, 'bar'); +analyze remt1; +analyze remt2; +explain (verbose, costs off) +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------- + Update on public.parent + Output: parent.a, parent.b, remt2.a, remt2.b + Update on public.parent + Foreign Update on public.remt1 + -> Nested Loop + Output: parent.a, (parent.b || remt2.b), parent.ctid, remt2.*, remt2.a, remt2.b + Join Filter: (parent.a = remt2.a) + -> Seq Scan on public.parent + Output: parent.a, parent.b, parent.ctid + -> Foreign Scan on public.remt2 + Output: remt2.b, remt2.*, remt2.a + Remote SQL: SELECT a, b FROM public.loct2 + -> Foreign Update + Remote SQL: UPDATE public.loct1 r4 SET b = (r4.b || r2.b) FROM public.loct2 r2 WHERE ((r4.a = r2.a)) RETURNING r4.a, r4.b, r2.a, r2.b +(14 rows) + +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *; + a | b | a | b +---+--------+---+----- + 1 | foofoo | 1 | foo + 2 | barbar | 2 | bar +(2 rows) + +explain (verbose, costs off) +delete from parent using remt2 where parent.a = remt2.a returning parent; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Delete on public.parent + Output: parent.* + Delete on public.parent + Foreign Delete on public.remt1 + -> Nested Loop + Output: parent.ctid, remt2.* + Join Filter: (parent.a = remt2.a) + -> Seq Scan on public.parent + Output: parent.ctid, parent.a + -> Foreign Scan on public.remt2 + Output: remt2.*, remt2.a + Remote SQL: SELECT a, b FROM public.loct2 + -> Foreign Delete + Remote SQL: DELETE FROM public.loct1 r4 USING public.loct2 r2 WHERE ((r4.a = r2.a)) RETURNING r4.a, r4.b +(14 rows) + +delete from parent using remt2 where parent.a = remt2.a returning parent; + parent +------------ + (1,foofoo) + (2,barbar) +(2 rows) + +-- cleanup +drop foreign table remt1; +drop foreign table remt2; +drop table loct1; +drop table loct2; +drop table parent; -- =================================================================== -- test tuple routing for foreign-table partitions -- =================================================================== diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index 231b1e01a5f..cdfd9c960e5 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -1767,6 +1767,38 @@ drop table bar cascade; drop table loct1; drop table loct2; +-- Test pushing down UPDATE/DELETE joins to the remote server +create table parent (a int, b text); +create table loct1 (a int, b text); +create table loct2 (a int, b text); +create foreign table remt1 (a int, b text) + server loopback options (table_name 'loct1'); +create foreign table remt2 (a int, b text) + server loopback options (table_name 'loct2'); +alter foreign table remt1 inherit parent; + +insert into remt1 values (1, 'foo'); +insert into remt1 values (2, 'bar'); +insert into remt2 values (1, 'foo'); +insert into remt2 values (2, 'bar'); + +analyze remt1; +analyze remt2; + +explain (verbose, costs off) +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *; +update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *; +explain (verbose, costs off) +delete from parent using remt2 where parent.a = remt2.a returning parent; +delete from parent using remt2 where parent.a = remt2.a returning parent; + +-- cleanup +drop foreign table remt1; +drop foreign table remt2; +drop table loct1; +drop table loct2; +drop table parent; + -- =================================================================== -- test tuple routing for foreign-table partitions -- =================================================================== |