diff options
author | Robert Haas <rhaas@postgresql.org> | 2016-03-28 21:50:28 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2016-03-28 21:50:28 -0400 |
commit | 5d4171d1c70edfe3e9be1de9e66603af28e3afe1 (patch) | |
tree | e74ee89c0af8ea0662fc001ba9ce965d6a2890c8 /contrib/postgres_fdw | |
parent | 868628e4fd44d75987d6c099ac63613cc5417629 (diff) | |
download | postgresql-5d4171d1c70edfe3e9be1de9e66603af28e3afe1.tar.gz postgresql-5d4171d1c70edfe3e9be1de9e66603af28e3afe1.zip |
Don't require a user mapping for FDWs to work.
Commit fbe5a3fb73102c2cfec11aaaa4a67943f4474383 accidentally changed
this behavior; put things back the way they were, and add some
regression tests.
Report by Andres Freund; patch by Ashutosh Bapat, with a bit of
kibitzing by me.
Diffstat (limited to 'contrib/postgres_fdw')
-rw-r--r-- | contrib/postgres_fdw/expected/postgres_fdw.out | 61 | ||||
-rw-r--r-- | contrib/postgres_fdw/postgres_fdw.c | 10 | ||||
-rw-r--r-- | contrib/postgres_fdw/sql/postgres_fdw.sql | 9 |
3 files changed, 72 insertions, 8 deletions
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out index 96535d41806..50f1261e63f 100644 --- a/contrib/postgres_fdw/expected/postgres_fdw.out +++ b/contrib/postgres_fdw/expected/postgres_fdw.out @@ -1958,13 +1958,30 @@ EXECUTE join_stmt; -- change the session user to view_owner and execute the statement. Because of -- change in session user, the plan should get invalidated and created again. --- While creating the plan, it should throw error since there is no user mapping --- available for view_owner. +-- The join will not be pushed down since the joining relations do not have a +-- valid user mapping. SET SESSION ROLE view_owner; EXPLAIN (COSTS OFF, VERBOSE) EXECUTE join_stmt; -ERROR: user mapping not found for "view_owner" -EXECUTE join_stmt; -ERROR: user mapping not found for "view_owner" + QUERY PLAN +------------------------------------------------------------------ + Limit + Output: t1.c1, t2.c1 + -> Sort + Output: t1.c1, t2.c1 + Sort Key: t1.c1, t2.c1 + -> Hash Left Join + Output: t1.c1, t2.c1 + Hash Cond: (t1.c1 = t2.c1) + -> Foreign Scan on public.ft4 t1 + Output: t1.c1, t1.c2, t1.c3 + Remote SQL: SELECT c1 FROM "S 1"."T 3" + -> Hash + Output: t2.c1 + -> Foreign Scan on public.ft5 t2 + Output: t2.c1 + Remote SQL: SELECT c1 FROM "S 1"."T 4" +(16 rows) + RESET ROLE; DEALLOCATE join_stmt; CREATE VIEW v_ft5 AS SELECT * FROM ft5; @@ -2021,6 +2038,40 @@ EXECUTE join_stmt; ----+---- (0 rows) +-- If a sub-join can't be pushed down, upper level join shouldn't be either. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 FROM (ft5 t1 JOIN v_ft5 t2 ON (t1.c1 = t2.c1)) left join (ft5 t3 JOIN v_ft5 t4 ON (t3.c1 = t4.c1)) ON (t1.c1 = t3.c1); + QUERY PLAN +------------------------------------------------------------------ + Hash Join + Output: t1.c1, ft5.c1 + Hash Cond: (t1.c1 = ft5.c1) + -> Hash Right Join + Output: t1.c1 + Hash Cond: (t3.c1 = t1.c1) + -> Hash Join + Output: t3.c1 + Hash Cond: (t3.c1 = ft5_1.c1) + -> Foreign Scan on public.ft5 t3 + Output: t3.c1, t3.c2, t3.c3 + Remote SQL: SELECT c1 FROM "S 1"."T 4" + -> Hash + Output: ft5_1.c1 + -> Foreign Scan on public.ft5 ft5_1 + Output: ft5_1.c1 + Remote SQL: SELECT c1 FROM "S 1"."T 4" + -> Hash + Output: t1.c1 + -> Foreign Scan on public.ft5 t1 + Output: t1.c1 + Remote SQL: SELECT c1 FROM "S 1"."T 4" + -> Hash + Output: ft5.c1 + -> Foreign Scan on public.ft5 + Output: ft5.c1 + Remote SQL: SELECT c1 FROM "S 1"."T 4" +(27 rows) + -- recreate the dropped user mapping for further tests CREATE USER MAPPING FOR CURRENT_USER SERVER loopback; DROP USER MAPPING FOR PUBLIC SERVER loopback; diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index f21689e73d1..4fbbde13bc5 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -3911,6 +3911,16 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype, List *otherclauses; /* + * Core code may call GetForeignJoinPaths hook even when the join + * relation doesn't have a valid user mapping associated with it. See + * build_join_rel() for details. We can't push down such join, since + * there doesn't exist a user mapping which can be used to connect to the + * foreign server. + */ + if (!OidIsValid(joinrel->umid)) + return false; + + /* * We support pushing down INNER, LEFT, RIGHT and FULL OUTER joins. * Constructing queries representing SEMI and ANTI joins is hard, hence * not considered right now. diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql index 61cbf55ab93..f420b230e76 100644 --- a/contrib/postgres_fdw/sql/postgres_fdw.sql +++ b/contrib/postgres_fdw/sql/postgres_fdw.sql @@ -478,11 +478,10 @@ EXPLAIN (COSTS OFF, VERBOSE) EXECUTE join_stmt; EXECUTE join_stmt; -- change the session user to view_owner and execute the statement. Because of -- change in session user, the plan should get invalidated and created again. --- While creating the plan, it should throw error since there is no user mapping --- available for view_owner. +-- The join will not be pushed down since the joining relations do not have a +-- valid user mapping. SET SESSION ROLE view_owner; EXPLAIN (COSTS OFF, VERBOSE) EXECUTE join_stmt; -EXECUTE join_stmt; RESET ROLE; DEALLOCATE join_stmt; @@ -506,6 +505,10 @@ CREATE USER MAPPING FOR view_owner SERVER loopback; EXPLAIN (COSTS false, VERBOSE) EXECUTE join_stmt; EXECUTE join_stmt; +-- If a sub-join can't be pushed down, upper level join shouldn't be either. +EXPLAIN (COSTS false, VERBOSE) +SELECT t1.c1, t2.c1 FROM (ft5 t1 JOIN v_ft5 t2 ON (t1.c1 = t2.c1)) left join (ft5 t3 JOIN v_ft5 t4 ON (t3.c1 = t4.c1)) ON (t1.c1 = t3.c1); + -- recreate the dropped user mapping for further tests CREATE USER MAPPING FOR CURRENT_USER SERVER loopback; DROP USER MAPPING FOR PUBLIC SERVER loopback; |