mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -2647,6 +2655,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.
|
||||
|
@@ -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));
|
||||
|
||||
/*
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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:
|
||||
|
Reference in New Issue
Block a user