*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***************
*** 123,128 **** static void deparseTargetList(StringInfo buf,
--- 123,129 ----
  				  Bitmapset *attrs_used,
  				  bool qualify_col,
  				  List **retrieved_attrs);
+ static const char *get_jointype_name(JoinType jointype);
  static void deparseExplicitTargetList(List *tlist, List **retrieved_attrs,
  						  deparse_expr_cxt *context);
  static void deparseReturningList(StringInfo buf, PlannerInfo *root,
***************
*** 1062,1068 **** appendConditions(List *exprs, deparse_expr_cxt *context)
  }
  
  /* Output join name for given join type */
! extern const char *
  get_jointype_name(JoinType jointype)
  {
  	switch (jointype)
--- 1063,1069 ----
  }
  
  /* Output join name for given join type */
! static const char *
  get_jointype_name(JoinType jointype)
  {
  	switch (jointype)
*** a/contrib/postgres_fdw/expected/postgres_fdw.out
--- b/contrib/postgres_fdw/expected/postgres_fdw.out
***************
*** 455,467 **** EXPLAIN (VERBOSE, COSTS OFF)
     ->  Merge Right Join
           Output: t1."C 1"
           Merge Cond: (t3.c1 = t1."C 1")
!          ->  Foreign Scan
                 Output: t3.c1
-                Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
                 Remote SQL: SELECT r3."C 1" FROM ("S 1"."T 1" r2 INNER JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r2."C 1" ASC NULLS LAST
           ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
                 Output: t1."C 1"
! (11 rows)
  
  SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
   C 1 
--- 455,466 ----
     ->  Merge Right Join
           Output: t1."C 1"
           Merge Cond: (t3.c1 = t1."C 1")
!          ->  Foreign Join on public.ft1 t2, public.ft2 t3
                 Output: t3.c1
                 Remote SQL: SELECT r3."C 1" FROM ("S 1"."T 1" r2 INNER JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r2."C 1" ASC NULLS LAST
           ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
                 Output: t1."C 1"
! (10 rows)
  
  SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
   C 1 
***************
*** 490,502 **** EXPLAIN (VERBOSE, COSTS OFF)
     ->  Merge Right Join
           Output: t1."C 1", t2.c1, t3.c1
           Merge Cond: (t3.c1 = t1."C 1")
!          ->  Foreign Scan
                 Output: t3.c1, t2.c1
-                Relations: (public.ft2 t3) LEFT JOIN (public.ft1 t2)
                 Remote SQL: SELECT r3."C 1", r2."C 1" FROM ("S 1"."T 1" r3 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
           ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
                 Output: t1."C 1"
! (11 rows)
  
  SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
   C 1 | c1  | c1  
--- 489,500 ----
     ->  Merge Right Join
           Output: t1."C 1", t2.c1, t3.c1
           Merge Cond: (t3.c1 = t1."C 1")
!          ->  Foreign Join on public.ft1 t2, public.ft2 t3
                 Output: t3.c1, t2.c1
                 Remote SQL: SELECT r3."C 1", r2."C 1" FROM ("S 1"."T 1" r3 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
           ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
                 Output: t1."C 1"
! (10 rows)
  
  SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
   C 1 | c1  | c1  
***************
*** 523,535 **** EXPLAIN (VERBOSE, COSTS OFF)
     ->  Merge Full Join
           Output: t1."C 1", t2.c1, t3.c1
           Merge Cond: (t3.c1 = t1."C 1")
!          ->  Foreign Scan
                 Output: t2.c1, t3.c1
-                Relations: (public.ft1 t2) FULL JOIN (public.ft2 t3)
                 Remote SQL: SELECT r2."C 1", r3."C 1" FROM ("S 1"."T 1" r2 FULL JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
           ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
                 Output: t1."C 1"
! (11 rows)
  
  SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
   C 1 | c1  | c1  
--- 521,532 ----
     ->  Merge Full Join
           Output: t1."C 1", t2.c1, t3.c1
           Merge Cond: (t3.c1 = t1."C 1")
!          ->  Foreign Join on public.ft1 t2, public.ft2 t3
                 Output: t2.c1, t3.c1
                 Remote SQL: SELECT r2."C 1", r3."C 1" FROM ("S 1"."T 1" r2 FULL JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
           ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
                 Output: t1."C 1"
! (10 rows)
  
  SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
   C 1 | c1  | c1  
***************
*** 975,985 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1, t1.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c1, t1.c3
-          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
           Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
   c1  | c1  
--- 972,981 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1, t1.c3
!    ->  Foreign Join on public.ft1 t1, public.ft2 t2
           Output: t1.c1, t2.c1, t1.c3
           Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
   c1  | c1  
***************
*** 1006,1016 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t
     ->  Sort
           Output: t1.c1, t2.c2, t3.c3, t1.c3
           Sort Key: t1.c3, t1.c1
!          ->  Foreign Scan
                 Output: t1.c1, t2.c2, t3.c3, t1.c3
-                Relations: ((public.ft1 t1) INNER JOIN (public.ft2 t2)) INNER JOIN (public.ft4 t3)
                 Remote SQL: SELECT r1."C 1", r1.c3, r2.c2, r4.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) INNER JOIN "S 1"."T 3" r4 ON (((r1."C 1" = r4.c1))))
! (9 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1002,1011 ----
     ->  Sort
           Output: t1.c1, t2.c2, t3.c3, t1.c3
           Sort Key: t1.c3, t1.c1
!          ->  Foreign Join on public.ft1 t1, public.ft2 t2, public.ft4 t3
                 Output: t1.c1, t2.c2, t3.c3, t1.c3
                 Remote SQL: SELECT r1."C 1", r1.c3, r2.c2, r4.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) INNER JOIN "S 1"."T 3" r4 ON (((r1."C 1" = r4.c1))))
! (8 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1034,1044 **** SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1
!    ->  Foreign Scan
           Output: t1.c1, t2.c1
-          Relations: (public.ft4 t1) LEFT JOIN (public.ft5 t2)
           Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c1 
--- 1029,1038 ----
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1
!    ->  Foreign Join on public.ft4 t1, public.ft5 t2
           Output: t1.c1, t2.c1
           Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c1 
***************
*** 1062,1072 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 LEFT JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1056,1065 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 LEFT JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1090,1100 **** EXPLAIN (VERBOSE, COSTS OFF)
  SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
                                                                            QUERY PLAN                                                                           
  ---------------------------------------------------------------------------------------------------------------------------------------------------------------
!  Foreign Scan
     Output: t1.c1, t1.c2, ft5.c1, ft5.c2
-    Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
     Remote SQL: SELECT r1.c1, r1.c2, r4.c1, r4.c2 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r4 ON (((r1.c1 = r4.c1)) AND ((r4.c1 < 10)))) WHERE ((r1.c1 < 10))
! (4 rows)
  
  SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
   c1 | c2 | c1 | c2 
--- 1083,1092 ----
  SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
                                                                            QUERY PLAN                                                                           
  ---------------------------------------------------------------------------------------------------------------------------------------------------------------
!  Foreign Join on public.ft4 t1, public.ft5
     Output: t1.c1, t1.c2, ft5.c1, ft5.c2
     Remote SQL: SELECT r1.c1, r1.c2, r4.c1, r4.c2 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r4 ON (((r1.c1 = r4.c1)) AND ((r4.c1 < 10)))) WHERE ((r1.c1 < 10))
! (3 rows)
  
  SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
   c1 | c2 | c1 | c2 
***************
*** 1112,1122 **** SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE
  			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
                                                                                                QUERY PLAN                                                                                               
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
!  Foreign Scan
     Output: t1.c1, t1.c2, ft5.c1, ft5.c2
-    Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
     Remote SQL: SELECT r1.c1, r1.c2, r4.c1, r4.c2 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r4 ON (((r1.c1 = r4.c1)) AND ((r4.c1 < 10)))) WHERE (((r4.c1 < 10) OR (r4.c1 IS NULL))) AND ((r1.c1 < 10))
! (4 rows)
  
  SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1)
  			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
--- 1104,1113 ----
  			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
                                                                                                QUERY PLAN                                                                                               
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
!  Foreign Join on public.ft4 t1, public.ft5
     Output: t1.c1, t1.c2, ft5.c1, ft5.c2
     Remote SQL: SELECT r1.c1, r1.c2, r4.c1, r4.c2 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r4 ON (((r1.c1 = r4.c1)) AND ((r4.c1 < 10)))) WHERE (((r4.c1 < 10) OR (r4.c1 IS NULL))) AND ((r1.c1 < 10))
