Redefine create_upper_paths_hook as being invoked once per upper relation.
authorTom Lane
Tue, 12 Apr 2016 19:23:14 +0000 (15:23 -0400)
committerTom Lane
Tue, 12 Apr 2016 19:23:14 +0000 (15:23 -0400)
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
src/backend/optimizer/prep/prepunion.c
src/include/optimizer/planner.h

index b2a9a8088f61d855945e5ec57eb7298a056a091d..7c1e3d6bbfd29ae9c2f8bc916262d7c7c5776381 100644 (file)
@@ -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.
index a1ab4daf11a7d8e3361467d8837f6e0831ccbf5a..552b756b8b1b5da51445c02183a304889b439ee1 100644 (file)
@@ -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;
index a95e73fa93b4e36f83dd0c79b8b3b2160ec87729..4161bcf8d745221a6acec7f0f721b96ef07984c1 100644 (file)
@@ -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;