*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***************
*** 843,883 **** deparse_type_name(Oid type_oid, int32 typemod)
  }
  
  /*
-  * Build the targetlist for given relation to be deparsed as SELECT clause.
-  *
-  * The output targetlist contains the columns that need to be fetched from the
-  * foreign server for the given relation.  If foreignrel is an upper relation,
-  * then the output targetlist can also contain expressions to be evaluated on
-  * foreign server.
-  */
- List *
- build_tlist_to_deparse(RelOptInfo *foreignrel)
- {
- 	List	   *tlist = NIL;
- 	PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
- 
- 	/*
- 	 * For an upper relation, we have already built the target list while
- 	 * checking shippability, so just return that.
- 	 */
- 	if (foreignrel->reloptkind == RELOPT_UPPER_REL)
- 		return fpinfo->grouped_tlist;
- 
- 	/*
- 	 * We require columns specified in foreignrel->reltarget->exprs and those
- 	 * required for evaluating the local conditions.
- 	 */
- 	tlist = add_to_flat_tlist(tlist,
- 					   pull_var_clause((Node *) foreignrel->reltarget->exprs,
- 									   PVC_RECURSE_PLACEHOLDERS));
- 	tlist = add_to_flat_tlist(tlist,
- 							  pull_var_clause((Node *) fpinfo->local_conds,
- 											  PVC_RECURSE_PLACEHOLDERS));
- 
- 	return tlist;
- }
- 
- /*
   * Deparse SELECT statement for given relation into buf.
   *
   * tlist contains the list of desired columns to be fetched from foreign server.
--- 843,848 ----
*** a/contrib/postgres_fdw/postgres_fdw.c
--- b/contrib/postgres_fdw/postgres_fdw.c
***************
*** 406,411 **** static void conversion_error_callback(void *arg);
--- 406,412 ----
  static bool foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel,
  				JoinType jointype, RelOptInfo *outerrel, RelOptInfo *innerrel,
  				JoinPathExtraData *extra);
+ static List *build_tlist_to_deparse(RelOptInfo *foreignrel);
  static bool foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel);
  static List *get_useful_pathkeys_for_relation(PlannerInfo *root,
  								 RelOptInfo *rel);
***************
*** 1190,1197 **** postgresGetForeignPlan(PlannerInfo *root,
  		remote_conds = fpinfo->remote_conds;
  		local_exprs = fpinfo->local_conds;
  
! 		/* Build the list of columns to be fetched from the foreign server. */
! 		fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
  
  		/*
  		 * Ensure that the outer plan produces a tuple whose descriptor
--- 1191,1209 ----
  		remote_conds = fpinfo->remote_conds;
  		local_exprs = fpinfo->local_conds;
  
! 		/* Get the list of columns to be fetched from the foreign server. */
! 		if ((fpinfo->use_remote_estimate &&
! 			 foreignrel->reloptkind == RELOPT_JOINREL) ||
! 			foreignrel->reloptkind == RELOPT_UPPER_REL)
! 		{
! 			/*
! 			 * We have already built the tlist for a join relation as well as
! 			 * for an upper relation.
! 			 */
! 			fdw_scan_tlist = fpinfo->tlist;
! 		}
! 		else
! 			fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
  
  		/*
  		 * Ensure that the outer plan produces a tuple whose descriptor
***************
*** 2528,2537 **** estimate_path_cost_size(PlannerInfo *root,
  		classifyConditions(root, foreignrel, param_join_conds,
  						   &remote_param_join_conds, &local_param_join_conds);
  
! 		/* Build the list of columns to be fetched from the foreign server. */
  		if (foreignrel->reloptkind == RELOPT_JOINREL ||
  			foreignrel->reloptkind == RELOPT_UPPER_REL)
! 			fdw_scan_tlist = build_tlist_to_deparse(foreignrel);
  		else
  			fdw_scan_tlist = NIL;
  
--- 2540,2555 ----
  		classifyConditions(root, foreignrel, param_join_conds,
  						   &remote_param_join_conds, &local_param_join_conds);
  
! 		/* Get the list of columns to be fetched from the foreign server. */
  		if (foreignrel->reloptkind == RELOPT_JOINREL ||
  			foreignrel->reloptkind == RELOPT_UPPER_REL)
! 		{
! 			/*
! 			 * We have already built the tlist for a join relation as well as
! 			 * for an upper relation.
! 			 */
! 			fdw_scan_tlist = fpinfo->tlist;
! 		}
  		else
  			fdw_scan_tlist = NIL;
  
