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

Commit 5864d6a

Browse files
committed
Provide a planner hook at a suitable place for creating upper-rel Paths.
In the initial revision of the upper-planner pathification work, the only available way for an FDW or custom-scan provider to inject Paths representing post-scan-join processing was to insert them during scan-level GetForeignPaths or similar processing. While that's not impossible, it'd require quite a lot of duplicative processing to look forward and see if the extension would be capable of implementing the whole query. To improve matters for custom-scan providers, provide a hook function at the point where the core code is about to start filling in upperrel Paths. At this point Paths are available for the whole scan/join tree, which should reduce the amount of redundant effort considerably. (An alternative design that was suggested was to provide a separate hook for each post-scan-join processing step, but that seems messy and not clearly more useful.) Following our time-honored tradition, there's no documentation for this hook outside the source code. As-is, this hook is only meant for custom scan providers, which we can't assume very much about. A followon patch will implement an FDW callback to let FDWs do the same thing in a somewhat more structured fashion.
1 parent 28048cb commit 5864d6a

File tree

4 files changed

+35
-0
lines changed

4 files changed

+35
-0
lines changed

src/backend/optimizer/plan/planner.c

+26
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ int force_parallel_mode = FORCE_PARALLEL_OFF;
6262
/* Hook for plugins to get control in planner() */
6363
planner_hook_type planner_hook = NULL;
6464

65+
/* Hook for plugins to get control before grouping_planner plans upper rels */
66+
create_upper_paths_hook_type create_upper_paths_hook = NULL;
67+
6568

6669
/* Expression kind codes for preprocess_expression */
6770
#define EXPRKIND_QUAL 0
@@ -459,6 +462,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
459462
root->append_rel_list = NIL;
460463
root->rowMarks = NIL;
461464
memset(root->upper_rels, 0, sizeof(root->upper_rels));
465+
memset(root->upper_targets, 0, sizeof(root->upper_targets));
462466
root->processed_tlist = NIL;
463467
root->grouping_map = NULL;
464468
root->minmax_aggs = NIL;
@@ -1736,6 +1740,28 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
17361740
}
17371741
}
17381742

1743+
/*
1744+
* Save the various upper-rel PathTargets we just computed into
1745+
* root->upper_targets[]. The core code doesn't use this, but it
1746+
* provides a convenient place for extensions to get at the info. For
1747+
* consistency, we save all the intermediate targets, even though some
1748+
* of the corresponding upperrels might not be needed for this query.
1749+
*/
1750+
root->upper_targets[UPPERREL_FINAL] = final_target;
1751+
root->upper_targets[UPPERREL_WINDOW] = sort_input_target;
1752+
root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target;
1753+
1754+
/*
1755+
* Let extensions, particularly CustomScan providers, consider
1756+
* injecting extension Paths into the query's upperrels, where they
1757+
* will compete with the Paths we create below. We pass the final
1758+
* scan/join rel because that's not so easily findable from the
1759+
* PlannerInfo struct; anything else the hook wants to know should be
1760+
* obtainable via "root".
1761+
*/
1762+
if (create_upper_paths_hook)
1763+
(*create_upper_paths_hook) (root, current_rel);
1764+
17391765
/*
17401766
* If we have grouping and/or aggregation, consider ways to implement
17411767
* that. We build a new upperrel representing the output of this

src/backend/optimizer/prep/prepjointree.c

+1
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
909909
subroot->append_rel_list = NIL;
910910
subroot->rowMarks = NIL;
911911
memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
912+
memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
912913
subroot->processed_tlist = NIL;
913914
subroot->grouping_map = NULL;
914915
subroot->minmax_aggs = NIL;

src/include/nodes/relation.h

+3
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ typedef struct PlannerInfo
263263
/* Use fetch_upper_rel() to get any particular upper rel */
264264
List *upper_rels[UPPERREL_FINAL + 1]; /* upper-rel RelOptInfos */
265265

266+
/* Result tlists chosen by grouping_planner for upper-stage processing */
267+
struct PathTarget *upper_targets[UPPERREL_FINAL + 1];
268+
266269
/*
267270
* grouping_planner passes back its final processed targetlist here, for
268271
* use in relabeling the topmost tlist of the finished Plan.

src/include/optimizer/planner.h

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ typedef PlannedStmt *(*planner_hook_type) (Query *parse,
2424
ParamListInfo boundParams);
2525
extern PGDLLIMPORT planner_hook_type planner_hook;
2626

27+
/* Hook for plugins to get control before grouping_planner plans upper rels */
28+
typedef void (*create_upper_paths_hook_type) (PlannerInfo *root,
29+
RelOptInfo *scan_join_rel);
30+
extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;
31+
2732

2833
extern PlannedStmt *planner(Query *parse, int cursorOptions,
2934
ParamListInfo boundParams);

0 commit comments

Comments
 (0)