 doc/src/sgml/custom-scan.sgml         | 12 ++------
 doc/src/sgml/fdwhandler.sgml          | 11 +-------
 src/backend/optimizer/path/joinpath.c | 52 +++++++++++++++++++++++------------
 src/include/foreign/fdwapi.h          | 12 ++------
 src/include/optimizer/paths.h         | 33 ++++++++++++++--------
 5 files changed, 61 insertions(+), 59 deletions(-)

diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml
index 9fd1db6..9c14d87 100644
--- a/doc/src/sgml/custom-scan.sgml
+++ b/doc/src/sgml/custom-scan.sgml
@@ -89,16 +89,8 @@ typedef struct CustomPath
    different combinations of inner and outer relations; it is the
    responsibility of the hook to minimize duplicated work.
 <programlisting>
-typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
-                                             RelOptInfo *joinrel,
-                                             RelOptInfo *outerrel,
-                                             RelOptInfo *innerrel,
-                                             List *restrictlist,
-                                             JoinType jointype,
-                                             SpecialJoinInfo *sjinfo,
-                                             SemiAntiJoinFactors *semifactors,
-                                             Relids param_source_rels,
-                                             Relids extra_lateral_rels);
+typedef void (*set_join_pathlist_hook_type) (ExtraJoinPathArgs *jargs);
+
 extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
 </programlisting>
   </para>
diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml
index 04f3c22..eb49eaa 100644
--- a/doc/src/sgml/fdwhandler.sgml
+++ b/doc/src/sgml/fdwhandler.sgml
@@ -603,16 +603,7 @@ IsForeignRelUpdatable (Relation rel);
     <para>
 <programlisting>
 void
-GetForeignJoinPaths(PlannerInfo *root,
-                    RelOptInfo *joinrel,
-                    RelOptInfo *outerrel,
-                    RelOptInfo *innerrel,
-                    List *restrictlist,
-                    JoinType jointype,
-                    SpecialJoinInfo *sjinfo,
-                    SemiAntiJoinFactors *semifactors,
-                    Relids param_source_rels,
-                    Relids extra_lateral_rels);
+GetForeignJoinPaths(ExtraJoinPathArgs *jargs);
 </programlisting>
      Create possible access paths for a join of two foreign tables managed
      by the same foreign data wrapper.
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index dabef3c..54a238f 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -265,25 +265,41 @@ add_paths_to_joinrel(PlannerInfo *root,
 							 param_source_rels, extra_lateral_rels);
 
 	/*
-	 * 5. If both inner and outer relations are managed by the same FDW,
-	 * give it a chance to push down joins.
+	 * If we may consider the last two cases, join paths provided by
+	 * extensions, ExtraJoinPathArgs will pack all the arguments to
+	 * be informed, for simplification and stability of the interface.
 	 */
-	if (joinrel->fdwroutine &&
-		joinrel->fdwroutine->GetForeignJoinPaths)
-		joinrel->fdwroutine->GetForeignJoinPaths(root, joinrel,
-												 outerrel, innerrel,
-												 restrictlist, jointype, sjinfo,
-												 &semifactors,
-												 param_source_rels,
-												 extra_lateral_rels);
-	/*
-	 * 6. Finally, give extensions a chance to manipulate the path list.
-	 */
-	if (set_join_pathlist_hook)
-		set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
-							   restrictlist, jointype,
-							   sjinfo, &semifactors,
-							   param_source_rels, extra_lateral_rels);
+	if ((joinrel->fdwroutine &&
+		 joinrel->fdwroutine->GetForeignJoinPaths) ||
+		set_join_pathlist_hook)
+	{
+		ExtraJoinPathArgs	jargs;
+
+		jargs.root = root;
+		jargs.joinrel = joinrel;
+		jargs.outerrel = outerrel;
+		jargs.innerrel = innerrel;
+		jargs.restrictlist = restrictlist;
+		jargs.jointype = jointype;
+		jargs.sjinfo = sjinfo;
+		jargs.semifactors = &semifactors;
+		jargs.param_source_rels = param_source_rels;
+		jargs.extra_lateral_rels = extra_lateral_rels;
+
+		/*
+		 * 5. If both inner and outer relations are managed by the same
+		 * foreign server, give it a chance to push down joins.
+		 */
+		if (joinrel->fdwroutine &&
+			joinrel->fdwroutine->GetForeignJoinPaths)
+			joinrel->fdwroutine->GetForeignJoinPaths(&jargs);
+
+		/*
+		 * 6. Finally, give extensions a chance to manipulate the path list.
+		 */
+		if (set_join_pathlist_hook)
+			set_join_pathlist_hook(&jargs);
+	}
 }
 
 /*
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
index c683d92..c674f8f 100644
--- a/src/include/foreign/fdwapi.h
+++ b/src/include/foreign/fdwapi.h
@@ -14,6 +14,7 @@
 
 #include "nodes/execnodes.h"
 #include "nodes/relation.h"
+#include "optimizer/paths.h"
 
 /* To avoid including explain.h here, reference ExplainState thus: */
 struct ExplainState;
@@ -82,16 +83,7 @@ typedef void (*EndForeignModify_function) (EState *estate,
 
 typedef int (*IsForeignRelUpdatable_function) (Relation rel);
 
-typedef void (*GetForeignJoinPaths_function) (PlannerInfo *root,
-											  RelOptInfo *joinrel,
-											  RelOptInfo *outerrel,
-											  RelOptInfo *innerrel,
-											  List *restrictlist,
-											  JoinType jointype,
-											  SpecialJoinInfo *sjinfo,
-											  SemiAntiJoinFactors *semifactors,
-											  Relids param_source_rels,
-											  Relids extra_lateral_rels);
+typedef void (*GetForeignJoinPaths_function) (ExtraJoinPathArgs *jargs);
 
 typedef void (*ExplainForeignScan_function) (ForeignScanState *node,
 													struct ExplainState *es);
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index c42c69d..10bace7 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -30,17 +30,28 @@ typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
 														RangeTblEntry *rte);
 extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
 
-/* Hook for plugins to get control in add_paths_to_joinrel() */
-typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
-											 RelOptInfo *joinrel,
-											 RelOptInfo *outerrel,
-											 RelOptInfo *innerrel,
-											 List *restrictlist,
-											 JoinType jointype,
-											 SpecialJoinInfo *sjinfo,
-											 SemiAntiJoinFactors *semifactors,
-											 Relids param_source_rels,
-											 Relids extra_lateral_rels);
+/*
+ * Hook for plugins to get control in add_paths_to_joinrel()
+ *
+ * ExtraJoinPathArgs packs all the information to construct extra paths
+ * by extensions. Its definition may be adjusted in the future version.
+ */
+typedef struct
+{
+	PlannerInfo	   *root;
+	RelOptInfo	   *joinrel;
+	RelOptInfo	   *outerrel;
+	RelOptInfo	   *innerrel;
+	List		   *restrictlist;
+	JoinType		jointype;
+	SpecialJoinInfo *sjinfo;
+	SemiAntiJoinFactors *semifactors;
+	Relids			param_source_rels;
+	Relids			extra_lateral_rels;
+} ExtraJoinPathArgs;
+
+typedef void (*set_join_pathlist_hook_type) (ExtraJoinPathArgs *jargs);
+
 extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
 
 /* Hook for plugins to replace standard_join_search() */
