aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/planner.c45
-rw-r--r--src/backend/optimizer/prep/prepunion.c7
-rw-r--r--src/include/optimizer/planner.h6
3 files changed, 45 insertions, 13 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index b2a9a8088f6..7c1e3d6bbfd 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 a1ab4daf11a..552b756b8b1 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 a95e73fa93b..4161bcf8d74 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;