! (3 rows)
  
  SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1)
  			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
***************
*** 1135,1145 **** SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1
!    ->  Foreign Scan
           Output: t1.c1, t2.c1
-          Relations: (public.ft4 t2) LEFT JOIN (public.ft5 t1)
           Remote SQL: SELECT r2.c1, r1.c1 FROM ("S 1"."T 3" r2 LEFT JOIN "S 1"."T 4" r1 ON (((r1.c1 = r2.c1)))) ORDER BY r2.c1 ASC NULLS LAST, r1.c1 ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10;
   c1 | c1 
--- 1126,1135 ----
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1
!    ->  Foreign Join on public.ft5 t1, public.ft4 t2
           Output: t1.c1, t2.c1
           Remote SQL: SELECT r2.c1, r1.c1 FROM ("S 1"."T 3" r2 LEFT JOIN "S 1"."T 4" r1 ON (((r1.c1 = r2.c1)))) ORDER BY r2.c1 ASC NULLS LAST, r1.c1 ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10;
   c1 | c1 
***************
*** 1163,1173 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGH
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
           Remote SQL: SELECT r4.c3, r2.c2, r1."C 1" FROM (("S 1"."T 3" r4 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r4.c1)))) LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1153,1162 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r4.c3, r2.c2, r1."C 1" FROM (("S 1"."T 3" r4 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r4.c1)))) LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1191,1201 **** SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1
!    ->  Foreign Scan
           Output: t1.c1, t2.c1
-          Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
           Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10;
   c1  | c1 
--- 1180,1189 ----
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1
!    ->  Foreign Join on public.ft4 t1, public.ft5 t2
           Output: t1.c1, t2.c1
           Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10;
   c1  | c1 
***************
*** 1253,1263 **** SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 a
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1, t3.c1
!    ->  Foreign Scan
           Output: t1.c1, t2.c1, t3.c1
