diff options
author | Robert Haas <rhaas@postgresql.org> | 2015-06-26 09:40:47 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2015-06-26 09:40:47 -0400 |
commit | 5ca611841bcd37c7ee8448c46c8398ef8d8edcc4 (patch) | |
tree | 492d1f96b9f0b3a25e321f6d58cba98b0a95bfd2 /src | |
parent | 4b8e24b9ad308c30dbe2184e06848e638e018114 (diff) | |
download | postgresql-5ca611841bcd37c7ee8448c46c8398ef8d8edcc4.tar.gz postgresql-5ca611841bcd37c7ee8448c46c8398ef8d8edcc4.zip |
Improve handling of CustomPath/CustomPlan(State) children.
Allow CustomPath to have a list of paths, CustomPlan a list of plans,
and CustomPlanState a list of planstates known to the core system, so
that custom path/plan providers can more reasonably use this
infrastructure for nodes with multiple children.
KaiGai Kohei, per a design suggestion from Tom Lane, with some
further kibitzing by me.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/explain.c | 22 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 13 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 8 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 25 | ||||
-rw-r--r-- | src/include/nodes/execnodes.h | 1 | ||||
-rw-r--r-- | src/include/nodes/plannodes.h | 1 | ||||
-rw-r--r-- | src/include/nodes/relation.h | 4 |
7 files changed, 68 insertions, 6 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index a82c6ff7b4d..0d1ecc2a3ed 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -115,6 +115,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, @@ -1624,6 +1626,8 @@ ExplainNode(PlanState *planstate, List *ancestors, IsA(plan, BitmapAnd) || IsA(plan, BitmapOr) || IsA(plan, SubqueryScan) || + (IsA(planstate, CustomScanState) && + ((CustomScanState *) planstate)->custom_ps != NIL) || planstate->subPlan; if (haschildren) { @@ -1678,6 +1682,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; } @@ -2648,6 +2656,20 @@ ExplainSubPlans(List *plans, List *ancestors, } /* + * Explain a list of children of a CustomScan. + */ +static void +ExplainCustomChildren(CustomScanState *css, List *ancestors, ExplainState *es) +{ + ListCell *cell; + const char *label = + (list_length(css->custom_ps) != 1 ? "children" : "child"); + + foreach (cell, css->custom_ps) + ExplainNode((PlanState *) lfirst(cell), 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 a3482def643..dc2dcbf93f7 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -2157,6 +2157,16 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path, { CustomScan *cplan; RelOptInfo *rel = best_path->path.parent; + List *custom_plans = NIL; + ListCell *lc; + + /* Recursively transform child paths. */ + foreach (lc, best_path->custom_paths) + { + Plan *plan = create_plan_recurse(root, (Path *) lfirst(lc)); + + custom_plans = lappend(custom_plans, plan); + } /* * Sort clauses into the best execution order, although custom-scan @@ -2172,7 +2182,8 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path, rel, best_path, tlist, - scan_clauses); + scan_clauses, + custom_plans); Assert(IsA(cplan, CustomScan)); /* diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index a7f65dd529f..c0641a7cfb0 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -1151,6 +1151,8 @@ set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset) { + ListCell *lc; + /* Adjust scanrelid if it's valid */ if (cscan->scan.scanrelid > 0) cscan->scan.scanrelid += rtoffset; @@ -1194,6 +1196,12 @@ set_customscan_references(PlannerInfo *root, fix_scan_list(root, cscan->custom_exprs, rtoffset); } + /* Adjust child plan-nodes recursively, if needed */ + foreach (lc, cscan->custom_plans) + { + lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset); + } + /* Adjust custom_relids if needed */ if (rtoffset > 0) { diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index f80abb494c7..4708b87f330 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -2373,10 +2373,27 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, break; case T_CustomScan: - finalize_primnode((Node *) ((CustomScan *) plan)->custom_exprs, - &context); - /* We assume custom_scan_tlist cannot contain Params */ - context.paramids = bms_add_members(context.paramids, scan_params); + { + CustomScan *cscan = (CustomScan *) plan; + ListCell *lc; + + finalize_primnode((Node *) cscan->custom_exprs, + &context); + /* We assume custom_scan_tlist cannot contain Params */ + context.paramids = + bms_add_members(context.paramids, scan_params); + + /* child nodes if any */ + foreach (lc, cscan->custom_plans) + { + context.paramids = + bms_add_members(context.paramids, + finalize_plan(root, + (Plan *) lfirst(lc), + valid_params, + scan_params)); + } + } break; case T_ModifyTable: diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index db5bd7faf04..541ee187356 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1616,6 +1616,7 @@ typedef struct CustomScanState { ScanState ss; uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */ + List *custom_ps; /* list of child PlanState nodes, if any */ const CustomExecMethods *methods; } CustomScanState; diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index d967219c0b5..5f538f3e8cc 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -550,6 +550,7 @@ typedef struct CustomScan { Scan scan; uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */ + List *custom_plans; /* 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 33b08745702..cb916ea8e14 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -929,7 +929,8 @@ typedef struct CustomPathMethods RelOptInfo *rel, struct CustomPath *best_path, List *tlist, - List *clauses); + List *clauses, + List *custom_plans); /* Optional: print additional fields besides "private" */ void (*TextOutCustomPath) (StringInfo str, const struct CustomPath *node); @@ -939,6 +940,7 @@ typedef struct CustomPath { Path path; uint32 flags; /* mask of CUSTOMPATH_* flags, see above */ + List *custom_paths; /* list of child Path nodes, if any */ List *custom_private; const CustomPathMethods *methods; } CustomPath; |