Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5ca6118

Browse files
committed
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.
1 parent 4b8e24b commit 5ca6118

File tree

8 files changed

+77
-7
lines changed

8 files changed

+77
-7
lines changed

doc/src/sgml/custom-scan.sgml

+9-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef struct CustomPath
6060
{
6161
Path path;
6262
uint32 flags;
63+
List *custom_paths;
6364
List *custom_private;
6465
const CustomPathMethods *methods;
6566
} CustomPath;
@@ -73,6 +74,9 @@ typedef struct CustomPath
7374
<literal>CUSTOMPATH_SUPPORT_BACKWARD_SCAN</> if the custom path can support
7475
a backward scan and <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</> if it
7576
can support mark and restore. Both capabilities are optional.
77+
An optional <structfield>custom_paths</> is a list of <structname>Path</>
78+
nodes used by this custom-path node; these will be transformed into
79+
<structname>Plan</> nodes by planner.
7680
<structfield>custom_private</> can be used to store the custom path's
7781
private data. Private data should be stored in a form that can be handled
7882
by <literal>nodeToString</>, so that debugging routines that attempt to
@@ -112,7 +116,8 @@ Plan *(*PlanCustomPath) (PlannerInfo *root,
112116
RelOptInfo *rel,
113117
CustomPath *best_path,
114118
List *tlist,
115-
List *clauses);
119+
List *clauses,
120+
List *custom_plans);
116121
</programlisting>
117122
Convert a custom path to a finished plan. The return value will generally
118123
be a <literal>CustomScan</> object, which the callback must allocate and
@@ -145,6 +150,7 @@ typedef struct CustomScan
145150
{
146151
Scan scan;
147152
uint32 flags;
153+
List *custom_plans;
148154
List *custom_exprs;
149155
List *custom_private;
150156
List *custom_scan_tlist;
@@ -159,6 +165,8 @@ typedef struct CustomScan
159165
estimated costs, target lists, qualifications, and so on.
160166
<structfield>flags</> is a bitmask with the same meaning as in
161167
<structname>CustomPath</>.
168+
<structfield>custom_plans</> can be used to store child
169+
<structname>Plan</> nodes.
162170
<structfield>custom_exprs</> should be used to
163171
store expression trees that will need to be fixed up by
164172
<filename>setrefs.c</> and <filename>subselect.c</>, while

src/backend/commands/explain.c

+22
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ static void ExplainMemberNodes(List *plans, PlanState **planstates,
115115
List *ancestors, ExplainState *es);
116116
static void ExplainSubPlans(List *plans, List *ancestors,
117117
const char *relationship, ExplainState *es);
118+
static void ExplainCustomChildren(CustomScanState *css,
119+
List *ancestors, ExplainState *es);
118120
static void ExplainProperty(const char *qlabel, const char *value,
119121
bool numeric, ExplainState *es);
120122
static void ExplainOpenGroup(const char *objtype, const char *labelname,
@@ -1624,6 +1626,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
16241626
IsA(plan, BitmapAnd) ||
16251627
IsA(plan, BitmapOr) ||
16261628
IsA(plan, SubqueryScan) ||
1629+
(IsA(planstate, CustomScanState) &&
1630+
((CustomScanState *) planstate)->custom_ps != NIL) ||
16271631
planstate->subPlan;
16281632
if (haschildren)
16291633
{
@@ -1678,6 +1682,10 @@ ExplainNode(PlanState *planstate, List *ancestors,
16781682
ExplainNode(((SubqueryScanState *) planstate)->subplan, ancestors,
16791683
"Subquery", NULL, es);
16801684
break;
1685+
case T_CustomScan:
1686+
ExplainCustomChildren((CustomScanState *) planstate,
1687+
ancestors, es);
1688+
break;
16811689
default:
16821690
break;
16831691
}
@@ -2647,6 +2655,20 @@ ExplainSubPlans(List *plans, List *ancestors,
26472655
}
26482656
}
26492657

2658+
/*
2659+
* Explain a list of children of a CustomScan.
2660+
*/
2661+
static void
2662+
ExplainCustomChildren(CustomScanState *css, List *ancestors, ExplainState *es)
2663+
{
2664+
ListCell *cell;
2665+
const char *label =
2666+
(list_length(css->custom_ps) != 1 ? "children" : "child");
2667+
2668+
foreach (cell, css->custom_ps)
2669+
ExplainNode((PlanState *) lfirst(cell), ancestors, label, NULL, es);
2670+
}
2671+
26502672
/*
26512673
* Explain a property, such as sort keys or targets, that takes the form of
26522674
* a list of unlabeled items. "data" is a list of C strings.

src/backend/optimizer/plan/createplan.c

+12-1
Original file line numberDiff line numberDiff line change
@@ -2157,6 +2157,16 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
21572157
{
21582158
CustomScan *cplan;
21592159
RelOptInfo *rel = best_path->path.parent;
2160+
List *custom_plans = NIL;
2161+
ListCell *lc;
2162+
2163+
/* Recursively transform child paths. */
2164+
foreach (lc, best_path->custom_paths)
2165+
{
2166+
Plan *plan = create_plan_recurse(root, (Path *) lfirst(lc));
2167+
2168+
custom_plans = lappend(custom_plans, plan);
2169+
}
21602170

21612171
/*
21622172
* Sort clauses into the best execution order, although custom-scan
@@ -2172,7 +2182,8 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
21722182
rel,
21732183
best_path,
21742184
tlist,
2175-
scan_clauses);
2185+
scan_clauses,
2186+
custom_plans);
21762187
Assert(IsA(cplan, CustomScan));
21772188

21782189
/*

src/backend/optimizer/plan/setrefs.c

+8
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,8 @@ set_customscan_references(PlannerInfo *root,
11511151
CustomScan *cscan,
11521152
int rtoffset)
11531153
{
1154+
ListCell *lc;
1155+
11541156
/* Adjust scanrelid if it's valid */
11551157
if (cscan->scan.scanrelid > 0)
11561158
cscan->scan.scanrelid += rtoffset;
@@ -1194,6 +1196,12 @@ set_customscan_references(PlannerInfo *root,
11941196
fix_scan_list(root, cscan->custom_exprs, rtoffset);
11951197
}
11961198

1199+
/* Adjust child plan-nodes recursively, if needed */
1200+
foreach (lc, cscan->custom_plans)
1201+
{
1202+
lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1203+
}
1204+
11971205
/* Adjust custom_relids if needed */
11981206
if (rtoffset > 0)
11991207
{

src/backend/optimizer/plan/subselect.c

+21-4
Original file line numberDiff line numberDiff line change
@@ -2373,10 +2373,27 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
23732373
break;
23742374

23752375
case T_CustomScan:
2376-
finalize_primnode((Node *) ((CustomScan *) plan)->custom_exprs,
2377-
&context);
2378-
/* We assume custom_scan_tlist cannot contain Params */
2379-
context.paramids = bms_add_members(context.paramids, scan_params);
2376+
{
2377+
CustomScan *cscan = (CustomScan *) plan;
2378+
ListCell *lc;
2379+
2380+
finalize_primnode((Node *) cscan->custom_exprs,
2381+
&context);
2382+
/* We assume custom_scan_tlist cannot contain Params */
2383+
context.paramids =
2384+
bms_add_members(context.paramids, scan_params);
2385+
2386+
/* child nodes if any */
2387+
foreach (lc, cscan->custom_plans)
2388+
{
2389+
context.paramids =
2390+
bms_add_members(context.paramids,
2391+
finalize_plan(root,
2392+
(Plan *) lfirst(lc),
2393+
valid_params,
2394+
scan_params));
2395+
}
2396+
}
23802397
break;
23812398

23822399
case T_ModifyTable:

src/include/nodes/execnodes.h

+1
Original file line numberDiff line numberDiff line change
@@ -1616,6 +1616,7 @@ typedef struct CustomScanState
16161616
{
16171617
ScanState ss;
16181618
uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */
1619+
List *custom_ps; /* list of child PlanState nodes, if any */
16191620
const CustomExecMethods *methods;
16201621
} CustomScanState;
16211622

src/include/nodes/plannodes.h

+1
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ typedef struct CustomScan
550550
{
551551
Scan scan;
552552
uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */
553+
List *custom_plans; /* list of Plan nodes, if any */
553554
List *custom_exprs; /* expressions that custom code may evaluate */
554555
List *custom_private; /* private data for custom code */
555556
List *custom_scan_tlist; /* optional tlist describing scan

src/include/nodes/relation.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,8 @@ typedef struct CustomPathMethods
929929
RelOptInfo *rel,
930930
struct CustomPath *best_path,
931931
List *tlist,
932-
List *clauses);
932+
List *clauses,
933+
List *custom_plans);
933934
/* Optional: print additional fields besides "private" */
934935
void (*TextOutCustomPath) (StringInfo str,
935936
const struct CustomPath *node);
@@ -939,6 +940,7 @@ typedef struct CustomPath
939940
{
940941
Path path;
941942
uint32 flags; /* mask of CUSTOMPATH_* flags, see above */
943+
List *custom_paths; /* list of child Path nodes, if any */
942944
List *custom_private;
943945
const CustomPathMethods *methods;
944946
} CustomPath;

0 commit comments

Comments
 (0)