-          Relations: ((public.ft4 t1) INNER JOIN (public.ft5 t2)) FULL JOIN (public.ft4 t3)
           Remote SQL: SELECT r1.c1, r2.c1, r4.c1 FROM (("S 1"."T 3" r1 INNER JOIN "S 1"."T 4" r2 ON (((r1.c1 = (r2.c1 + 1))) AND ((r1.c1 >= 50)) AND ((r1.c1 <= 60)))) FULL JOIN "S 1"."T 3" r4 ON (((r2.c1 = r4.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST, r4.c1 ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10;
   c1 | c1 | c1 
--- 1241,1250 ----
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c1, t3.c1
!    ->  Foreign Join on public.ft4 t1, public.ft5 t2, public.ft4 t3
           Output: t1.c1, t2.c1, t3.c1
           Remote SQL: SELECT r1.c1, r2.c1, r4.c1 FROM (("S 1"."T 3" r1 INNER JOIN "S 1"."T 4" r2 ON (((r1.c1 = (r2.c1 + 1))) AND ((r1.c1 >= 50)) AND ((r1.c1 <= 60)))) FULL JOIN "S 1"."T 3" r4 ON (((r2.c1 = r4.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST, r4.c1 ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10;
   c1 | c1 | c1 
***************
*** 1281,1291 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1268,1277 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1309,1319 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
           Remote SQL: SELECT r4.c3, r2.c2, r1."C 1" FROM (("S 1"."T 3" r4 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r4.c1)))) LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1295,1304 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r4.c3, r2.c2, r1."C 1" FROM (("S 1"."T 3" r4 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r4.c1)))) LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1337,1347 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) FULL JOIN (public.ft4 t3)
           Remote SQL: SELECT r2.c2, r1."C 1", r4.c3 FROM (("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1322,1331 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r2.c2, r1."C 1", r4.c3 FROM (("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1365,1375 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1349,1358 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1393,1403 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 LEFT JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1376,1385 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 LEFT JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1421,1431 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) LEFT JOIN (public.ft4 t3)
           Remote SQL: SELECT r2.c2, r1."C 1", r4.c3 FROM (("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1403,1412 ----
  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r2.c2, r1."C 1", r4.c3 FROM (("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1449,1459 **** SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Scan
           Output: t1.c1, t2.c2, t3.c3
-          Relations: (public.ft4 t3) LEFT JOIN ((public.ft2 t1) INNER JOIN (public.ft2 t2))
           Remote SQL: SELECT r4.c3, r1."C 1", r2.c2 FROM ("S 1"."T 3" r4 LEFT JOIN ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ON (((r2."C 1" = r4.c1))))
! (6 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
--- 1430,1439 ----
  -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.c1, t2.c2, t3.c3
!    ->  Foreign Join on public.ft2 t1, public.ft2 t2, public.ft4 t3
           Output: t1.c1, t2.c2, t3.c3
           Remote SQL: SELECT r4.c3, r1."C 1", r2.c2 FROM ("S 1"."T 3" r4 LEFT JOIN ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ON (((r2."C 1" = r4.c1))))
! (5 rows)
  
  SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
   c1 | c2 |   c3   
***************
*** 1480,1490 **** SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1
     ->  Sort
           Output: t1.c1, t2.c1
           Sort Key: t1.c1, t2.c1
!          ->  Foreign Scan
                 Output: t1.c1, t2.c1
-                Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
                 Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 = r2.c1) OR (r1.c1 IS NULL)))
! (9 rows)
  
  SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c1 
--- 1460,1469 ----
     ->  Sort
           Output: t1.c1, t2.c1
           Sort Key: t1.c1, t2.c1
!          ->  Foreign Join on public.ft4 t1, public.ft5 t2
                 Output: t1.c1, t2.c1
                 Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 = r2.c1) OR (r1.c1 IS NULL)))
! (8 rows)
  
  SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c1 
***************
*** 1511,1519 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Scan
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
-                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR UPDATE OF r1
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
--- 1490,1497 ----
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Join on public.ft1 t1, public.ft2 t2
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR UPDATE OF r1
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
***************
*** 1530,1536 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
! (23 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1;
   c1  | c1  
--- 1508,1514 ----
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
! (22 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1;
   c1  | c1  
***************
*** 1555,1563 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Scan
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
-                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR UPDATE OF r1 FOR UPDATE OF r2
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
--- 1533,1540 ----
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Join on public.ft1 t1, public.ft2 t2
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR UPDATE OF r1 FOR UPDATE OF r2
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
***************
*** 1574,1580 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
! (23 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE;
   c1  | c1  
--- 1551,1557 ----
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
! (22 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE;
   c1  | c1  
***************
*** 1600,1608 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Scan
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
-                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR SHARE OF r1
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
--- 1577,1584 ----
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Join on public.ft1 t1, public.ft2 t2
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR SHARE OF r1
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
***************
*** 1619,1625 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
! (23 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1;
   c1  | c1  
--- 1595,1601 ----
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
! (22 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1;
   c1  | c1  
***************
*** 1644,1652 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Scan
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
-                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR SHARE OF r1 FOR SHARE OF r2
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
--- 1620,1627 ----
     Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
     ->  LockRows
           Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
!          ->  Foreign Join on public.ft1 t1, public.ft2 t2
                 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
                 Remote SQL: SELECT r1."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR SHARE OF r1 FOR SHARE OF r2
                 ->  Merge Join
                       Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
***************
*** 1663,1669 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
! (23 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE;
   c1  | c1  
--- 1638,1644 ----
                             ->  Foreign Scan on public.ft2 t2
                                   Output: t2.c1, t2.*
                                   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
! (22 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE;
   c1  | c1  
***************
*** 1688,1703 **** WITH t (c1_1, c1_3, c2_1) AS (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2
   Limit
     Output: t.c1_1, t.c2_1, t.c1_3
     CTE t
!      ->  Foreign Scan
             Output: t1.c1, t1.c3, t2.c1
-            Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
             Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
     ->  Sort
           Output: t.c1_1, t.c2_1, t.c1_3
           Sort Key: t.c1_3, t.c1_1
           ->  CTE Scan on t
                 Output: t.c1_1, t.c2_1, t.c1_3
! (12 rows)
  
  WITH t (c1_1, c1_3, c2_1) AS (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10;
   c1_1 | c2_1 
--- 1663,1677 ----
   Limit
     Output: t.c1_1, t.c2_1, t.c1_3
     CTE t
!      ->  Foreign Join on public.ft1 t1, public.ft2 t2
             Output: t1.c1, t1.c3, t2.c1
             Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
     ->  Sort
           Output: t.c1_1, t.c2_1, t.c1_3
           Sort Key: t.c1_3, t.c1_1
           ->  CTE Scan on t
                 Output: t.c1_1, t.c2_1, t.c1_3
! (11 rows)
  
  WITH t (c1_1, c1_3, c2_1) AS (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10;
   c1_1 | c2_1 
***************
*** 1721,1731 **** SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER B
  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
!    ->  Foreign Scan
           Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
-          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
           Remote SQL: SELECT r1.ctid, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r1."C 1", r1.c3, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
! (6 rows)
  
  -- SEMI JOIN, not pushed down
  EXPLAIN (VERBOSE, COSTS OFF)
--- 1695,1704 ----
  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
!    ->  Foreign Join on public.ft1 t1, public.ft2 t2
           Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
           Remote SQL: SELECT r1.ctid, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r1."C 1", r1.c3, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
! (5 rows)
  
  -- SEMI JOIN, not pushed down
  EXPLAIN (VERBOSE, COSTS OFF)
***************
*** 1954,1965 **** SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.
     ->  Sort
           Output: t1.c1, t2.c1, t1.c3
           Sort Key: t1.c3, t1.c1
!          ->  Foreign Scan
                 Output: t1.c1, t2.c1, t1.c3
                 Filter: (t1.c8 = t2.c8)
-                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                 Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1", r1.c8, r2.c8 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
! (10 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
   c1  | c1  
--- 1927,1937 ----
     ->  Sort
           Output: t1.c1, t2.c1, t1.c3
           Sort Key: t1.c3, t1.c1
!          ->  Foreign Join on public.ft1 t1, public.ft2 t2
                 Output: t1.c1, t2.c1, t1.c3
                 Filter: (t1.c8 = t2.c8)
                 Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1", r1.c8, r2.c8 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
! (9 rows)
  
  SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
   c1  | c1  
***************
*** 1993,2007 **** SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2
                       Output: t1.c1, t2.c1
                       Group Key: t1.c1, t2.c1
                       ->  Append
!                            ->  Foreign Scan
                                   Output: t1.c1, t2.c1
-                                  Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                                   Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
!                            ->  Foreign Scan
                                   Output: t1_1.c1, t2_1.c1
-                                  Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
                                   Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
! (20 rows)
  
  SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10;
   t1c1 |         avg          
--- 1965,1977 ----
                       Output: t1.c1, t2.c1
                       Group Key: t1.c1, t2.c1
                       ->  Append
!                            ->  Foreign Join on public.ft1 t1, public.ft2 t2
                                   Output: t1.c1, t2.c1
                                   Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
!                            ->  Foreign Join on public.ft1 t1_1, public.ft2 t2_1
                                   Output: t1_1.c1, t2_1.c1
                                   Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
! (18 rows)
  
  SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10;
   t1c1 |         avg          
***************
*** 2032,2042 **** SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM
           ->  HashAggregate
                 Output: t2.c1, t3.c1
                 Group Key: t2.c1, t3.c1
!                ->  Foreign Scan
                       Output: t2.c1, t3.c1
-                      Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
                       Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")) AND ((r1.c2 = $1::integer))))
! (13 rows)
  
  SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10;
   C 1 
--- 2002,2011 ----
           ->  HashAggregate
                 Output: t2.c1, t3.c1
                 Group Key: t2.c1, t3.c1
!                ->  Foreign Join on public.ft1 t2, public.ft2 t3
                       Output: t2.c1, t3.c1
                       Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")) AND ((r1.c2 = $1::integer))))
! (12 rows)
  
  SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10;
   C 1 
***************
*** 2097,2107 **** SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT
           Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
     ->  Materialize
           Output: ft1.c1, ft2.c1, (13)
!          ->  Foreign Scan
                 Output: ft1.c1, ft2.c1, 13
-                Relations: (public.ft1) INNER JOIN (public.ft2)
                 Remote SQL: SELECT r4."C 1", r5."C 1" FROM ("S 1"."T 1" r4 INNER JOIN "S 1"."T 1" r5 ON (((r5."C 1" = 12)) AND ((r4."C 1" = 12)))) ORDER BY r4."C 1" ASC NULLS LAST
! (12 rows)
  
  SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15;
   c1 | a  | b  | c  
--- 2066,2075 ----
           Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
     ->  Materialize
           Output: ft1.c1, ft2.c1, (13)
!          ->  Foreign Join on public.ft1, public.ft2
                 Output: ft1.c1, ft2.c1, 13
                 Remote SQL: SELECT r4."C 1", r5."C 1" FROM ("S 1"."T 1" r4 INNER JOIN "S 1"."T 1" r5 ON (((r5."C 1" = 12)) AND ((r4."C 1" = 12)))) ORDER BY r4."C 1" ASC NULLS LAST
! (11 rows)
  
  SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15;
   c1 | a  | b  | c  
***************
*** 2117,2127 **** EXPLAIN (VERBOSE, COSTS OFF)
  SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
                                                                                                                                  QUERY PLAN                                                                                                                                 
  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
!  Foreign Scan
     Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
-    Relations: (public.ft5) INNER JOIN (public.ft4)
     Remote SQL: SELECT CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1.c1, r1.c2, r1.c3) END, r1.c1, r1.c2, r1.c3, r2.c1, r2.c2 FROM ("S 1"."T 4" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c1 = r2.c1)) AND ((r2.c1 >= 10)) AND ((r2.c1 <= 30)))) ORDER BY r1.c1 ASC NULLS LAST
! (4 rows)
  
  SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
        ft5       | c1 | c2 |   c3   | c1 | c2 
--- 2085,2094 ----
  SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
                                                                                                                                  QUERY PLAN                                                                                                                                 
  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
!  Foreign Join on public.ft5, public.ft4
     Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
     Remote SQL: SELECT CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1.c1, r1.c2, r1.c3) END, r1.c1, r1.c2, r1.c3, r2.c1, r2.c2 FROM ("S 1"."T 4" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c1 = r2.c1)) AND ((r2.c1 >= 10)) AND ((r2.c1 <= 30)))) ORDER BY r1.c1 ASC NULLS LAST
! (3 rows)
  
  SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
        ft5       | c1 | c2 |   c3   | c1 | c2 
***************
*** 2184,2194 **** SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1
  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: ft4.c1, ft5.c2, ft5.c1
!    ->  Foreign Scan
           Output: ft4.c1, ft5.c2, ft5.c1
-          Relations: (public.ft4) LEFT JOIN (public.ft5)
           Remote SQL: SELECT r6.c1, r9.c2, r9.c1 FROM ("S 1"."T 3" r6 LEFT JOIN "S 1"."T 4" r9 ON (((r6.c1 = r9.c1)))) ORDER BY r6.c1 ASC NULLS LAST, r9.c1 ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c2 
--- 2151,2160 ----
  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: ft4.c1, ft5.c2, ft5.c1
!    ->  Foreign Join on public.ft4, public.ft5
           Output: ft4.c1, ft5.c2, ft5.c1
           Remote SQL: SELECT r6.c1, r9.c2, r9.c1 FROM ("S 1"."T 3" r6 LEFT JOIN "S 1"."T 4" r9 ON (((r6.c1 = r9.c1)))) ORDER BY r6.c1 ASC NULLS LAST, r9.c1 ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c2 
***************
*** 2249,2259 **** SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c
  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: ft4.c1, t2.c2, t2.c1
!    ->  Foreign Scan
           Output: ft4.c1, t2.c2, t2.c1
-          Relations: (public.ft4) LEFT JOIN (public.ft5 t2)
           Remote SQL: SELECT r6.c1, r2.c2, r2.c1 FROM ("S 1"."T 3" r6 LEFT JOIN "S 1"."T 4" r2 ON (((r6.c1 = r2.c1)))) ORDER BY r6.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
! (6 rows)
  
  SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c2 
--- 2215,2224 ----
  --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Limit
     Output: ft4.c1, t2.c2, t2.c1
!    ->  Foreign Join on public.ft5 t2, public.ft4
           Output: ft4.c1, t2.c2, t2.c1
           Remote SQL: SELECT r6.c1, r2.c2, r2.c1 FROM ("S 1"."T 3" r6 LEFT JOIN "S 1"."T 4" r2 ON (((r6.c1 = r2.c1)))) ORDER BY r6.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
! (5 rows)
  
  SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
   c1 | c2 
***************
*** 2282,2292 **** PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $
  EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
                                                            QUERY PLAN                                                          
  ------------------------------------------------------------------------------------------------------------------------------
!  Foreign Scan
     Output: t1.c3, t2.c3
-    Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
     Remote SQL: SELECT r1.c3, r2.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = 2)) AND ((r1."C 1" = 1))))
! (4 rows)
  
  EXECUTE st1(1, 1);
    c3   |  c3   
--- 2247,2256 ----
  EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
                                                            QUERY PLAN                                                          
  ------------------------------------------------------------------------------------------------------------------------------
!  Foreign Join on public.ft1 t1, public.ft2 t2
     Output: t1.c3, t2.c3
     Remote SQL: SELECT r1.c3, r2.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = 2)) AND ((r1."C 1" = 1))))
