From e288a50dcc70dacef1d1de8cea5c2eacecd7908e Mon Sep 17 00:00:00 2001 From: Alena Rybakina Date: Thu, 23 May 2024 16:31:58 +0300 Subject: [PATCH] Update patch --- aqo_master.patch | 1499 +++++++++++++++++++------------------- expected/aqo_fdw.out | 19 +- expected/unsupported.out | 22 +- 3 files changed, 769 insertions(+), 771 deletions(-) diff --git a/aqo_master.patch b/aqo_master.patch index 8a1030e6..dc9beb77 100644 --- a/aqo_master.patch +++ b/aqo_master.patch @@ -1,747 +1,752 @@ -diff --git a/contrib/Makefile b/contrib/Makefile -index abd780f2774..601892ef54a 100644 ---- a/contrib/Makefile -+++ b/contrib/Makefile -@@ -6,6 +6,7 @@ include $(top_builddir)/src/Makefile.global - - SUBDIRS = \ - amcheck \ -+ aqo \ - auth_delay \ - auto_explain \ - basic_archive \ -diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c -index 94511a5a024..81b04bf9eb9 100644 ---- a/src/backend/commands/explain.c -+++ b/src/backend/commands/explain.c -@@ -24,6 +24,7 @@ - #include "nodes/extensible.h" - #include "nodes/makefuncs.h" - #include "nodes/nodeFuncs.h" -+#include "optimizer/cost.h" - #include "parser/analyze.h" - #include "parser/parsetree.h" - #include "rewrite/rewriteHandler.h" -@@ -47,6 +48,12 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; - /* Hook for plugins to get control in explain_get_index_name() */ - explain_get_index_name_hook_type explain_get_index_name_hook = NULL; - -+/* Hook for plugins to get control in ExplainOnePlan() */ -+ExplainOnePlan_hook_type ExplainOnePlan_hook = NULL; -+ -+/* Hook for plugins to get control in ExplainOnePlan() */ -+ExplainOneNode_hook_type ExplainOneNode_hook = NULL; -+ - - /* Instrumentation data for SERIALIZE option */ - typedef struct SerializeMetrics -@@ -795,6 +802,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, - ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3, - es); - -+ if (ExplainOnePlan_hook) -+ ExplainOnePlan_hook(plannedstmt, into, es, -+ queryString, params, planduration, queryEnv); -+ - ExplainCloseGroup("Query", NULL, true, es); - } - -@@ -1885,6 +1896,9 @@ ExplainNode(PlanState *planstate, List *ancestors, - } - } - -+ if (ExplainOneNode_hook) -+ ExplainOneNode_hook(es, planstate, plan); -+ - /* in text format, first line ends here */ - if (es->format == EXPLAIN_FORMAT_TEXT) - appendStringInfoChar(es->str, '\n'); -diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c -index ee23ed7835d..4ca51d39d1c 100644 ---- a/src/backend/optimizer/path/costsize.c -+++ b/src/backend/optimizer/path/costsize.c -@@ -98,6 +98,11 @@ - #include "utils/spccache.h" - #include "utils/tuplesort.h" - -+set_baserel_rows_estimate_hook_type set_baserel_rows_estimate_hook = NULL; -+set_foreign_rows_estimate_hook_type set_foreign_rows_estimate_hook = NULL; -+get_parameterized_baserel_size_hook_type get_parameterized_baserel_size_hook = NULL; -+get_parameterized_joinrel_size_hook_type get_parameterized_joinrel_size_hook = NULL; -+set_joinrel_size_estimates_hook_type set_joinrel_size_estimates_hook = NULL; - - #define LOG2(x) (log(x) / 0.693147180559945) - -@@ -191,7 +196,6 @@ static void set_rel_width(PlannerInfo *root, RelOptInfo *rel); - static int32 get_expr_width(PlannerInfo *root, const Node *expr); - static double relation_byte_size(double tuples, int width); - static double page_size(double tuples, int width); --static double get_parallel_divisor(Path *path); - - - /* -@@ -5222,6 +5226,58 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals) - } - - -+void -+set_foreign_rows_estimate(PlannerInfo *root, RelOptInfo *rel) -+{ -+ if (set_foreign_rows_estimate_hook) -+ (*set_foreign_rows_estimate_hook) (root, rel); -+ else -+ rel->rows = 1000; /* entirely bogus default estimate */ -+} -+ -+/* -+ * set_baserel_rows_estimate -+ * Set the rows estimate for the given base relation. -+ * -+ * Rows is the estimated number of output tuples after applying -+ * restriction clauses. -+ * -+ * To support loadable plugins that monitor or modify cardinality estimation, -+ * we provide a hook variable that lets a plugin get control before and -+ * after the cardinality estimation. -+ * The hook must set rel->rows. -+ */ -+void -+set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel) -+{ -+ if (set_baserel_rows_estimate_hook) -+ (*set_baserel_rows_estimate_hook) (root, rel); -+ else -+ set_baserel_rows_estimate_standard(root, rel); -+} -+ -+/* -+ * set_baserel_rows_estimate -+ * Set the rows estimate for the given base relation. -+ * -+ * Rows is the estimated number of output tuples after applying -+ * restriction clauses. -+ */ -+void -+set_baserel_rows_estimate_standard(PlannerInfo *root, RelOptInfo *rel) -+{ -+ double nrows; -+ -+ nrows = rel->tuples * -+ clauselist_selectivity(root, -+ rel->baserestrictinfo, -+ 0, -+ JOIN_INNER, -+ NULL); -+ -+ rel->rows = clamp_row_est(nrows); -+} -+ - /* - * set_baserel_size_estimates - * Set the size estimates for the given base relation. -@@ -5238,19 +5294,10 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals) - void - set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) - { -- double nrows; -- - /* Should only be applied to base relations */ - Assert(rel->relid > 0); - -- nrows = rel->tuples * -- clauselist_selectivity(root, -- rel->baserestrictinfo, -- 0, -- JOIN_INNER, -- NULL); -- -- rel->rows = clamp_row_est(nrows); -+ set_baserel_rows_estimate(root, rel); - - cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); - -@@ -5261,13 +5308,33 @@ set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) - * get_parameterized_baserel_size - * Make a size estimate for a parameterized scan of a base relation. - * -+ * To support loadable plugins that monitor or modify cardinality estimation, -+ * we provide a hook variable that lets a plugin get control before and -+ * after the cardinality estimation. -+ */ -+double -+get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, -+ List *param_clauses) -+{ -+ if (get_parameterized_baserel_size_hook) -+ return (*get_parameterized_baserel_size_hook) (root, rel, -+ param_clauses); -+ else -+ return get_parameterized_baserel_size_standard(root, rel, -+ param_clauses); -+} -+ -+/* -+ * get_parameterized_baserel_size_standard -+ * Make a size estimate for a parameterized scan of a base relation. -+ * - * 'param_clauses' lists the additional join clauses to be used. - * - * set_baserel_size_estimates must have been applied already. - */ - double --get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, -- List *param_clauses) -+get_parameterized_baserel_size_standard(PlannerInfo *root, RelOptInfo *rel, -+ List *param_clauses) - { - List *allclauses; - double nrows; -@@ -5296,6 +5363,36 @@ get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, - * set_joinrel_size_estimates - * Set the size estimates for the given join relation. - * -+ * To support loadable plugins that monitor or modify cardinality estimation, -+ * we provide a hook variable that lets a plugin get control before and -+ * after the cardinality estimation. -+ * The hook must set rel->rows value. -+ */ -+void -+set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, -+ RelOptInfo *outer_rel, -+ RelOptInfo *inner_rel, -+ SpecialJoinInfo *sjinfo, -+ List *restrictlist) -+{ -+ if (set_joinrel_size_estimates_hook) -+ (*set_joinrel_size_estimates_hook) (root, rel, -+ outer_rel, -+ inner_rel, -+ sjinfo, -+ restrictlist); -+ else -+ set_joinrel_size_estimates_standard(root, rel, -+ outer_rel, -+ inner_rel, -+ sjinfo, -+ restrictlist); -+} -+ -+/* -+ * set_joinrel_size_estimates_standard -+ * Set the size estimates for the given join relation. -+ * - * The rel's targetlist must have been constructed already, and a - * restriction clause list that matches the given component rels must - * be provided. -@@ -5315,11 +5412,11 @@ get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, - * build_joinrel_tlist, and baserestrictcost is not used for join rels. - */ - void --set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, -- RelOptInfo *outer_rel, -- RelOptInfo *inner_rel, -- SpecialJoinInfo *sjinfo, -- List *restrictlist) -+set_joinrel_size_estimates_standard(PlannerInfo *root, RelOptInfo *rel, -+ RelOptInfo *outer_rel, -+ RelOptInfo *inner_rel, -+ SpecialJoinInfo *sjinfo, -+ List *restrictlist) - { - rel->rows = calc_joinrel_size_estimate(root, - rel, -@@ -5335,6 +5432,35 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, - * get_parameterized_joinrel_size - * Make a size estimate for a parameterized scan of a join relation. - * -+ * To support loadable plugins that monitor or modify cardinality estimation, -+ * we provide a hook variable that lets a plugin get control before and -+ * after the cardinality estimation. -+ */ -+double -+get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, -+ Path *outer_path, -+ Path *inner_path, -+ SpecialJoinInfo *sjinfo, -+ List *restrict_clauses) -+{ -+ if (get_parameterized_joinrel_size_hook) -+ return (*get_parameterized_joinrel_size_hook) (root, rel, -+ outer_path, -+ inner_path, -+ sjinfo, -+ restrict_clauses); -+ else -+ return get_parameterized_joinrel_size_standard(root, rel, -+ outer_path, -+ inner_path, -+ sjinfo, -+ restrict_clauses); -+} -+ -+/* -+ * get_parameterized_joinrel_size_standard -+ * Make a size estimate for a parameterized scan of a join relation. -+ * - * 'rel' is the joinrel under consideration. - * 'outer_path', 'inner_path' are (probably also parameterized) Paths that - * produce the relations being joined. -@@ -5347,11 +5473,11 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, - * set_joinrel_size_estimates must have been applied already. - */ - double --get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, -- Path *outer_path, -- Path *inner_path, -- SpecialJoinInfo *sjinfo, -- List *restrict_clauses) -+get_parameterized_joinrel_size_standard(PlannerInfo *root, RelOptInfo *rel, -+ Path *outer_path, -+ Path *inner_path, -+ SpecialJoinInfo *sjinfo, -+ List *restrict_clauses) - { - double nrows; - -@@ -6066,7 +6192,7 @@ set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel) - /* Should only be applied to base relations */ - Assert(rel->relid > 0); - -- rel->rows = 1000; /* entirely bogus default estimate */ -+ set_foreign_rows_estimate(root, rel); - - cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); - -@@ -6359,7 +6485,7 @@ page_size(double tuples, int width) - * Estimate the fraction of the work that each worker will do given the - * number of workers budgeted for the path. - */ --static double -+double - get_parallel_divisor(Path *path) - { - double parallel_divisor = path->parallel_workers; -diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c -index 6b64c4a362d..4e44babc0a2 100644 ---- a/src/backend/optimizer/plan/createplan.c -+++ b/src/backend/optimizer/plan/createplan.c -@@ -71,6 +71,7 @@ - #define CP_LABEL_TLIST 0x0004 /* tlist must contain sortgrouprefs */ - #define CP_IGNORE_TLIST 0x0008 /* caller will replace tlist */ - -+create_plan_hook_type create_plan_hook = NULL; - - static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path, - int flags); -@@ -548,6 +549,10 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags) - break; - } - -+ if (create_plan_hook) -+ /* Give an extension a chance to do something */ -+ (*create_plan_hook)(root, best_path, &plan); -+ - return plan; - } - -@@ -5414,6 +5419,7 @@ copy_generic_path_info(Plan *dest, Path *src) - dest->plan_width = src->pathtarget->width; - dest->parallel_aware = src->parallel_aware; - dest->parallel_safe = src->parallel_safe; -+ dest->ext_nodes = NIL; - } - - /* -diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c -index 032818423f6..a5c7e71b724 100644 ---- a/src/backend/optimizer/plan/planner.c -+++ b/src/backend/optimizer/plan/planner.c -@@ -142,7 +142,8 @@ static List *extract_rollup_sets(List *groupingSets); - static List *reorder_grouping_sets(List *groupingSets, List *sortclause); - static void standard_qp_callback(PlannerInfo *root, void *extra); - static double get_number_of_groups(PlannerInfo *root, -- double path_rows, -+ Path *subpath, -+ RelOptInfo *grouped_rel, - grouping_sets_data *gd, - List *target_list); - static RelOptInfo *create_grouping_paths(PlannerInfo *root, -@@ -3531,7 +3532,8 @@ standard_qp_callback(PlannerInfo *root, void *extra) - */ - static double - get_number_of_groups(PlannerInfo *root, -- double path_rows, -+ Path *subpath, -+ RelOptInfo *grouped_rel, - grouping_sets_data *gd, - List *target_list) - { -@@ -3568,7 +3570,7 @@ get_number_of_groups(PlannerInfo *root, - GroupingSetData *gs = lfirst_node(GroupingSetData, lc3); - double numGroups = estimate_num_groups(root, - groupExprs, -- path_rows, -+ subpath->rows, - &gset, - NULL); - -@@ -3594,7 +3596,7 @@ get_number_of_groups(PlannerInfo *root, - GroupingSetData *gs = lfirst_node(GroupingSetData, lc2); - double numGroups = estimate_num_groups(root, - groupExprs, -- path_rows, -+ subpath->rows, - &gset, - NULL); - -@@ -3611,8 +3613,8 @@ get_number_of_groups(PlannerInfo *root, - groupExprs = get_sortgrouplist_exprs(root->processed_groupClause, - target_list); - -- dNumGroups = estimate_num_groups(root, groupExprs, path_rows, -- NULL, NULL); -+ dNumGroups = estimate_num_groups_ext(root, groupExprs, subpath, -+ grouped_rel, NULL, NULL); - } - } - else if (parse->groupingSets) -@@ -4002,7 +4004,8 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, - * Estimate number of groups. - */ - dNumGroups = get_number_of_groups(root, -- cheapest_path->rows, -+ cheapest_path, -+ grouped_rel, - gd, - extra->targetList); - -@@ -7207,13 +7210,15 @@ create_partial_grouping_paths(PlannerInfo *root, - if (cheapest_total_path != NULL) - dNumPartialGroups = - get_number_of_groups(root, -- cheapest_total_path->rows, -+ cheapest_total_path, -+ partially_grouped_rel, - gd, - extra->targetList); - if (cheapest_partial_path != NULL) - dNumPartialPartialGroups = - get_number_of_groups(root, -- cheapest_partial_path->rows, -+ cheapest_partial_path, -+ partially_grouped_rel, - gd, - extra->targetList); - -diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c -index e05b21c884e..5805136b70f 100644 ---- a/src/backend/optimizer/util/relnode.c -+++ b/src/backend/optimizer/util/relnode.c -@@ -286,6 +286,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) - rel->all_partrels = NULL; - rel->partexprs = NULL; - rel->nullable_partexprs = NULL; -+ rel->ext_nodes = NULL; - - /* - * Pass assorted information down the inheritance hierarchy. -@@ -422,7 +423,6 @@ find_base_rel(PlannerInfo *root, int relid) - if (rel) - return rel; - } -- - elog(ERROR, "no relation entry for relid %d", relid); - - return NULL; /* keep compiler quiet */ -@@ -768,6 +768,7 @@ build_join_rel(PlannerInfo *root, - joinrel->all_partrels = NULL; - joinrel->partexprs = NULL; - joinrel->nullable_partexprs = NULL; -+ joinrel->ext_nodes = NULL; - - /* Compute information relevant to the foreign relations. */ - set_foreign_rel_properties(joinrel, outer_rel, inner_rel); -@@ -962,6 +963,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, - joinrel->all_partrels = NULL; - joinrel->partexprs = NULL; - joinrel->nullable_partexprs = NULL; -+ joinrel->ext_nodes = NULL; - - /* Compute information relevant to foreign relations. */ - set_foreign_rel_properties(joinrel, outer_rel, inner_rel); -@@ -1542,6 +1544,7 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel) - } - - -+set_parampathinfo_postinit_hook_type parampathinfo_postinit_hook = NULL; - /* - * get_baserel_parampathinfo - * Get the ParamPathInfo for a parameterized path for a base relation, -@@ -1634,6 +1637,10 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, - ppi->ppi_rows = rows; - ppi->ppi_clauses = pclauses; - ppi->ppi_serials = pserials; -+ -+ if (parampathinfo_postinit_hook) -+ (*parampathinfo_postinit_hook)(ppi); -+ - baserel->ppilist = lappend(baserel->ppilist, ppi); - - return ppi; -@@ -1888,6 +1895,10 @@ get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer) - ppi->ppi_rows = 0; - ppi->ppi_clauses = NIL; - ppi->ppi_serials = NULL; -+ -+ if (parampathinfo_postinit_hook) -+ (*parampathinfo_postinit_hook)(ppi); -+ - appendrel->ppilist = lappend(appendrel->ppilist, ppi); - - return ppi; -diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c -index 5f5d7959d8e..20f63aae589 100644 ---- a/src/backend/utils/adt/selfuncs.c -+++ b/src/backend/utils/adt/selfuncs.c -@@ -146,6 +146,7 @@ - /* Hooks for plugins to get control when we ask for stats */ - get_relation_stats_hook_type get_relation_stats_hook = NULL; - get_index_stats_hook_type get_index_stats_hook = NULL; -+estimate_num_groups_hook_type estimate_num_groups_hook = NULL; - - static double eqsel_internal(PG_FUNCTION_ARGS, bool negate); - static double eqjoinsel_inner(Oid opfuncoid, Oid collation, -@@ -3341,6 +3342,20 @@ add_unique_group_var(PlannerInfo *root, List *varinfos, - return varinfos; - } - -+double -+estimate_num_groups_ext(PlannerInfo *root, List *groupExprs, Path *subpath, -+ RelOptInfo *grouped_rel, List **pgset, -+ EstimationInfo *estinfo) -+{ -+ double input_rows = subpath->rows; -+ -+ if (estimate_num_groups_hook != NULL) -+ return (*estimate_num_groups_hook)(root, groupExprs, subpath, grouped_rel, -+ pgset, estinfo); -+ -+ return estimate_num_groups(root, groupExprs, input_rows, pgset, estinfo); -+} -+ - /* - * estimate_num_groups - Estimate number of groups in a grouped query - * -diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h -index 9b8b351d9a2..f49233826af 100644 ---- a/src/include/commands/explain.h -+++ b/src/include/commands/explain.h -@@ -85,6 +85,18 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook; - typedef const char *(*explain_get_index_name_hook_type) (Oid indexId); - extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook; - -+/* Hook for plugins to get control in ExplainOnePlan() */ -+typedef void (*ExplainOnePlan_hook_type) (PlannedStmt *plannedstmt, IntoClause *into, -+ ExplainState *es, const char *queryString, -+ ParamListInfo params, const instr_time *planduration, -+ QueryEnvironment *queryEnv); -+extern PGDLLIMPORT ExplainOnePlan_hook_type ExplainOnePlan_hook; -+ -+/* Explain a node info */ -+typedef void (*ExplainOneNode_hook_type) (ExplainState *es, -+ PlanState *ps, -+ Plan *plan); -+extern PGDLLIMPORT ExplainOneNode_hook_type ExplainOneNode_hook; - - extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, - ParamListInfo params, DestReceiver *dest); -diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h -index 14ef296ab72..b1316b8f791 100644 ---- a/src/include/nodes/pathnodes.h -+++ b/src/include/nodes/pathnodes.h -@@ -1039,6 +1039,16 @@ typedef struct RelOptInfo - List **partexprs pg_node_attr(read_write_ignore); - /* Nullable partition key expressions */ - List **nullable_partexprs pg_node_attr(read_write_ignore); -+ -+ /* For Adaptive optimization DEBUG purposes */ -+ double predicted_cardinality; -+ int fss_hash; -+ -+ /* -+ * At this list an extension can add additional nodes to pass an info along -+ * the planning and executing stages. -+ */ -+ List *ext_nodes; - } RelOptInfo; - - /* -@@ -1569,6 +1579,10 @@ typedef struct ParamPathInfo - Cardinality ppi_rows; /* estimated number of result tuples */ - List *ppi_clauses; /* join clauses available from outer rels */ - Bitmapset *ppi_serials; /* set of rinfo_serial for enforced quals */ -+ -+ /* AQO DEBUG purposes */ -+ double predicted_ppi_rows; -+ double fss_ppi_hash; - } ParamPathInfo; - - -diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h -index 1aeeaec95e1..308f38214a3 100644 ---- a/src/include/nodes/plannodes.h -+++ b/src/include/nodes/plannodes.h -@@ -169,6 +169,9 @@ typedef struct Plan - */ - Bitmapset *extParam; - Bitmapset *allParam; -+ -+ /* Additional field for an extension purposes. */ -+ List *ext_nodes; - } Plan; - - /* ---------------- -diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h -index b1c51a4e70f..1cb601e3b27 100644 ---- a/src/include/optimizer/cost.h -+++ b/src/include/optimizer/cost.h -@@ -41,6 +41,37 @@ typedef enum - } ConstraintExclusionType; - - -+/* Hook for plugins to get control of cardinality estimation */ -+typedef void (*set_baserel_rows_estimate_hook_type) (PlannerInfo *root, -+ RelOptInfo *rel); -+typedef void (*set_foreign_rows_estimate_hook_type) (PlannerInfo *root, -+ RelOptInfo *rel); -+extern PGDLLIMPORT set_baserel_rows_estimate_hook_type -+ set_baserel_rows_estimate_hook; -+extern PGDLLIMPORT set_foreign_rows_estimate_hook_type -+ set_foreign_rows_estimate_hook; -+typedef double (*get_parameterized_baserel_size_hook_type) (PlannerInfo *root, -+ RelOptInfo *rel, -+ List *param_clauses); -+extern PGDLLIMPORT get_parameterized_baserel_size_hook_type -+ get_parameterized_baserel_size_hook; -+typedef double (*get_parameterized_joinrel_size_hook_type) (PlannerInfo *root, -+ RelOptInfo *rel, -+ Path *outer_path, -+ Path *inner_path, -+ SpecialJoinInfo *sjinfo, -+ List *restrict_clauses); -+extern PGDLLIMPORT get_parameterized_joinrel_size_hook_type -+ get_parameterized_joinrel_size_hook; -+typedef void (*set_joinrel_size_estimates_hook_type) (PlannerInfo *root, -+ RelOptInfo *rel, -+ RelOptInfo *outer_rel, -+ RelOptInfo *inner_rel, -+ SpecialJoinInfo *sjinfo, -+ List *restrictlist); -+extern PGDLLIMPORT set_joinrel_size_estimates_hook_type -+ set_joinrel_size_estimates_hook; -+ - /* - * prototypes for costsize.c - * routines to compute costs and sizes -@@ -184,10 +215,22 @@ extern void compute_semi_anti_join_factors(PlannerInfo *root, - SpecialJoinInfo *sjinfo, - List *restrictlist, - SemiAntiJoinFactors *semifactors); -+extern void set_foreign_rows_estimate(PlannerInfo *root, RelOptInfo *rel); -+extern void set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel); -+extern void set_baserel_rows_estimate_standard(PlannerInfo *root, RelOptInfo *rel); - extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel); - extern double get_parameterized_baserel_size(PlannerInfo *root, - RelOptInfo *rel, - List *param_clauses); -+extern double get_parameterized_baserel_size_standard(PlannerInfo *root, -+ RelOptInfo *rel, -+ List *param_clauses); -+extern double get_parameterized_joinrel_size_standard(PlannerInfo *root, -+ RelOptInfo *rel, -+ Path *outer_path, -+ Path *inner_path, -+ SpecialJoinInfo *sjinfo, -+ List *restrict_clauses); - extern double get_parameterized_joinrel_size(PlannerInfo *root, - RelOptInfo *rel, - Path *outer_path, -@@ -199,6 +242,11 @@ extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, - RelOptInfo *inner_rel, - SpecialJoinInfo *sjinfo, - List *restrictlist); -+extern void set_joinrel_size_estimates_standard(PlannerInfo *root, RelOptInfo *rel, -+ RelOptInfo *outer_rel, -+ RelOptInfo *inner_rel, -+ SpecialJoinInfo *sjinfo, -+ List *restrictlist); - extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel); - extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel); - extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel); -@@ -212,5 +260,6 @@ extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *targ - extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, - Path *bitmapqual, double loop_count, - Cost *cost_p, double *tuples_p); -+extern double get_parallel_divisor(Path *path); - - #endif /* COST_H */ -diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h -index 112e7c23d4e..8397995e183 100644 ---- a/src/include/optimizer/pathnode.h -+++ b/src/include/optimizer/pathnode.h -@@ -18,6 +18,10 @@ - #include "nodes/pathnodes.h" - - -+typedef void (*set_parampathinfo_postinit_hook_type) (ParamPathInfo *ppi); -+ -+extern PGDLLIMPORT set_parampathinfo_postinit_hook_type parampathinfo_postinit_hook; -+ - /* - * prototypes for pathnode.c - */ -diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h -index aafc1737921..d520d8d5475 100644 ---- a/src/include/optimizer/planmain.h -+++ b/src/include/optimizer/planmain.h -@@ -24,6 +24,12 @@ extern PGDLLIMPORT double cursor_tuple_fraction; - /* query_planner callback to compute query_pathkeys */ - typedef void (*query_pathkeys_callback) (PlannerInfo *root, void *extra); - -+ -+/* Hook for plugins to get control in ExecutorRun() */ -+typedef void (*create_plan_hook_type) (PlannerInfo *root, -+ Path *best_path, -+ Plan **plan); -+extern PGDLLIMPORT create_plan_hook_type create_plan_hook; - /* - * prototypes for plan/planmain.c - */ -diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h -index f2563ad1cb3..0beac5f3139 100644 ---- a/src/include/utils/selfuncs.h -+++ b/src/include/utils/selfuncs.h -@@ -147,6 +147,13 @@ typedef bool (*get_index_stats_hook_type) (PlannerInfo *root, - AttrNumber indexattnum, - VariableStatData *vardata); - extern PGDLLIMPORT get_index_stats_hook_type get_index_stats_hook; -+typedef double (*estimate_num_groups_hook_type) (PlannerInfo *root, -+ List *groupExprs, -+ Path *subpath, -+ RelOptInfo *grouped_rel, -+ List **pgset, -+ EstimationInfo *estinfo); -+extern PGDLLIMPORT estimate_num_groups_hook_type estimate_num_groups_hook; - - /* Functions in selfuncs.c */ - -@@ -213,6 +220,9 @@ extern void mergejoinscansel(PlannerInfo *root, Node *clause, - Selectivity *leftstart, Selectivity *leftend, - Selectivity *rightstart, Selectivity *rightend); - -+extern double estimate_num_groups_ext(PlannerInfo *root, List *groupExprs, -+ Path *subpath, RelOptInfo *grouped_rel, -+ List **pgset, EstimationInfo *estinfo); - extern double estimate_num_groups(PlannerInfo *root, List *groupExprs, - double input_rows, List **pgset, - EstimationInfo *estinfo); +diff --git a/aqo_master.patch b/aqo_master.patch +index 8a1030e..e69de29 100644 +--- a/aqo_master.patch ++++ b/aqo_master.patch +@@ -1,747 +0,0 @@ +-diff --git a/contrib/Makefile b/contrib/Makefile +-index abd780f2774..601892ef54a 100644 +---- a/contrib/Makefile +-+++ b/contrib/Makefile +-@@ -6,6 +6,7 @@ include $(top_builddir)/src/Makefile.global +- +- SUBDIRS = \ +- amcheck \ +-+ aqo \ +- auth_delay \ +- auto_explain \ +- basic_archive \ +-diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c +-index 94511a5a024..81b04bf9eb9 100644 +---- a/src/backend/commands/explain.c +-+++ b/src/backend/commands/explain.c +-@@ -24,6 +24,7 @@ +- #include "nodes/extensible.h" +- #include "nodes/makefuncs.h" +- #include "nodes/nodeFuncs.h" +-+#include "optimizer/cost.h" +- #include "parser/analyze.h" +- #include "parser/parsetree.h" +- #include "rewrite/rewriteHandler.h" +-@@ -47,6 +48,12 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; +- /* Hook for plugins to get control in explain_get_index_name() */ +- explain_get_index_name_hook_type explain_get_index_name_hook = NULL; +- +-+/* Hook for plugins to get control in ExplainOnePlan() */ +-+ExplainOnePlan_hook_type ExplainOnePlan_hook = NULL; +-+ +-+/* Hook for plugins to get control in ExplainOnePlan() */ +-+ExplainOneNode_hook_type ExplainOneNode_hook = NULL; +-+ +- +- /* Instrumentation data for SERIALIZE option */ +- typedef struct SerializeMetrics +-@@ -795,6 +802,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, +- ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3, +- es); +- +-+ if (ExplainOnePlan_hook) +-+ ExplainOnePlan_hook(plannedstmt, into, es, +-+ queryString, params, planduration, queryEnv); +-+ +- ExplainCloseGroup("Query", NULL, true, es); +- } +- +-@@ -1885,6 +1896,9 @@ ExplainNode(PlanState *planstate, List *ancestors, +- } +- } +- +-+ if (ExplainOneNode_hook) +-+ ExplainOneNode_hook(es, planstate, plan); +-+ +- /* in text format, first line ends here */ +- if (es->format == EXPLAIN_FORMAT_TEXT) +- appendStringInfoChar(es->str, '\n'); +-diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c +-index ee23ed7835d..4ca51d39d1c 100644 +---- a/src/backend/optimizer/path/costsize.c +-+++ b/src/backend/optimizer/path/costsize.c +-@@ -98,6 +98,11 @@ +- #include "utils/spccache.h" +- #include "utils/tuplesort.h" +- +-+set_baserel_rows_estimate_hook_type set_baserel_rows_estimate_hook = NULL; +-+set_foreign_rows_estimate_hook_type set_foreign_rows_estimate_hook = NULL; +-+get_parameterized_baserel_size_hook_type get_parameterized_baserel_size_hook = NULL; +-+get_parameterized_joinrel_size_hook_type get_parameterized_joinrel_size_hook = NULL; +-+set_joinrel_size_estimates_hook_type set_joinrel_size_estimates_hook = NULL; +- +- #define LOG2(x) (log(x) / 0.693147180559945) +- +-@@ -191,7 +196,6 @@ static void set_rel_width(PlannerInfo *root, RelOptInfo *rel); +- static int32 get_expr_width(PlannerInfo *root, const Node *expr); +- static double relation_byte_size(double tuples, int width); +- static double page_size(double tuples, int width); +--static double get_parallel_divisor(Path *path); +- +- +- /* +-@@ -5222,6 +5226,58 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals) +- } +- +- +-+void +-+set_foreign_rows_estimate(PlannerInfo *root, RelOptInfo *rel) +-+{ +-+ if (set_foreign_rows_estimate_hook) +-+ (*set_foreign_rows_estimate_hook) (root, rel); +-+ else +-+ rel->rows = 1000; /* entirely bogus default estimate */ +-+} +-+ +-+/* +-+ * set_baserel_rows_estimate +-+ * Set the rows estimate for the given base relation. +-+ * +-+ * Rows is the estimated number of output tuples after applying +-+ * restriction clauses. +-+ * +-+ * To support loadable plugins that monitor or modify cardinality estimation, +-+ * we provide a hook variable that lets a plugin get control before and +-+ * after the cardinality estimation. +-+ * The hook must set rel->rows. +-+ */ +-+void +-+set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel) +-+{ +-+ if (set_baserel_rows_estimate_hook) +-+ (*set_baserel_rows_estimate_hook) (root, rel); +-+ else +-+ set_baserel_rows_estimate_standard(root, rel); +-+} +-+ +-+/* +-+ * set_baserel_rows_estimate +-+ * Set the rows estimate for the given base relation. +-+ * +-+ * Rows is the estimated number of output tuples after applying +-+ * restriction clauses. +-+ */ +-+void +-+set_baserel_rows_estimate_standard(PlannerInfo *root, RelOptInfo *rel) +-+{ +-+ double nrows; +-+ +-+ nrows = rel->tuples * +-+ clauselist_selectivity(root, +-+ rel->baserestrictinfo, +-+ 0, +-+ JOIN_INNER, +-+ NULL); +-+ +-+ rel->rows = clamp_row_est(nrows); +-+} +-+ +- /* +- * set_baserel_size_estimates +- * Set the size estimates for the given base relation. +-@@ -5238,19 +5294,10 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals) +- void +- set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) +- { +-- double nrows; +-- +- /* Should only be applied to base relations */ +- Assert(rel->relid > 0); +- +-- nrows = rel->tuples * +-- clauselist_selectivity(root, +-- rel->baserestrictinfo, +-- 0, +-- JOIN_INNER, +-- NULL); +-- +-- rel->rows = clamp_row_est(nrows); +-+ set_baserel_rows_estimate(root, rel); +- +- cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); +- +-@@ -5261,13 +5308,33 @@ set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) +- * get_parameterized_baserel_size +- * Make a size estimate for a parameterized scan of a base relation. +- * +-+ * To support loadable plugins that monitor or modify cardinality estimation, +-+ * we provide a hook variable that lets a plugin get control before and +-+ * after the cardinality estimation. +-+ */ +-+double +-+get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, +-+ List *param_clauses) +-+{ +-+ if (get_parameterized_baserel_size_hook) +-+ return (*get_parameterized_baserel_size_hook) (root, rel, +-+ param_clauses); +-+ else +-+ return get_parameterized_baserel_size_standard(root, rel, +-+ param_clauses); +-+} +-+ +-+/* +-+ * get_parameterized_baserel_size_standard +-+ * Make a size estimate for a parameterized scan of a base relation. +-+ * +- * 'param_clauses' lists the additional join clauses to be used. +- * +- * set_baserel_size_estimates must have been applied already. +- */ +- double +--get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, +-- List *param_clauses) +-+get_parameterized_baserel_size_standard(PlannerInfo *root, RelOptInfo *rel, +-+ List *param_clauses) +- { +- List *allclauses; +- double nrows; +-@@ -5296,6 +5363,36 @@ get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, +- * set_joinrel_size_estimates +- * Set the size estimates for the given join relation. +- * +-+ * To support loadable plugins that monitor or modify cardinality estimation, +-+ * we provide a hook variable that lets a plugin get control before and +-+ * after the cardinality estimation. +-+ * The hook must set rel->rows value. +-+ */ +-+void +-+set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, +-+ RelOptInfo *outer_rel, +-+ RelOptInfo *inner_rel, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrictlist) +-+{ +-+ if (set_joinrel_size_estimates_hook) +-+ (*set_joinrel_size_estimates_hook) (root, rel, +-+ outer_rel, +-+ inner_rel, +-+ sjinfo, +-+ restrictlist); +-+ else +-+ set_joinrel_size_estimates_standard(root, rel, +-+ outer_rel, +-+ inner_rel, +-+ sjinfo, +-+ restrictlist); +-+} +-+ +-+/* +-+ * set_joinrel_size_estimates_standard +-+ * Set the size estimates for the given join relation. +-+ * +- * The rel's targetlist must have been constructed already, and a +- * restriction clause list that matches the given component rels must +- * be provided. +-@@ -5315,11 +5412,11 @@ get_parameterized_baserel_size(PlannerInfo *root, RelOptInfo *rel, +- * build_joinrel_tlist, and baserestrictcost is not used for join rels. +- */ +- void +--set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, +-- RelOptInfo *outer_rel, +-- RelOptInfo *inner_rel, +-- SpecialJoinInfo *sjinfo, +-- List *restrictlist) +-+set_joinrel_size_estimates_standard(PlannerInfo *root, RelOptInfo *rel, +-+ RelOptInfo *outer_rel, +-+ RelOptInfo *inner_rel, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrictlist) +- { +- rel->rows = calc_joinrel_size_estimate(root, +- rel, +-@@ -5335,6 +5432,35 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, +- * get_parameterized_joinrel_size +- * Make a size estimate for a parameterized scan of a join relation. +- * +-+ * To support loadable plugins that monitor or modify cardinality estimation, +-+ * we provide a hook variable that lets a plugin get control before and +-+ * after the cardinality estimation. +-+ */ +-+double +-+get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, +-+ Path *outer_path, +-+ Path *inner_path, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrict_clauses) +-+{ +-+ if (get_parameterized_joinrel_size_hook) +-+ return (*get_parameterized_joinrel_size_hook) (root, rel, +-+ outer_path, +-+ inner_path, +-+ sjinfo, +-+ restrict_clauses); +-+ else +-+ return get_parameterized_joinrel_size_standard(root, rel, +-+ outer_path, +-+ inner_path, +-+ sjinfo, +-+ restrict_clauses); +-+} +-+ +-+/* +-+ * get_parameterized_joinrel_size_standard +-+ * Make a size estimate for a parameterized scan of a join relation. +-+ * +- * 'rel' is the joinrel under consideration. +- * 'outer_path', 'inner_path' are (probably also parameterized) Paths that +- * produce the relations being joined. +-@@ -5347,11 +5473,11 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, +- * set_joinrel_size_estimates must have been applied already. +- */ +- double +--get_parameterized_joinrel_size(PlannerInfo *root, RelOptInfo *rel, +-- Path *outer_path, +-- Path *inner_path, +-- SpecialJoinInfo *sjinfo, +-- List *restrict_clauses) +-+get_parameterized_joinrel_size_standard(PlannerInfo *root, RelOptInfo *rel, +-+ Path *outer_path, +-+ Path *inner_path, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrict_clauses) +- { +- double nrows; +- +-@@ -6066,7 +6192,7 @@ set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel) +- /* Should only be applied to base relations */ +- Assert(rel->relid > 0); +- +-- rel->rows = 1000; /* entirely bogus default estimate */ +-+ set_foreign_rows_estimate(root, rel); +- +- cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); +- +-@@ -6359,7 +6485,7 @@ page_size(double tuples, int width) +- * Estimate the fraction of the work that each worker will do given the +- * number of workers budgeted for the path. +- */ +--static double +-+double +- get_parallel_divisor(Path *path) +- { +- double parallel_divisor = path->parallel_workers; +-diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c +-index 6b64c4a362d..4e44babc0a2 100644 +---- a/src/backend/optimizer/plan/createplan.c +-+++ b/src/backend/optimizer/plan/createplan.c +-@@ -71,6 +71,7 @@ +- #define CP_LABEL_TLIST 0x0004 /* tlist must contain sortgrouprefs */ +- #define CP_IGNORE_TLIST 0x0008 /* caller will replace tlist */ +- +-+create_plan_hook_type create_plan_hook = NULL; +- +- static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path, +- int flags); +-@@ -548,6 +549,10 @@ create_plan_recurse(PlannerInfo *root, Path *best_path, int flags) +- break; +- } +- +-+ if (create_plan_hook) +-+ /* Give an extension a chance to do something */ +-+ (*create_plan_hook)(root, best_path, &plan); +-+ +- return plan; +- } +- +-@@ -5414,6 +5419,7 @@ copy_generic_path_info(Plan *dest, Path *src) +- dest->plan_width = src->pathtarget->width; +- dest->parallel_aware = src->parallel_aware; +- dest->parallel_safe = src->parallel_safe; +-+ dest->ext_nodes = NIL; +- } +- +- /* +-diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c +-index 032818423f6..a5c7e71b724 100644 +---- a/src/backend/optimizer/plan/planner.c +-+++ b/src/backend/optimizer/plan/planner.c +-@@ -142,7 +142,8 @@ static List *extract_rollup_sets(List *groupingSets); +- static List *reorder_grouping_sets(List *groupingSets, List *sortclause); +- static void standard_qp_callback(PlannerInfo *root, void *extra); +- static double get_number_of_groups(PlannerInfo *root, +-- double path_rows, +-+ Path *subpath, +-+ RelOptInfo *grouped_rel, +- grouping_sets_data *gd, +- List *target_list); +- static RelOptInfo *create_grouping_paths(PlannerInfo *root, +-@@ -3531,7 +3532,8 @@ standard_qp_callback(PlannerInfo *root, void *extra) +- */ +- static double +- get_number_of_groups(PlannerInfo *root, +-- double path_rows, +-+ Path *subpath, +-+ RelOptInfo *grouped_rel, +- grouping_sets_data *gd, +- List *target_list) +- { +-@@ -3568,7 +3570,7 @@ get_number_of_groups(PlannerInfo *root, +- GroupingSetData *gs = lfirst_node(GroupingSetData, lc3); +- double numGroups = estimate_num_groups(root, +- groupExprs, +-- path_rows, +-+ subpath->rows, +- &gset, +- NULL); +- +-@@ -3594,7 +3596,7 @@ get_number_of_groups(PlannerInfo *root, +- GroupingSetData *gs = lfirst_node(GroupingSetData, lc2); +- double numGroups = estimate_num_groups(root, +- groupExprs, +-- path_rows, +-+ subpath->rows, +- &gset, +- NULL); +- +-@@ -3611,8 +3613,8 @@ get_number_of_groups(PlannerInfo *root, +- groupExprs = get_sortgrouplist_exprs(root->processed_groupClause, +- target_list); +- +-- dNumGroups = estimate_num_groups(root, groupExprs, path_rows, +-- NULL, NULL); +-+ dNumGroups = estimate_num_groups_ext(root, groupExprs, subpath, +-+ grouped_rel, NULL, NULL); +- } +- } +- else if (parse->groupingSets) +-@@ -4002,7 +4004,8 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, +- * Estimate number of groups. +- */ +- dNumGroups = get_number_of_groups(root, +-- cheapest_path->rows, +-+ cheapest_path, +-+ grouped_rel, +- gd, +- extra->targetList); +- +-@@ -7207,13 +7210,15 @@ create_partial_grouping_paths(PlannerInfo *root, +- if (cheapest_total_path != NULL) +- dNumPartialGroups = +- get_number_of_groups(root, +-- cheapest_total_path->rows, +-+ cheapest_total_path, +-+ partially_grouped_rel, +- gd, +- extra->targetList); +- if (cheapest_partial_path != NULL) +- dNumPartialPartialGroups = +- get_number_of_groups(root, +-- cheapest_partial_path->rows, +-+ cheapest_partial_path, +-+ partially_grouped_rel, +- gd, +- extra->targetList); +- +-diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c +-index e05b21c884e..5805136b70f 100644 +---- a/src/backend/optimizer/util/relnode.c +-+++ b/src/backend/optimizer/util/relnode.c +-@@ -286,6 +286,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) +- rel->all_partrels = NULL; +- rel->partexprs = NULL; +- rel->nullable_partexprs = NULL; +-+ rel->ext_nodes = NULL; +- +- /* +- * Pass assorted information down the inheritance hierarchy. +-@@ -422,7 +423,6 @@ find_base_rel(PlannerInfo *root, int relid) +- if (rel) +- return rel; +- } +-- +- elog(ERROR, "no relation entry for relid %d", relid); +- +- return NULL; /* keep compiler quiet */ +-@@ -768,6 +768,7 @@ build_join_rel(PlannerInfo *root, +- joinrel->all_partrels = NULL; +- joinrel->partexprs = NULL; +- joinrel->nullable_partexprs = NULL; +-+ joinrel->ext_nodes = NULL; +- +- /* Compute information relevant to the foreign relations. */ +- set_foreign_rel_properties(joinrel, outer_rel, inner_rel); +-@@ -962,6 +963,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, +- joinrel->all_partrels = NULL; +- joinrel->partexprs = NULL; +- joinrel->nullable_partexprs = NULL; +-+ joinrel->ext_nodes = NULL; +- +- /* Compute information relevant to foreign relations. */ +- set_foreign_rel_properties(joinrel, outer_rel, inner_rel); +-@@ -1542,6 +1544,7 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel) +- } +- +- +-+set_parampathinfo_postinit_hook_type parampathinfo_postinit_hook = NULL; +- /* +- * get_baserel_parampathinfo +- * Get the ParamPathInfo for a parameterized path for a base relation, +-@@ -1634,6 +1637,10 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, +- ppi->ppi_rows = rows; +- ppi->ppi_clauses = pclauses; +- ppi->ppi_serials = pserials; +-+ +-+ if (parampathinfo_postinit_hook) +-+ (*parampathinfo_postinit_hook)(ppi); +-+ +- baserel->ppilist = lappend(baserel->ppilist, ppi); +- +- return ppi; +-@@ -1888,6 +1895,10 @@ get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer) +- ppi->ppi_rows = 0; +- ppi->ppi_clauses = NIL; +- ppi->ppi_serials = NULL; +-+ +-+ if (parampathinfo_postinit_hook) +-+ (*parampathinfo_postinit_hook)(ppi); +-+ +- appendrel->ppilist = lappend(appendrel->ppilist, ppi); +- +- return ppi; +-diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c +-index 5f5d7959d8e..20f63aae589 100644 +---- a/src/backend/utils/adt/selfuncs.c +-+++ b/src/backend/utils/adt/selfuncs.c +-@@ -146,6 +146,7 @@ +- /* Hooks for plugins to get control when we ask for stats */ +- get_relation_stats_hook_type get_relation_stats_hook = NULL; +- get_index_stats_hook_type get_index_stats_hook = NULL; +-+estimate_num_groups_hook_type estimate_num_groups_hook = NULL; +- +- static double eqsel_internal(PG_FUNCTION_ARGS, bool negate); +- static double eqjoinsel_inner(Oid opfuncoid, Oid collation, +-@@ -3341,6 +3342,20 @@ add_unique_group_var(PlannerInfo *root, List *varinfos, +- return varinfos; +- } +- +-+double +-+estimate_num_groups_ext(PlannerInfo *root, List *groupExprs, Path *subpath, +-+ RelOptInfo *grouped_rel, List **pgset, +-+ EstimationInfo *estinfo) +-+{ +-+ double input_rows = subpath->rows; +-+ +-+ if (estimate_num_groups_hook != NULL) +-+ return (*estimate_num_groups_hook)(root, groupExprs, subpath, grouped_rel, +-+ pgset, estinfo); +-+ +-+ return estimate_num_groups(root, groupExprs, input_rows, pgset, estinfo); +-+} +-+ +- /* +- * estimate_num_groups - Estimate number of groups in a grouped query +- * +-diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h +-index 9b8b351d9a2..f49233826af 100644 +---- a/src/include/commands/explain.h +-+++ b/src/include/commands/explain.h +-@@ -85,6 +85,18 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook; +- typedef const char *(*explain_get_index_name_hook_type) (Oid indexId); +- extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook; +- +-+/* Hook for plugins to get control in ExplainOnePlan() */ +-+typedef void (*ExplainOnePlan_hook_type) (PlannedStmt *plannedstmt, IntoClause *into, +-+ ExplainState *es, const char *queryString, +-+ ParamListInfo params, const instr_time *planduration, +-+ QueryEnvironment *queryEnv); +-+extern PGDLLIMPORT ExplainOnePlan_hook_type ExplainOnePlan_hook; +-+ +-+/* Explain a node info */ +-+typedef void (*ExplainOneNode_hook_type) (ExplainState *es, +-+ PlanState *ps, +-+ Plan *plan); +-+extern PGDLLIMPORT ExplainOneNode_hook_type ExplainOneNode_hook; +- +- extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, +- ParamListInfo params, DestReceiver *dest); +-diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h +-index 14ef296ab72..b1316b8f791 100644 +---- a/src/include/nodes/pathnodes.h +-+++ b/src/include/nodes/pathnodes.h +-@@ -1039,6 +1039,16 @@ typedef struct RelOptInfo +- List **partexprs pg_node_attr(read_write_ignore); +- /* Nullable partition key expressions */ +- List **nullable_partexprs pg_node_attr(read_write_ignore); +-+ +-+ /* For Adaptive optimization DEBUG purposes */ +-+ double predicted_cardinality; +-+ int fss_hash; +-+ +-+ /* +-+ * At this list an extension can add additional nodes to pass an info along +-+ * the planning and executing stages. +-+ */ +-+ List *ext_nodes; +- } RelOptInfo; +- +- /* +-@@ -1569,6 +1579,10 @@ typedef struct ParamPathInfo +- Cardinality ppi_rows; /* estimated number of result tuples */ +- List *ppi_clauses; /* join clauses available from outer rels */ +- Bitmapset *ppi_serials; /* set of rinfo_serial for enforced quals */ +-+ +-+ /* AQO DEBUG purposes */ +-+ double predicted_ppi_rows; +-+ double fss_ppi_hash; +- } ParamPathInfo; +- +- +-diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h +-index 1aeeaec95e1..308f38214a3 100644 +---- a/src/include/nodes/plannodes.h +-+++ b/src/include/nodes/plannodes.h +-@@ -169,6 +169,9 @@ typedef struct Plan +- */ +- Bitmapset *extParam; +- Bitmapset *allParam; +-+ +-+ /* Additional field for an extension purposes. */ +-+ List *ext_nodes; +- } Plan; +- +- /* ---------------- +-diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h +-index b1c51a4e70f..1cb601e3b27 100644 +---- a/src/include/optimizer/cost.h +-+++ b/src/include/optimizer/cost.h +-@@ -41,6 +41,37 @@ typedef enum +- } ConstraintExclusionType; +- +- +-+/* Hook for plugins to get control of cardinality estimation */ +-+typedef void (*set_baserel_rows_estimate_hook_type) (PlannerInfo *root, +-+ RelOptInfo *rel); +-+typedef void (*set_foreign_rows_estimate_hook_type) (PlannerInfo *root, +-+ RelOptInfo *rel); +-+extern PGDLLIMPORT set_baserel_rows_estimate_hook_type +-+ set_baserel_rows_estimate_hook; +-+extern PGDLLIMPORT set_foreign_rows_estimate_hook_type +-+ set_foreign_rows_estimate_hook; +-+typedef double (*get_parameterized_baserel_size_hook_type) (PlannerInfo *root, +-+ RelOptInfo *rel, +-+ List *param_clauses); +-+extern PGDLLIMPORT get_parameterized_baserel_size_hook_type +-+ get_parameterized_baserel_size_hook; +-+typedef double (*get_parameterized_joinrel_size_hook_type) (PlannerInfo *root, +-+ RelOptInfo *rel, +-+ Path *outer_path, +-+ Path *inner_path, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrict_clauses); +-+extern PGDLLIMPORT get_parameterized_joinrel_size_hook_type +-+ get_parameterized_joinrel_size_hook; +-+typedef void (*set_joinrel_size_estimates_hook_type) (PlannerInfo *root, +-+ RelOptInfo *rel, +-+ RelOptInfo *outer_rel, +-+ RelOptInfo *inner_rel, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrictlist); +-+extern PGDLLIMPORT set_joinrel_size_estimates_hook_type +-+ set_joinrel_size_estimates_hook; +-+ +- /* +- * prototypes for costsize.c +- * routines to compute costs and sizes +-@@ -184,10 +215,22 @@ extern void compute_semi_anti_join_factors(PlannerInfo *root, +- SpecialJoinInfo *sjinfo, +- List *restrictlist, +- SemiAntiJoinFactors *semifactors); +-+extern void set_foreign_rows_estimate(PlannerInfo *root, RelOptInfo *rel); +-+extern void set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel); +-+extern void set_baserel_rows_estimate_standard(PlannerInfo *root, RelOptInfo *rel); +- extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel); +- extern double get_parameterized_baserel_size(PlannerInfo *root, +- RelOptInfo *rel, +- List *param_clauses); +-+extern double get_parameterized_baserel_size_standard(PlannerInfo *root, +-+ RelOptInfo *rel, +-+ List *param_clauses); +-+extern double get_parameterized_joinrel_size_standard(PlannerInfo *root, +-+ RelOptInfo *rel, +-+ Path *outer_path, +-+ Path *inner_path, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrict_clauses); +- extern double get_parameterized_joinrel_size(PlannerInfo *root, +- RelOptInfo *rel, +- Path *outer_path, +-@@ -199,6 +242,11 @@ extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel, +- RelOptInfo *inner_rel, +- SpecialJoinInfo *sjinfo, +- List *restrictlist); +-+extern void set_joinrel_size_estimates_standard(PlannerInfo *root, RelOptInfo *rel, +-+ RelOptInfo *outer_rel, +-+ RelOptInfo *inner_rel, +-+ SpecialJoinInfo *sjinfo, +-+ List *restrictlist); +- extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel); +- extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel); +- extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel); +-@@ -212,5 +260,6 @@ extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *targ +- extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel, +- Path *bitmapqual, double loop_count, +- Cost *cost_p, double *tuples_p); +-+extern double get_parallel_divisor(Path *path); +- +- #endif /* COST_H */ +-diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h +-index 112e7c23d4e..8397995e183 100644 +---- a/src/include/optimizer/pathnode.h +-+++ b/src/include/optimizer/pathnode.h +-@@ -18,6 +18,10 @@ +- #include "nodes/pathnodes.h" +- +- +-+typedef void (*set_parampathinfo_postinit_hook_type) (ParamPathInfo *ppi); +-+ +-+extern PGDLLIMPORT set_parampathinfo_postinit_hook_type parampathinfo_postinit_hook; +-+ +- /* +- * prototypes for pathnode.c +- */ +-diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h +-index aafc1737921..d520d8d5475 100644 +---- a/src/include/optimizer/planmain.h +-+++ b/src/include/optimizer/planmain.h +-@@ -24,6 +24,12 @@ extern PGDLLIMPORT double cursor_tuple_fraction; +- /* query_planner callback to compute query_pathkeys */ +- typedef void (*query_pathkeys_callback) (PlannerInfo *root, void *extra); +- +-+ +-+/* Hook for plugins to get control in ExecutorRun() */ +-+typedef void (*create_plan_hook_type) (PlannerInfo *root, +-+ Path *best_path, +-+ Plan **plan); +-+extern PGDLLIMPORT create_plan_hook_type create_plan_hook; +- /* +- * prototypes for plan/planmain.c +- */ +-diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h +-index f2563ad1cb3..0beac5f3139 100644 +---- a/src/include/utils/selfuncs.h +-+++ b/src/include/utils/selfuncs.h +-@@ -147,6 +147,13 @@ typedef bool (*get_index_stats_hook_type) (PlannerInfo *root, +- AttrNumber indexattnum, +- VariableStatData *vardata); +- extern PGDLLIMPORT get_index_stats_hook_type get_index_stats_hook; +-+typedef double (*estimate_num_groups_hook_type) (PlannerInfo *root, +-+ List *groupExprs, +-+ Path *subpath, +-+ RelOptInfo *grouped_rel, +-+ List **pgset, +-+ EstimationInfo *estinfo); +-+extern PGDLLIMPORT estimate_num_groups_hook_type estimate_num_groups_hook; +- +- /* Functions in selfuncs.c */ +- +-@@ -213,6 +220,9 @@ extern void mergejoinscansel(PlannerInfo *root, Node *clause, +- Selectivity *leftstart, Selectivity *leftend, +- Selectivity *rightstart, Selectivity *rightend); +- +-+extern double estimate_num_groups_ext(PlannerInfo *root, List *groupExprs, +-+ Path *subpath, RelOptInfo *grouped_rel, +-+ List **pgset, EstimationInfo *estinfo); +- extern double estimate_num_groups(PlannerInfo *root, List *groupExprs, +- double input_rows, List **pgset, +- EstimationInfo *estinfo); diff --git a/expected/aqo_fdw.out b/expected/aqo_fdw.out index d72f85da..69c1b132 100644 --- a/expected/aqo_fdw.out +++ b/expected/aqo_fdw.out @@ -258,27 +258,20 @@ WHERE str NOT LIKE '%Memory%'; DROP TABLE main, local_main_p0, local_main_p1; DROP TABLE ref, local_ref_p0, local_ref_p1; ---ALTER SERVER loopback OPTIONS (DROP fdw_tuple_cost); +ALTER SERVER loopback OPTIONS (DROP fdw_tuple_cost); reset enable_partitionwise_join; -- TODO: Non-mergejoinable join condition. EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) SELECT * FROM frgn AS a, frgn AS b WHERE a.x Foreign Scan on frgn a (actual rows=1 loops=1) - AQO not used - -> Materialize (actual rows=1 loops=1) - AQO not used - -> Foreign Scan on frgn b (actual rows=1 loops=1) - AQO not used + Relations: (frgn a) INNER JOIN (frgn b) Using aqo: true AQO mode: LEARN JOINS: 0 -(13 rows) +(6 rows) SELECT str FROM expln(' EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE) diff --git a/expected/unsupported.out b/expected/unsupported.out index c0752fb2..a1a6f4ae 100644 --- a/expected/unsupported.out +++ b/expected/unsupported.out @@ -203,7 +203,7 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) ---------------------------------------------------------- Aggregate (actual rows=1 loops=1) AQO not used - InitPlan 1 + InitPlan 1 (returns $0) -> Aggregate (actual rows=1 loops=1) AQO not used -> Seq Scan on t t_1 (actual rows=50 loops=1) @@ -212,7 +212,7 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) Rows Removed by Filter: 950 -> Seq Scan on t (actual rows=50 loops=1) AQO: rows=50, error=0% - Filter: ((x)::numeric = (InitPlan 1).col1) + Filter: ((x)::numeric = $0) Rows Removed by Filter: 950 Using aqo: true AQO mode: LEARN @@ -253,13 +253,13 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21) OR x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21); - QUERY PLAN -------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------- Aggregate (actual rows=1 loops=1) AQO not used -> Seq Scan on t (actual rows=0 loops=1) AQO not used - Filter: (((x)::numeric = (SubPlan 1)) OR (ANY ((x)::numeric = (SubPlan 2).col1))) + Filter: (((x)::numeric = (SubPlan 1)) OR (SubPlan 2)) Rows Removed by Filter: 1000 SubPlan 1 -> Aggregate (actual rows=1 loops=1000) @@ -284,13 +284,13 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21) OR x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21); - QUERY PLAN -------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------- Aggregate (actual rows=1 loops=1) AQO not used -> Seq Scan on t (actual rows=0 loops=1) AQO: rows=1, error=100% - Filter: (((x)::numeric = (SubPlan 1)) OR (ANY ((x)::numeric = (SubPlan 2).col1))) + Filter: (((x)::numeric = (SubPlan 1)) OR (SubPlan 2)) Rows Removed by Filter: 1000 SubPlan 1 -> Aggregate (actual rows=1 loops=1000) @@ -316,13 +316,13 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 22) OR x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 23); - QUERY PLAN -------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------- Aggregate (actual rows=1 loops=1) AQO not used -> Seq Scan on t (actual rows=0 loops=1) AQO: rows=1, error=100% - Filter: (((x)::numeric = (SubPlan 1)) OR (ANY ((x)::numeric = (SubPlan 2).col1))) + Filter: (((x)::numeric = (SubPlan 1)) OR (SubPlan 2)) Rows Removed by Filter: 1000 SubPlan 1 -> Aggregate (actual rows=1 loops=1000)