From f1f01de145d0aaca80e6cf8b2ccb7e7f4ed1ad02 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 12 Apr 2016 15:23:14 -0400 Subject: [PATCH] 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. --- src/backend/optimizer/plan/planner.c | 45 ++++++++++++++++++++------ src/backend/optimizer/prep/prepunion.c | 7 +++- src/include/optimizer/planner.h | 6 ++-- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index b2a9a8088f..7c1e3d6bbf 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -62,7 +62,7 @@ int force_parallel_mode = FORCE_PARALLEL_OFF; /* Hook for plugins to get control in planner() */ 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; @@ -1772,20 +1772,20 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, root->upper_targets[UPPERREL_GROUP_AGG] = grouping_target; /* - * Let extensions, particularly FDWs and CustomScan providers, - * consider injecting extension Paths into the query's upperrels, - * where they will compete with the Paths we create below. We pass - * the final scan/join rel because that's not so easily findable from - * the PlannerInfo struct; anything else the hooks want to know should - * be obtainable via "root". + * If there is an FDW that's responsible for the final scan/join rel, + * let it consider injecting extension Paths into the query's + * upperrels, where they will compete with the Paths we create below. + * We pass the final scan/join rel because that's not so easily + * findable from the PlannerInfo struct; anything else the FDW wants + * 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 && current_rel->fdwroutine->GetForeignUpperPaths) 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 * 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); } + /* 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() */ } @@ -3724,6 +3729,11 @@ create_grouping_paths(PlannerInfo *root, errmsg("could not implement GROUP BY"), 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) */ set_cheapest(grouped_rel); @@ -3780,6 +3790,11 @@ create_window_paths(PlannerInfo *root, 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) */ set_cheapest(window_rel); @@ -4056,6 +4071,11 @@ create_distinct_paths(PlannerInfo *root, errmsg("could not implement DISTINCT"), 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) */ 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 * need us to do it. diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index a1ab4daf11..552b756b8b 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -206,7 +206,12 @@ plan_set_operations(PlannerInfo *root) /* Add only the final path to the SETOP upperrel. */ 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); return setop_rel; diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index a95e73fa93..4161bcf8d7 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -24,9 +24,11 @@ typedef PlannedStmt *(*planner_hook_type) (Query *parse, ParamListInfo boundParams); 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, - RelOptInfo *scan_join_rel); + UpperRelationKind stage, + RelOptInfo *input_rel, + RelOptInfo *output_rel); extern PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook;