Redefine create_upper_paths_hook as being invoked once per upper relation.

Per discussion, this gives potential users of the hook more flexibility,
because they can build custom Paths that implement only one stage of
upper processing atop core-provided Paths for earlier stages.
This commit is contained in:
Tom Lane 2016-04-12 15:23:14 -04:00
parent 7a5f8b5c59
commit f1f01de145
3 changed files with 45 additions and 13 deletions

View File

@ -62,7 +62,7 @@ int force_parallel_mode = FORCE_PARALLEL_OFF;
/* Hook for plugins to get control in planner() */ /* Hook for plugins to get control in planner() */
planner_hook_type planner_hook = NULL; planner_hook_type planner_hook = NULL;
/* Hook for plugins to get control before grouping_planner plans upper rels */ /* Hook for plugins to get control when grouping_planner() plans upper rels */
create_upper_paths_hook_type create_upper_paths_hook = NULL; create_upper_paths_hook_type create_upper_paths_hook = NULL;
@ -1772,20 +1772,20 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target; root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target;
/* /*
* Let extensions, particularly FDWs and CustomScan providers, * If there is an FDW that's responsible for the final scan/join rel,
* consider injecting extension Paths into the query's upperrels, * let it consider injecting extension Paths into the query's
* where they will compete with the Paths we create below. We pass * upperrels, where they will compete with the Paths we create below.
* the final scan/join rel because that's not so easily findable from * We pass the final scan/join rel because that's not so easily
* the PlannerInfo struct; anything else the hooks want to know should * findable from the PlannerInfo struct; anything else the FDW wants
* be obtainable via "root". * to know should be obtainable via "root".
*
* Note: CustomScan providers, as well as FDWs that don't want to
* use this hook, can use the create_upper_paths_hook; see below.
*/ */
if (current_rel->fdwroutine && if (current_rel->fdwroutine &&
current_rel->fdwroutine->GetForeignUpperPaths) current_rel->fdwroutine->GetForeignUpperPaths)
current_rel->fdwroutine->GetForeignUpperPaths(root, current_rel); current_rel->fdwroutine->GetForeignUpperPaths(root, current_rel);
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, current_rel);
/* /*
* If we have grouping and/or aggregation, consider ways to implement * If we have grouping and/or aggregation, consider ways to implement
* that. We build a new upperrel representing the output of this * that. We build a new upperrel representing the output of this
@ -1962,6 +1962,11 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
add_path(final_rel, path); add_path(final_rel, path);
} }
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_FINAL,
current_rel, final_rel);
/* Note: currently, we leave it to callers to do set_cheapest() */ /* Note: currently, we leave it to callers to do set_cheapest() */
} }
@ -3724,6 +3729,11 @@ create_grouping_paths(PlannerInfo *root,
errmsg("could not implement GROUP BY"), errmsg("could not implement GROUP BY"),
errdetail("Some of the datatypes only support hashing, while others only support sorting."))); errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_GROUP_AGG,
input_rel, grouped_rel);
/* Now choose the best path(s) */ /* Now choose the best path(s) */
set_cheapest(grouped_rel); set_cheapest(grouped_rel);
@ -3780,6 +3790,11 @@ create_window_paths(PlannerInfo *root,
activeWindows); activeWindows);
} }
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_WINDOW,
input_rel, window_rel);
/* Now choose the best path(s) */ /* Now choose the best path(s) */
set_cheapest(window_rel); set_cheapest(window_rel);
@ -4056,6 +4071,11 @@ create_distinct_paths(PlannerInfo *root,
errmsg("could not implement DISTINCT"), errmsg("could not implement DISTINCT"),
errdetail("Some of the datatypes only support hashing, while others only support sorting."))); errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_DISTINCT,
input_rel, distinct_rel);
/* Now choose the best path(s) */ /* Now choose the best path(s) */
set_cheapest(distinct_rel); set_cheapest(distinct_rel);
@ -4117,6 +4137,11 @@ create_ordered_paths(PlannerInfo *root,
} }
} }
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_ORDERED,
input_rel, ordered_rel);
/* /*
* No need to bother with set_cheapest here; grouping_planner does not * No need to bother with set_cheapest here; grouping_planner does not
* need us to do it. * need us to do it.

View File

@ -206,7 +206,12 @@ plan_set_operations(PlannerInfo *root)
/* Add only the final path to the SETOP upperrel. */ /* Add only the final path to the SETOP upperrel. */
add_path(setop_rel, path); add_path(setop_rel, path);
/* Select cheapest path (pretty easy at the moment) */ /* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_SETOP,
NULL, setop_rel);
/* Select cheapest path */
set_cheapest(setop_rel); set_cheapest(setop_rel);
return setop_rel; return setop_rel;

View File

@ -24,9 +24,11 @@ typedef PlannedStmt *(*planner_hook_type) (Query *parse,
ParamListInfo boundParams); ParamListInfo boundParams);
extern PGDLLIMPORT planner_hook_type planner_hook; extern PGDLLIMPORT planner_hook_type planner_hook;
/* Hook for plugins to get control before grouping_planner plans upper rels */ /* Hook for plugins to get control when grouping_planner() plans upper rels */
typedef void (*create_upper_paths_hook_type) (PlannerInfo *root, typedef void (*create_upper_paths_hook_type) (PlannerInfo *root,
RelOptInfo *scan_join_rel); UpperRelationKind stage,
RelOptInfo *input_rel,
RelOptInfo *output_rel);
extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook; extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;