 src/backend/executor/nodeForeignscan.c  |  2 +-
 src/backend/foreign/foreign.c           | 50 +++++++++++++++++++++------------
 src/backend/nodes/copyfuncs.c           |  2 +-
 src/backend/nodes/outfuncs.c            |  2 +-
 src/backend/optimizer/plan/createplan.c |  2 +-
 src/backend/optimizer/util/plancat.c    |  4 +--
 src/backend/optimizer/util/relnode.c    | 12 ++++----
 src/include/foreign/fdwapi.h            |  3 +-
 src/include/nodes/plannodes.h           |  2 +-
 src/include/nodes/relation.h            |  4 +--
 10 files changed, 49 insertions(+), 34 deletions(-)

diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index fa553ac..17f7fb8 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -169,7 +169,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 	/*
 	 * Acquire function pointers from the FDW's handler, and init fdw_state.
 	 */
-	fdwroutine = GetFdwRoutine(node->fdw_handler);
+	fdwroutine = GetFdwRoutineByServer(node->fdw_server);
 	scanstate->fdwroutine = fdwroutine;
 	scanstate->fdw_state = NULL;
 
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index cdbd550..ea293ca 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -281,6 +281,27 @@ GetForeignColumnOptions(Oid relid, AttrNumber attnum)
 	return options;
 }
 
+/*
+ * GetFdwRoutineByRelId - looks up Oid of the foreign server for the
+ * given foreign table.
+ */
+Oid
+GetFdwServerByRelId(Oid relid)
+{
+	HeapTuple	tp;
+	Form_pg_foreign_table tableform;
+	Oid			serverid;
+
+	/* Get server OID for the foreign table. */
+	tp = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
+	if (!HeapTupleIsValid(tp))
+		elog(ERROR, "cache lookup failed for foreign table %u", relid);
+	tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
+	serverid = tableform->ftserver;
+	ReleaseSysCache(tp);
+
+	return serverid;
+}
 
 /*
  * GetFdwRoutine - call the specified foreign-data wrapper handler routine
@@ -302,30 +323,19 @@ GetFdwRoutine(Oid fdwhandler)
 	return routine;
 }
 
-
 /*
- * GetFdwHandlerByRelId - look up the handler of the foreign-data wrapper
- * for the given foreign table
+ * GetFdwRoutineByServer - look up the handler of the foreign-data wrapper
+ * for the given foreign server, and retrieve its FdwRoutine struct.
  */
-Oid
-GetFdwHandlerByRelId(Oid relid)
+FdwRoutine *
+GetFdwRoutineByServer(Oid serverid)
 {
 	HeapTuple	tp;
 	Form_pg_foreign_data_wrapper fdwform;
 	Form_pg_foreign_server serverform;
-	Form_pg_foreign_table tableform;
-	Oid			serverid;
 	Oid			fdwid;
 	Oid			fdwhandler;
 
-	/* Get server OID for the foreign table. */
-	tp = SearchSysCache1(FOREIGNTABLEREL, ObjectIdGetDatum(relid));
-	if (!HeapTupleIsValid(tp))
-		elog(ERROR, "cache lookup failed for foreign table %u", relid);
-	tableform = (Form_pg_foreign_table) GETSTRUCT(tp);
-	serverid = tableform->ftserver;
-	ReleaseSysCache(tp);
-
 	/* Get foreign-data wrapper OID for the server. */
 	tp = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(serverid));
 	if (!HeapTupleIsValid(tp))
@@ -350,7 +360,8 @@ GetFdwHandlerByRelId(Oid relid)
 
 	ReleaseSysCache(tp);
 
-	return fdwhandler;
+	/* And finally, call the handler function. */
+	return GetFdwRoutine(fdwhandler);
 }
 
 /*
@@ -360,9 +371,12 @@ GetFdwHandlerByRelId(Oid relid)
 FdwRoutine *
 GetFdwRoutineByRelId(Oid relid)
 {
-	Oid			fdwhandler = GetFdwHandlerByRelId(relid);
+	Oid			serverid;
 
-	return GetFdwRoutine(fdwhandler);
+	/* Get server OID for the foreign table. */
+	serverid = GetFdwServerByRelId(relid);
+	/* Then retrieve its FdwRoutine struct */
+	return GetFdwRoutineByServer(serverid);
 }
 
 /*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 805045d..aa05590 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -592,7 +592,7 @@ _copyForeignScan(const ForeignScan *from)
 	/*
 	 * copy remainder of node
 	 */
-	COPY_SCALAR_FIELD(fdw_handler);
+	COPY_SCALAR_FIELD(fdw_server);
 	COPY_NODE_FIELD(fdw_exprs);
 	COPY_NODE_FIELD(fdw_ps_tlist);
 	COPY_NODE_FIELD(fdw_private);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index f9f948e..5a94c5e 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -558,7 +558,7 @@ _outForeignScan(StringInfo str, const ForeignScan *node)
 
 	_outScanInfo(str, (const Scan *) node);
 
