From af8f5bd65e33c819723231ce433dcd51438b7ef0 Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Thu, 26 Sep 2024 10:34:08 +0200 Subject: [PATCH 1/2] Introduce compare_path_hook. The add_path function is the only interface to safely add and remove paths in the pathlist. Postgres core provides a few optimisation hooks that an extension can use to offer additional paths. However, it is still uncertain whether such a path will be replaced until the end of the path population process. This hook allows the extension to control the comparison of a new path with each pathlist's path and denote the optimiser which path is better. It doesn't point to the optimiser directly about what exactly to do with the incoming path and paths, already existed in pathlist. Tag: optimizer. caused by: PGPRO-10445, PGPRO-11017. --- src/backend/optimizer/util/pathnode.c | 21 +++++++++++---------- src/include/optimizer/pathnode.h | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index fc97bf6ee2..ae57932862 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -31,13 +31,6 @@ #include "utils/memutils.h" #include "utils/selfuncs.h" -typedef enum -{ - COSTS_EQUAL, /* path costs are fuzzily equal */ - COSTS_BETTER1, /* first path is cheaper than second */ - COSTS_BETTER2, /* second path is cheaper than first */ - COSTS_DIFFERENT, /* neither path dominates the other on cost */ -} PathCostComparison; /* * STD_FUZZ_FACTOR is the normal fuzz factor for compare_path_costs_fuzzily. @@ -46,6 +39,9 @@ typedef enum */ #define STD_FUZZ_FACTOR 1.01 +/* Hook for plugins to get control over the add_path decision */ +compare_path_hook_type compare_path_hook = NULL; + static List *translate_sub_tlist(List *tlist, int relid); static int append_total_cost_compare(const ListCell *a, const ListCell *b); static int append_startup_cost_compare(const ListCell *a, const ListCell *b); @@ -178,7 +174,7 @@ compare_fractional_path_costs(Path *path1, Path *path2, * (But if total costs are fuzzily equal, we compare startup costs anyway, * in hopes of eliminating one path or the other.) */ -static PathCostComparison +PathCostComparison compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor) { #define CONSIDER_PATH_STARTUP_COST(p) \ @@ -490,8 +486,13 @@ add_path(RelOptInfo *parent_rel, Path *new_path) /* * Do a fuzzy cost comparison with standard fuzziness limit. */ - costcmp = compare_path_costs_fuzzily(new_path, old_path, - STD_FUZZ_FACTOR); + + if (compare_path_hook) + costcmp = (*compare_path_hook) (parent_rel, new_path, old_path, + STD_FUZZ_FACTOR); + else + costcmp = compare_path_costs_fuzzily(new_path, old_path, + STD_FUZZ_FACTOR); /* * If the two paths compare differently for startup and total cost, diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 1035e6560c..4b95d85e1a 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -18,11 +18,28 @@ #include "nodes/pathnodes.h" +typedef enum +{ + COSTS_EQUAL, /* path costs are fuzzily equal */ + COSTS_BETTER1, /* first path is cheaper than second */ + COSTS_BETTER2, /* second path is cheaper than first */ + COSTS_DIFFERENT, /* neither path dominates the other on cost */ +} PathCostComparison; + +/* Hook for plugins to get control when grouping_planner() plans upper rels */ +typedef PathCostComparison (*compare_path_hook_type) (RelOptInfo *parent_rel, + Path *new_path, + Path *old_path, + double fuzz_factor); +extern PGDLLIMPORT compare_path_hook_type compare_path_hook; + /* * prototypes for pathnode.c */ extern int compare_path_costs(Path *path1, Path *path2, CostSelector criterion); +extern PathCostComparison +compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor); extern int compare_fractional_path_costs(Path *path1, Path *path2, double fraction); extern void set_cheapest(RelOptInfo *parent_rel); -- 2.46.2