! (3 rows)
  
  EXECUTE st1(1, 1);
    c3   |  c3   
***************
*** 2898,2906 **** UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Update on public.ft2
     Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c3 = $3, c7 = $4 WHERE ctid = $1
!    ->  Foreign Scan
           Output: ft2.c1, (ft2.c2 + 500), NULL::integer, (ft2.c3 || '_update9'::text), ft2.c4, ft2.c5, ft2.c6, 'ft2       '::character(10), ft2.c8, ft2.ctid, ft1.*
-          Relations: (public.ft2) INNER JOIN (public.ft1)
           Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c8, r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 9)))) FOR UPDATE OF r1
           ->  Hash Join
                 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft2.ctid, ft1.*
--- 2862,2869 ----
  ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Update on public.ft2
     Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c3 = $3, c7 = $4 WHERE ctid = $1
!    ->  Foreign Join on public.ft2, public.ft1
           Output: ft2.c1, (ft2.c2 + 500), NULL::integer, (ft2.c3 || '_update9'::text), ft2.c4, ft2.c5, ft2.c6, 'ft2       '::character(10), ft2.c8, ft2.ctid, ft1.*
           Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c8, r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 9)))) FOR UPDATE OF r1
           ->  Hash Join
                 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft2.ctid, ft1.*
***************
*** 2913,2919 **** UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
                       ->  Foreign Scan on public.ft1
                             Output: ft1.*, ft1.c1
                             Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 9))
