 src/backend/commands/explain.c          | 21 +++++++++++++++++++++
 src/backend/optimizer/plan/createplan.c | 18 +++++++++++++++++-
 src/include/nodes/execnodes.h           |  2 ++
 src/include/nodes/plannodes.h           |  1 +
 src/include/nodes/relation.h            |  4 +++-
 5 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index eeb8f19..ce42388 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -109,6 +109,8 @@ static void ExplainMemberNodes(List *plans, PlanState **planstates,
 				   List *ancestors, ExplainState *es);
 static void ExplainSubPlans(List *plans, List *ancestors,
 				const char *relationship, ExplainState *es);
+static void ExplainCustomChildren(CustomScanState *css,
+								  List *ancestors, ExplainState *es);
 static void ExplainProperty(const char *qlabel, const char *value,
 				bool numeric, ExplainState *es);
 static void ExplainOpenGroup(const char *objtype, const char *labelname,
@@ -1596,6 +1598,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		IsA(plan, BitmapAnd) ||
 		IsA(plan, BitmapOr) ||
 		IsA(plan, SubqueryScan) ||
+		(IsA(planstate, CustomScanState) &&
+		 ((CustomScanState *) planstate)->num_children > 0) ||
 		planstate->subPlan;
 	if (haschildren)
 	{
@@ -1650,6 +1654,10 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			ExplainNode(((SubqueryScanState *) planstate)->subplan, ancestors,
 						"Subquery", NULL, es);
 			break;
+		case T_CustomScan:
+			ExplainCustomChildren((CustomScanState *) planstate,
+								  ancestors, es);
+			break;
 		default:
 			break;
 	}
@@ -2521,6 +2529,19 @@ ExplainSubPlans(List *plans, List *ancestors,
 }
 
 /*
+ * Explain underlying child nodes of CustomScanState, if any
+ */
+static void
+ExplainCustomChildren(CustomScanState *css, List *ancestors, ExplainState *es)
+{
+	const char *label = (css->num_children > 1 ? "children" : "child");
+	int			i;
+
+	for (i=0; i < css->num_children; i++)
+		ExplainNode(css->custom_children[i], ancestors, label, NULL, es);
+}
+
+/*
  * Explain a property, such as sort keys or targets, that takes the form of
  * a list of unlabeled items.  "data" is a list of C strings.
  */
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index c809237..61d50c2 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2069,6 +2069,21 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
 {
 	CustomScan *cplan;
 	RelOptInfo *rel = best_path->path.parent;
+	List	   *custom_children = NIL;
+	ListCell   *lc;
+
+	/*
+	 * If CustomPath takes underlying child nodes, we recursively transform
+	 * these Path nodes to Plan node.
+	 * Custom-scan provider will attach these plans on lefttree, righttree
+	 * or custom_children list of CustomScan node.
+	 */
+	foreach (lc, best_path->custom_children)
+	{
+		Plan   *child = create_plan_recurse(root, (Path *) lfirst(lc));
+
+		custom_children = lappend(custom_children, child);
+	}
 
 	/*
 	 * Sort clauses into the best execution order, although custom-scan
@@ -2084,7 +2099,8 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
 															  rel,
 															  best_path,
 															  tlist,
-															  scan_clauses);
+															  scan_clauses,
+															  custom_children);
 	Assert(IsA(cplan, CustomScan));
 
 	/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 9de6d14..24377a1 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1561,6 +1561,8 @@ typedef struct CustomScanState
 {
 	ScanState	ss;
 	uint32		flags;			/* mask of CUSTOMPATH_* flags, see relation.h */
+	uint32		num_children;	/* length of child nodes array */
+	PlanState **custom_children;/* array of child PlanState, if any */
 	const CustomExecMethods *methods;
 } CustomScanState;
 
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 9313292..a928771 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -541,6 +541,7 @@ typedef struct CustomScan
 {
 	Scan		scan;
 	uint32		flags;			/* mask of CUSTOMPATH_* flags, see relation.h */
+	List	   *custom_children;/* list of Plan nodes, if any */
 	List	   *custom_exprs;	/* expressions that custom code may evaluate */
 	List	   *custom_private; /* private data for custom code */
 	List	   *custom_scan_tlist;		/* optional tlist describing scan
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index d3ee61c..b9bdeff 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -924,7 +924,8 @@ typedef struct CustomPathMethods
 												RelOptInfo *rel,
 												struct CustomPath *best_path,
 												List *tlist,
-												List *clauses);
+												List *clauses,
+												List *custom_children);
 	/* Optional: print additional fields besides "private" */
 	void		(*TextOutCustomPath) (StringInfo str,
 											  const struct CustomPath *node);
@@ -934,6 +935,7 @@ typedef struct CustomPath
 {
 	Path		path;
 	uint32		flags;			/* mask of CUSTOMPATH_* flags, see above */
+	List	   *custom_children;/* list of child Path nodes, if any */
 	List	   *custom_private;
 	const CustomPathMethods *methods;
 } CustomPath;