-	WRITE_OID_FIELD(fdw_handler);
+	WRITE_OID_FIELD(fdw_server);
 	WRITE_NODE_FIELD(fdw_exprs);
 	WRITE_NODE_FIELD(fdw_ps_tlist);
 	WRITE_NODE_FIELD(fdw_private);
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index eeb2a41..a3f23ad 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2024,7 +2024,7 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
 	copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
 
 	/* Track FDW server-id; no need to make FDW do this */
-	scan_plan->fdw_handler = rel->fdw_handler;
+	scan_plan->fdw_server = rel->fdw_server;
 
 	/*
 	 * Replace any outer-relation variables with nestloop params in the qual
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 068ab39..d81736c 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -380,12 +380,12 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 	/* Grab the fdwroutine info using the relcache, while we have it */
 	if (relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
 	{
-		rel->fdw_handler = GetFdwHandlerByRelId(RelationGetRelid(relation));
+		rel->fdw_server = GetFdwServerByRelId(RelationGetRelid(relation));
 		rel->fdwroutine = GetFdwRoutineForRelation(relation, true);
 	}
 	else
 	{
-		rel->fdw_handler = InvalidOid;
+		rel->fdw_server = InvalidOid;
 		rel->fdwroutine = NULL;
 	}
 	heap_close(relation, NoLock);
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 5623566..e6a5349 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -123,7 +123,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
 	rel->subroot = NULL;
 	rel->subplan_params = NIL;
 	rel->fdwroutine = NULL;
-	rel->fdw_handler = InvalidOid;
+	rel->fdw_server = InvalidOid;
 	rel->fdw_private = NULL;
 	rel->baserestrictinfo = NIL;
 	rel->baserestrictcost.startup = 0;
@@ -432,12 +432,12 @@ build_join_rel(PlannerInfo *root,
 	 * Set FDW handler and routine if both outer and inner relation
 	 * are managed by same FDW driver.
 	 */
-	if (OidIsValid(outer_rel->fdw_handler) &&
-		OidIsValid(inner_rel->fdw_handler) &&
-		outer_rel->fdw_handler == inner_rel->fdw_handler)
+	if (OidIsValid(outer_rel->fdw_server) &&
+		OidIsValid(inner_rel->fdw_server) &&
+		outer_rel->fdw_server == inner_rel->fdw_server)
 	{
-		joinrel->fdw_handler = outer_rel->fdw_handler;
-		joinrel->fdwroutine = GetFdwRoutine(joinrel->fdw_handler);
+		joinrel->fdw_server = outer_rel->fdw_server;
+		joinrel->fdwroutine = GetFdwRoutineByServer(joinrel->fdw_server);
 	}
 
 	/*
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
index c683d92..ff91d0f 100644
--- a/src/include/foreign/fdwapi.h
+++ b/src/include/foreign/fdwapi.h
@@ -168,8 +168,9 @@ typedef struct FdwRoutine
 
 
 /* Functions in foreign/foreign.c */
-extern Oid GetFdwHandlerByRelId(Oid relid);
+extern Oid GetFdwServerByRelId(Oid relid);
 extern FdwRoutine *GetFdwRoutine(Oid fdwhandler);
+extern FdwRoutine *GetFdwRoutineByServer(Oid server_id);
 extern FdwRoutine *GetFdwRoutineByRelId(Oid relid);
 extern FdwRoutine *GetFdwRoutineForRelation(Relation relation, bool makecopy);
 extern bool IsImportableForeignTable(const char *tablename,
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index baeba2d..bd23d24 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -484,7 +484,7 @@ typedef struct WorkTableScan
 typedef struct ForeignScan
 {
 	Scan		scan;
-	Oid			fdw_handler;	/* OID of FDW handler */
+	Oid			fdw_server;		/* OID of FDW server */
 	List	   *fdw_exprs;		/* expressions that FDW may evaluate */
 	List	   *fdw_ps_tlist;	/* tlist, if replacing a join */
 	List	   *fdw_private;	/* private data for FDW */
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 1713d29..e0ca04f 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -366,7 +366,7 @@ typedef struct PlannerInfo
  *		subroot - PlannerInfo for subquery (NULL if it's not a subquery)
  *		subplan_params - list of PlannerParamItems to be passed to subquery
  *		fdwroutine - function hooks for FDW, if foreign table (else NULL)
- *		fdw_handler - OID of FDW handler, if foreign table (else InvalidOid)
+ *		fdw_server - OID of FDW server, if foreign table (else InvalidOid)
  *		fdw_private - private state for FDW, if foreign table (else NULL)
  *
  *		Note: for a subquery, tuples, subplan, subroot are not set immediately
@@ -462,7 +462,7 @@ typedef struct RelOptInfo
 	List	   *subplan_params; /* if subquery */
 	/* use "struct FdwRoutine" to avoid including fdwapi.h here */
 	struct FdwRoutine *fdwroutine;		/* if foreign table */
-	Oid			fdw_handler;	/* if foreign table */
+	Oid			fdw_server;		/* if foreign table */
 	void	   *fdw_private;	/* if foreign table */
 
 	/* used by various scans and joins: */