! (17 rows)
  
  UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
    FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
--- 2876,2882 ----
                       ->  Foreign Scan on public.ft1
                             Output: ft1.*, ft1.c1
                             Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 9))
! (16 rows)
  
  UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
    FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
***************
*** 3041,3049 **** DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Delete on public.ft2
     Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1
!    ->  Foreign Scan
           Output: ft2.ctid, ft1.*
-          Relations: (public.ft2) INNER JOIN (public.ft1)
           Remote SQL: SELECT r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 2)))) FOR UPDATE OF r1
           ->  Hash Join
                 Output: ft2.ctid, ft1.*
--- 3004,3011 ----
  -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
   Delete on public.ft2
     Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1
!    ->  Foreign Join on public.ft2, public.ft1
           Output: ft2.ctid, ft1.*
           Remote SQL: SELECT r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 2)))) FOR UPDATE OF r1
           ->  Hash Join
                 Output: ft2.ctid, ft1.*
***************
*** 3056,3062 **** DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
                       ->  Foreign Scan on public.ft1
                             Output: ft1.*, ft1.c1
                             Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 2))
! (17 rows)
  
  DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
  SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
--- 3018,3024 ----
                       ->  Foreign Scan on public.ft1
                             Output: ft1.*, ft1.c1
                             Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 2))
! (16 rows)
  
  DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
  SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