***************
*** 2708,2714 **** estimate_path_cost_size(PlannerInfo *root,
  			MemSet(&aggcosts, 0, sizeof(AggClauseCosts));
  			if (root->parse->hasAggs)
  			{
! 				get_agg_clause_costs(root, (Node *) fpinfo->grouped_tlist,
  									 AGGSPLIT_SIMPLE, &aggcosts);
  				get_agg_clause_costs(root, (Node *) root->parse->havingQual,
  									 AGGSPLIT_SIMPLE, &aggcosts);
--- 2726,2732 ----
  			MemSet(&aggcosts, 0, sizeof(AggClauseCosts));
  			if (root->parse->hasAggs)
  			{
! 				get_agg_clause_costs(root, (Node *) fpinfo->tlist,
  									 AGGSPLIT_SIMPLE, &aggcosts);
  				get_agg_clause_costs(root, (Node *) root->parse->havingQual,
  									 AGGSPLIT_SIMPLE, &aggcosts);
***************
*** 2718,2724 **** estimate_path_cost_size(PlannerInfo *root,
  			numGroupCols = list_length(root->parse->groupClause);
  			numGroups = estimate_num_groups(root,
  							get_sortgrouplist_exprs(root->parse->groupClause,
! 													fpinfo->grouped_tlist),
  											input_rows, NULL);
  
  			/*
--- 2736,2742 ----
  			numGroupCols = list_length(root->parse->groupClause);
  			numGroups = estimate_num_groups(root,
  							get_sortgrouplist_exprs(root->parse->groupClause,
! 													fpinfo->tlist),
  											input_rows, NULL);
  
  			/*
***************
*** 4276,4281 **** foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
--- 4294,4325 ----
  	return true;
  }
  
+ /*
+  * Build the targetlist for given relation to be deparsed as SELECT clause.
+  *
+  * The output targetlist contains the columns that need to be fetched from the
+  * foreign server for the given relation.
+  */
+ static List *
+ build_tlist_to_deparse(RelOptInfo *foreignrel)
+ {
+ 	List	   *tlist = NIL;
+ 	PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) foreignrel->fdw_private;
+ 
+ 	/*
+ 	 * We require columns specified in foreignrel->reltarget->exprs and those
+ 	 * required for evaluating the local conditions.
+ 	 */
+ 	tlist = add_to_flat_tlist(tlist,
+ 					   pull_var_clause((Node *) foreignrel->reltarget->exprs,
+ 									   PVC_RECURSE_PLACEHOLDERS));
+ 	tlist = add_to_flat_tlist(tlist,
+ 							  pull_var_clause((Node *) fpinfo->local_conds,
+ 											  PVC_RECURSE_PLACEHOLDERS));
+ 
+ 	return tlist;
+ }
+ 
  static void
  add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
  								Path *epq_path)
***************
*** 4407,4412 **** postgresGetForeignJoinPaths(PlannerInfo *root,
--- 4451,4460 ----
  														0, fpinfo->jointype,
  														extra->sjinfo);
  
+ 	/* If we are going to estimate costs remotely, build the tlist here. */
+ 	if (fpinfo->use_remote_estimate)
+ 		fpinfo->tlist = build_tlist_to_deparse(joinrel);
+ 
  	/* Estimate costs for bare join relation */
  	estimate_path_cost_size(root, joinrel, NIL, NIL, &rows,
  							&width, &startup_cost, &total_cost);
***************
*** 4613,4619 **** foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
  	apply_pathtarget_labeling_to_tlist(tlist, grouping_target);
  
  	/* Store generated targetlist */
! 	fpinfo->grouped_tlist = tlist;
  
  	/* Safe to pushdown */
  	fpinfo->pushdown_safe = true;
--- 4661,4667 ----
  	apply_pathtarget_labeling_to_tlist(tlist, grouping_target);
  
  	/* Store generated targetlist */
! 	fpinfo->tlist = tlist;
  
  	/* Safe to pushdown */
  	fpinfo->pushdown_safe = true;
*** a/contrib/postgres_fdw/postgres_fdw.h
--- b/contrib/postgres_fdw/postgres_fdw.h
***************
*** 93,100 **** typedef struct PgFdwRelationInfo
  	JoinType	jointype;
  	List	   *joinclauses;
  
! 	/* Grouping information */
! 	List	   *grouped_tlist;
  } PgFdwRelationInfo;
  
  /* in postgres_fdw.c */
--- 93,103 ----
  	JoinType	jointype;
  	List	   *joinclauses;
  
! 	/*
! 	 * Optional tlist describing the contents of the scan tuple from the
! 	 * relation.
! 	 */
! 	List	   *tlist;
  } PgFdwRelationInfo;
  
  /* in postgres_fdw.c */
***************
*** 158,164 **** extern void deparseAnalyzeSql(StringInfo buf, Relation rel,
  				  List **retrieved_attrs);
  extern void deparseStringLiteral(StringInfo buf, const char *val);
  extern Expr *find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel);
- extern List *build_tlist_to_deparse(RelOptInfo *foreignrel);
  extern void deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root,
  						RelOptInfo *foreignrel, List *tlist,
  						List *remote_conds, List *pathkeys,
--- 161,166 ----
