src/backend/optimizer/util/pathnode.c | 26 ++++++++++++++++++++++++++ src/include/optimizer/pathnode.h | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 34acb73..0955271 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -58,6 +58,7 @@ static List *reparameterize_pathlist_by_child(PlannerInfo *root, List *pathlist, RelOptInfo *child_rel); +path_removal_decision_hook_type path_removal_decision_hook = NULL; /***************************************************************************** * MISC. PATH UTILITIES @@ -581,6 +582,22 @@ add_path(RelOptInfo *parent_rel, Path *new_path) } /* + * This hook allows extension to provide an extra decision + * whether add_path() retains the dominated path by other new + * path, from different dimensions. + * Even if the old_path is not cheapest at this level, we can + * assume a combination with an expected upper path may have + * cheaper cost on the upper level. + */ + if (remove_old && path_removal_decision_hook) + { + remove_old = path_removal_decision_hook(parent_rel, + new_path, + old_path, + false); + } + + /* * Remove current element from pathlist if dominated by new. */ if (remove_old) @@ -816,6 +833,15 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) } } + if (remove_old && path_removal_decision_hook) + { + /* see comments at add_path() */ + remove_old = path_removal_decision_hook(parent_rel, + new_path, + old_path, + true); + } + /* * Remove current element from partial_pathlist if dominated by new. */ diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index a12af54..82a5e5e 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -17,6 +17,15 @@ #include "nodes/bitmapset.h" #include "nodes/pathnodes.h" +/* + * Plugins can provide extra decision whether (partial_)pathlist retain + * a path dominated by other new paths. + */ +typedef bool (*path_removal_decision_hook_type)(RelOptInfo *parent_rel, + Path *new_path, + Path *old_path, + bool is_partial_pathlist); +extern PGDLLIMPORT path_removal_decision_hook_type path_removal_decision_hook; /* * prototypes for pathnode.c