*** a/contrib/postgres_fdw/postgres_fdw.c
--- b/contrib/postgres_fdw/postgres_fdw.c
***************
*** 66,78 **** enum FdwScanPrivateIndex
  	/* Integer list of attribute numbers retrieved by the SELECT */
  	FdwScanPrivateRetrievedAttrs,
  	/* Integer representing the desired fetch_size */
! 	FdwScanPrivateFetchSize,
! 
! 	/*
! 	 * String describing join i.e. names of relations being joined and types
! 	 * of join, added when the scan is join
! 	 */
! 	FdwScanPrivateRelations
  };
  
  /*
--- 66,72 ----
  	/* Integer list of attribute numbers retrieved by the SELECT */
  	FdwScanPrivateRetrievedAttrs,
  	/* Integer representing the desired fetch_size */
! 	FdwScanPrivateFetchSize
  };
  
  /*
***************
*** 473,481 **** postgresGetForeignRelSize(PlannerInfo *root,
  	PgFdwRelationInfo *fpinfo;
  	ListCell   *lc;
  	RangeTblEntry *rte = planner_rt_fetch(baserel->relid, root);
- 	const char *namespace;
- 	const char *relname;
- 	const char *refname;
  
  	/*
  	 * We use PgFdwRelationInfo to pass various information to subsequent
--- 467,472 ----
***************
*** 638,660 **** postgresGetForeignRelSize(PlannerInfo *root,
  								&fpinfo->rows, &fpinfo->width,
  								&fpinfo->startup_cost, &fpinfo->total_cost);
  	}
- 
- 	/*
- 	 * Set the name of relation in fpinfo, while we are constructing it here.
- 	 * It will be used to build the string describing the join relation in
- 	 * EXPLAIN output. We can't know whether VERBOSE option is specified or
- 	 * not, so always schema-qualify the foreign table name.
- 	 */
- 	fpinfo->relation_name = makeStringInfo();
- 	namespace = get_namespace_name(get_rel_namespace(foreigntableid));
- 	relname = get_rel_name(foreigntableid);
- 	refname = rte->eref->aliasname;
- 	appendStringInfo(fpinfo->relation_name, "%s.%s",
- 					 quote_identifier(namespace),
- 					 quote_identifier(relname));
- 	if (*refname && strcmp(refname, relname) != 0)
- 		appendStringInfo(fpinfo->relation_name, " %s",
- 						 quote_identifier(rte->eref->aliasname));
  }
  
  /*
--- 629,634 ----
***************
*** 1228,1236 **** postgresGetForeignPlan(PlannerInfo *root,
  							 remote_conds,
  							 retrieved_attrs,
  							 makeInteger(fpinfo->fetch_size));
- 	if (foreignrel->reloptkind == RELOPT_JOINREL)
- 		fdw_private = lappend(fdw_private,
- 							  makeString(fpinfo->relation_name->data));
  
  	/*
  	 * Create the ForeignScan node for the given relation.
--- 1202,1207 ----
***************
*** 2393,2417 **** postgresExplainForeignScan(ForeignScanState *node, ExplainState *es)
  {
  	List	   *fdw_private;
  	char	   *sql;
- 	char	   *relations;
- 
- 	fdw_private = ((ForeignScan *) node->ss.ps.plan)->fdw_private;
  
- 	/*
- 	 * Add names of relation handled by the foreign scan when the scan is a
- 	 * join
- 	 */
- 	if (list_length(fdw_private) > FdwScanPrivateRelations)
- 	{
- 		relations = strVal(list_nth(fdw_private, FdwScanPrivateRelations));
- 		ExplainPropertyText("Relations", relations, es);
- 	}
- 
- 	/*
- 	 * Add remote query, when VERBOSE option is specified.
- 	 */
  	if (es->verbose)
  	{
  		sql = strVal(list_nth(fdw_private, FdwScanPrivateSelectSql));
  		ExplainPropertyText("Remote SQL", sql, es);
  	}
