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

Lines changed: 9 additions & 1 deletion
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

Lines changed: 22 additions & 0 deletions
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

Lines changed: 12 additions & 1 deletion
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 21 additions & 4 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 3 additions & 1 deletion
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy