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;