--- 2364,2373 ----
  {
  	List	   *fdw_private;
  	char	   *sql;
  
  	if (es->verbose)
  	{
+ 		fdw_private = ((ForeignScan *) node->ss.ps.plan)->fdw_private;
  		sql = strVal(list_nth(fdw_private, FdwScanPrivateSelectSql));
  		ExplainPropertyText("Remote SQL", sql, es);
  	}
***************
*** 4171,4186 **** foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
  	else
  		fpinfo->fetch_size = fpinfo_i->fetch_size;
  
- 	/*
- 	 * Set the string describing this join relation to be used in EXPLAIN
- 	 * output of corresponding ForeignScan.
- 	 */
- 	fpinfo->relation_name = makeStringInfo();
- 	appendStringInfo(fpinfo->relation_name, "(%s) %s JOIN (%s)",
- 					 fpinfo_o->relation_name->data,
- 					 get_jointype_name(fpinfo->jointype),
- 					 fpinfo_i->relation_name->data);
- 
  	return true;
  }
  
--- 4127,4132 ----
*** a/contrib/postgres_fdw/postgres_fdw.h
--- b/contrib/postgres_fdw/postgres_fdw.h
***************
*** 80,92 **** typedef struct PgFdwRelationInfo
  
  	int			fetch_size;		/* fetch size for this remote table */
  
- 	/*
- 	 * Name of the relation while EXPLAINing ForeignScan. It is used for join
- 	 * relations but is set for all relations. For join relation, the name
- 	 * indicates which foreign tables are being joined and the join type used.
- 	 */
- 	StringInfo	relation_name;
- 
  	/* Join information */
  	RelOptInfo *outerrel;
  	RelOptInfo *innerrel;
--- 80,85 ----
***************
*** 164,169 **** extern void deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root,
  /* in shippable.c */
  extern bool is_builtin(Oid objectId);
  extern bool is_shippable(Oid objectId, Oid classId, PgFdwRelationInfo *fpinfo);
- extern const char *get_jointype_name(JoinType jointype);
  
  #endif   /* POSTGRES_FDW_H */
--- 157,161 ----
*** a/src/backend/commands/explain.c
--- b/src/backend/commands/explain.c
***************
*** 111,116 **** static void ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir,
--- 111,117 ----
  static void ExplainScanTarget(Scan *plan, ExplainState *es);
  static void ExplainModifyTarget(ModifyTable *plan, ExplainState *es);
  static void ExplainTargetRel(Plan *plan, Index rti, ExplainState *es);
+ static void ExplainTargetRels(Plan *plan, ExplainState *es);
  static void show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
  					  ExplainState *es);
  static void ExplainMemberNodes(List *plans, PlanState **planstates,
***************
*** 812,817 **** ExplainNode(PlanState *planstate, List *ancestors,
--- 813,819 ----
  	const char *strategy = NULL;
  	const char *partialmode = NULL;
  	const char *operation = NULL;
+ 	const char *foperation = NULL;
  	const char *custom_name = NULL;
  	int			save_indent = es->indent;
  	bool		haschildren;
***************
*** 909,941 **** ExplainNode(PlanState *planstate, List *ancestors,
  			switch (((ForeignScan *) plan)->operation)
  			{
  				case CMD_SELECT:
! 					pname = "Foreign Scan";
! 					operation = "Select";
  					break;
  				case CMD_INSERT:
! 					pname = "Foreign Insert";
! 					operation = "Insert";
  					break;
  				case CMD_UPDATE:
! 					pname = "Foreign Update";
! 					operation = "Update";
  					break;
  				case CMD_DELETE:
! 					pname = "Foreign Delete";
! 					operation = "Delete";
  					break;
  				default:
! 					pname = "???";
  					break;
  			}
  			break;
  		case T_CustomScan:
! 			sname = "Custom Scan";
  			custom_name = ((CustomScan *) plan)->methods->CustomName;
  			if (custom_name)
! 				pname = psprintf("Custom Scan (%s)", custom_name);
! 			else
! 				pname = sname;
  			break;
  		case T_Material:
  			pname = sname = "Materialize";
--- 911,945 ----
  			switch (((ForeignScan *) plan)->operation)
  			{
  				case CMD_SELECT:
! 					if (((Scan *) plan)->scanrelid > 0)
! 						pname = foperation = "Foreign Scan";
! 					else
! 					{
! 						if (((ForeignScan *) plan)->fs_relids)
! 							pname = foperation = "Foreign Join";
! 						else
! 							pname = foperation = "Foreign Scan";
! 					}
  					break;
  				case CMD_INSERT:
! 					pname = foperation = "Foreign Insert";
  					break;
  				case CMD_UPDATE:
! 					pname = foperation = "Foreign Update";
  					break;
  				case CMD_DELETE:
! 					pname = foperation = "Foreign Delete";
  					break;
  				default:
! 					pname = foperation = "???";
  					break;
  			}
  			break;
  		case T_CustomScan:
! 			pname = sname = "Custom Scan";
  			custom_name = ((CustomScan *) plan)->methods->CustomName;
  			if (custom_name)
! 				pname = psprintf("%s (%s)", pname, custom_name);
  			break;
  		case T_Material:
  			pname = sname = "Materialize";
***************
*** 1055,1060 **** ExplainNode(PlanState *planstate, List *ancestors,
--- 1059,1066 ----
  			ExplainPropertyText("Partial Mode", partialmode, es);
  		if (operation)
  			ExplainPropertyText("Operation", operation, es);
+ 		if (foperation)
+ 			ExplainPropertyText("Foreign Operation", foperation, es);
  		if (relationship)
  			ExplainPropertyText("Parent Relationship", relationship, es);
  		if (plan_name)
***************
*** 1075,1086 **** ExplainNode(PlanState *planstate, List *ancestors,
  		case T_ValuesScan:
  		case T_CteScan:
  		case T_WorkTableScan:
- 			ExplainScanTarget((Scan *) plan, es);
- 			break;
  		case T_ForeignScan:
  		case T_CustomScan:
! 			if (((Scan *) plan)->scanrelid > 0)
! 				ExplainScanTarget((Scan *) plan, es);
  			break;
  		case T_IndexScan:
  			{
--- 1081,1089 ----
  		case T_ValuesScan:
  		case T_CteScan:
  		case T_WorkTableScan:
  		case T_ForeignScan:
  		case T_CustomScan:
! 			ExplainScanTarget((Scan *) plan, es);
  			break;
  		case T_IndexScan:
  			{
***************
*** 2479,2485 **** ExplainIndexScanDetails(Oid indexid, ScanDirection indexorderdir,
  static void
  ExplainScanTarget(Scan *plan, ExplainState *es)
  {
! 	ExplainTargetRel((Plan *) plan, plan->scanrelid, es);
  }
  
  /*
--- 2482,2491 ----
  static void
  ExplainScanTarget(Scan *plan, ExplainState *es)
  {
! 	if (plan->scanrelid > 0)
! 		ExplainTargetRel((Plan *) plan, plan->scanrelid, es);
! 	else
! 		ExplainTargetRels((Plan *) plan, es);
  }
  
  /*
***************
*** 2604,2609 **** ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
--- 2610,2696 ----
  }
  
  /*
+  * Show the target relations of a ForeignScan or CustomScan node
+  *
+  * Note: we currently don't show anything if upper relation processing
+  */
+ static void
+ ExplainTargetRels(Plan *plan, ExplainState *es)
+ {
+ 	Bitmapset  *relids;
+ 	int			rti = -1;
+ 	bool		first = true;
+ 
+ 	/* Ignore if custom scan FIXME later */
+ 	if (IsA(plan, CustomScan))
+ 		return;
+ 
+ 	if (IsA(plan, ForeignScan))
+ 		relids = ((ForeignScan *) plan)->fs_relids;
+ 	else
+ 		elog(ERROR, "unexpected scan node: %d", (int) nodeTag(plan));
+ 
+ 	/* No work if upper relation processing */
+ 	if (!relids)
+ 		return;
+ 
+ 	ExplainOpenGroup("Target Tables", "Target Tables", false, es);
+ 
+ 	while ((rti = bms_next_member(relids, rti)) >= 0)
+ 	{
+ 		RangeTblEntry *rte;
+ 		char	   *objectname;
+ 		char	   *namespace = NULL;
+ 		char	   *refname;
+ 
+ 		Assert(rti > 0);
+ 		rte = rt_fetch(rti, es->rtable);
+ 		/* Assert it's on a real relation */
+ 		Assert(rte->rtekind == RTE_RELATION);
+ 		objectname = get_rel_name(rte->relid);
+ 		Assert(objectname != NULL);
+ 		if (es->verbose)
+ 			namespace = get_namespace_name(get_rel_namespace(rte->relid));
+ 		refname = (char *) list_nth(es->rtable_names, rti - 1);
+ 		Assert(refname != NULL);
+ 
+ 		/* Open a group for this target */
+ 		ExplainOpenGroup("Target Table", NULL, true, es);
+ 
+ 		if (es->format == EXPLAIN_FORMAT_TEXT)
+ 		{
+ 			if (first)
+ 				appendStringInfoString(es->str, " on");
+ 			else
+ 				appendStringInfoString(es->str, ",");
+ 			first = false;
+ 
+ 			if (namespace != NULL)
+ 				appendStringInfo(es->str, " %s.%s",
+ 								 quote_identifier(namespace),
+ 								 quote_identifier(objectname));
+ 			else
+ 				appendStringInfo(es->str, " %s",
+ 								 quote_identifier(objectname));
+ 			if (strcmp(refname, objectname) != 0)
+ 				appendStringInfo(es->str, " %s", quote_identifier(refname));
+ 		}
+ 		else
+ 		{
+ 			ExplainPropertyText("Relation Name", objectname, es);
+ 			if (namespace != NULL)
+ 				ExplainPropertyText("Schema", namespace, es);
+ 			ExplainPropertyText("Alias", refname, es);
+ 		}
+ 
+ 		/* Close the group */
+ 		ExplainCloseGroup("Target Table", NULL, true, es);
+ 	}
+ 
+ 	ExplainCloseGroup("Target Tables", "Target Tables", false, es);
+ }
+ 
+ /*
   * Show extra information for a ModifyTable node
   *
   * We have three objectives here.  First, if there's more than one target
