From 6a1f91a0d6044fd65f18a3884c58daac30e10b3e Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Tue, 20 Aug 2024 15:35:16 +0900 Subject: [PATCH] Refresh upstream code copy with update_copied_funcs.pl This is required for the next release, to be in sync with the planner code pg_hint_plan depends on. Backpatch-through: 17 --- core.c | 121 +++++++++++++++++++++++++---------------- make_join_rel.c | 18 +----- pg_hint_plan.c | 5 +- update_copied_funcs.pl | 3 +- 4 files changed, 81 insertions(+), 66 deletions(-) diff --git a/core.c b/core.c index 950e1d5..c98cd2c 100644 --- a/core.c +++ b/core.c @@ -169,7 +169,8 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels) /* * Except for the topmost scan/join rel, consider gathering * partial paths. We'll do the same for the topmost scan/join rel - * once we know the final targetlist (see grouping_planner). + * once we know the final targetlist (see grouping_planner's and + * its call to apply_scanjoin_target_to_paths). */ if (!bms_equal(rel->relids, root->all_query_rels)) generate_useful_gather_paths(root, rel, false); @@ -178,7 +179,7 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels) set_cheapest(rel); #ifdef OPTIMIZER_DEBUG - debug_print_rel(root, rel); + pprint(rel); #endif } } @@ -258,6 +259,8 @@ join_search_one_level(PlannerInfo *root, int level) if (old_rel->joininfo != NIL || old_rel->has_eclass_joins || has_join_restriction(root, old_rel)) { + int first_rel; + /* * There are join clauses or join order restrictions relevant to * this rel, so consider joins between this rel and (only) those @@ -271,24 +274,12 @@ join_search_one_level(PlannerInfo *root, int level) * to each initial rel they don't already include but have a join * clause or restriction with. */ - List *other_rels_list; - ListCell *other_rels; - if (level == 2) /* consider remaining initial rels */ - { - other_rels_list = joinrels[level - 1]; - other_rels = lnext(other_rels_list, r); - } - else /* consider all initial rels */ - { - other_rels_list = joinrels[1]; - other_rels = list_head(other_rels_list); - } + first_rel = foreach_current_index(r) + 1; + else + first_rel = 0; - make_rels_by_clause_joins(root, - old_rel, - other_rels_list, - other_rels); + make_rels_by_clause_joins(root, old_rel, joinrels[1], first_rel); } else { @@ -332,8 +323,7 @@ join_search_one_level(PlannerInfo *root, int level) foreach(r, joinrels[k]) { RelOptInfo *old_rel = (RelOptInfo *) lfirst(r); - List *other_rels_list; - ListCell *other_rels; + int first_rel; ListCell *r2; /* @@ -345,19 +335,12 @@ join_search_one_level(PlannerInfo *root, int level) !has_join_restriction(root, old_rel)) continue; - if (k == other_level) - { - /* only consider remaining rels */ - other_rels_list = joinrels[k]; - other_rels = lnext(other_rels_list, r); - } + if (k == other_level) /* only consider remaining rels */ + first_rel = foreach_current_index(r) + 1; else - { - other_rels_list = joinrels[other_level]; - other_rels = list_head(other_rels_list); - } + first_rel = 0; - for_each_cell(r2, other_rels_list, other_rels) + for_each_from(r2, joinrels[other_level], first_rel) { RelOptInfo *new_rel = (RelOptInfo *) lfirst(r2); @@ -452,9 +435,8 @@ join_search_one_level(PlannerInfo *root, int level) * automatically ensures that each new joinrel is only added to the list once. * * 'old_rel' is the relation entry for the relation to be joined - * 'other_rels_list': a list containing the other - * rels to be considered for joining - * 'other_rels': the first cell to be considered + * 'other_rels': a list containing the other rels to be considered for joining + * 'first_rel_idx': the first rel to be considered in 'other_rels' * * Currently, this is only used with initial rels in other_rels, but it * will work for joining to joinrels too. @@ -462,12 +444,12 @@ join_search_one_level(PlannerInfo *root, int level) static void make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, - List *other_rels_list, - ListCell *other_rels) + List *other_rels, + int first_rel_idx) { ListCell *l; - for_each_cell(l, other_rels_list, other_rels) + for_each_from(l, other_rels, first_rel_idx) { RelOptInfo *other_rel = (RelOptInfo *) lfirst(l); @@ -942,6 +924,9 @@ restriction_is_constant_false(List *restrictlist, * Construct the SpecialJoinInfo for a child-join by translating * SpecialJoinInfo for the join between parents. left_relids and right_relids * are the relids of left and right side of the join respectively. + * + * If translations are added to or removed from this function, consider + * updating free_child_join_sjinfo() accordingly. */ static SpecialJoinInfo * build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, @@ -953,6 +938,14 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, AppendRelInfo **right_appinfos; int right_nappinfos; + /* Dummy SpecialJoinInfos can be created without any translation. */ + if (parent_sjinfo->jointype == JOIN_INNER) + { + Assert(parent_sjinfo->ojrelid == 0); + init_dummy_sjinfo(sjinfo, left_relids, right_relids); + return sjinfo; + } + memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo)); left_appinfos = find_appinfos_by_relids(root, left_relids, &left_nappinfos); @@ -1260,7 +1253,6 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, SpecialJoinInfo *child_sjinfo; List *child_restrictlist; RelOptInfo *child_joinrel; - Relids child_joinrelids; AppendRelInfo **appinfos; int nappinfos; @@ -1357,13 +1349,11 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_rel1->relids, child_rel2->relids); - /* Build correct join relids for child join */ - child_joinrelids = bms_union(child_rel1->relids, child_rel2->relids); - child_joinrelids = add_outer_joins_to_relids(root, child_joinrelids, - child_sjinfo, NULL); - /* Find the AppendRelInfo structures */ - appinfos = find_appinfos_by_relids(root, child_joinrelids, &nappinfos); + appinfos = find_appinfos_by_relids(root, + bms_union(child_rel1->relids, + child_rel2->relids), + &nappinfos); /* * Construct restrictions applicable to the child join from those @@ -1373,8 +1363,8 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, (List *) adjust_appendrel_attrs(root, (Node *) parent_restrictlist, nappinfos, appinfos); - pfree(appinfos); + /* Find or construct the child join's RelOptInfo */ child_joinrel = joinrel->part_rels[cnt_parts]; if (!child_joinrel) { @@ -1387,10 +1377,49 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, child_joinrel->relids); } - Assert(bms_equal(child_joinrel->relids, child_joinrelids)); + /* Assert we got the right one */ + Assert(bms_equal(child_joinrel->relids, + adjust_child_relids(joinrel->relids, + nappinfos, appinfos))); + /* And make paths for the child join */ populate_joinrel_with_paths(root, child_rel1, child_rel2, child_joinrel, child_sjinfo, child_restrictlist); + + pfree(appinfos); + free_child_join_sjinfo(child_sjinfo); + } +} + + +/* + * free_child_join_sjinfo + * Free memory consumed by a SpecialJoinInfo created by + * build_child_join_sjinfo() + * + * Only members that are translated copies of their counterpart in the parent + * SpecialJoinInfo are freed here. + */ +static void +free_child_join_sjinfo(SpecialJoinInfo *sjinfo) +{ + /* + * Dummy SpecialJoinInfos of inner joins do not have any translated fields + * and hence no fields that to be freed. + */ + if (sjinfo->jointype != JOIN_INNER) + { + bms_free(sjinfo->min_lefthand); + bms_free(sjinfo->min_righthand); + bms_free(sjinfo->syn_lefthand); + bms_free(sjinfo->syn_righthand); + + /* + * semi_rhs_exprs may in principle be freed, but a simple pfree() does + * not suffice, so we leave it alone. + */ } + + pfree(sjinfo); } diff --git a/make_join_rel.c b/make_join_rel.c index ac53690..4a5cf20 100644 --- a/make_join_rel.c +++ b/make_join_rel.c @@ -112,23 +112,7 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) if (sjinfo == NULL) { sjinfo = &sjinfo_data; - sjinfo->type = T_SpecialJoinInfo; - sjinfo->min_lefthand = rel1->relids; - sjinfo->min_righthand = rel2->relids; - sjinfo->syn_lefthand = rel1->relids; - sjinfo->syn_righthand = rel2->relids; - sjinfo->jointype = JOIN_INNER; - sjinfo->ojrelid = 0; - sjinfo->commute_above_l = NULL; - sjinfo->commute_above_r = NULL; - sjinfo->commute_below_l = NULL; - sjinfo->commute_below_r = NULL; - /* we don't bother trying to make the remaining fields valid */ - sjinfo->lhs_strict = false; - sjinfo->semi_can_btree = false; - sjinfo->semi_can_hash = false; - sjinfo->semi_operators = NIL; - sjinfo->semi_rhs_exprs = NIL; + init_dummy_sjinfo(sjinfo, rel1->relids, rel2->relids); } /* diff --git a/pg_hint_plan.c b/pg_hint_plan.c index 779d3ae..ff8aef2 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -493,14 +493,15 @@ void pg_hint_plan_set_rel_pathlist(PlannerInfo * root, RelOptInfo *rel, static void create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel); static void make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, - List *other_rels_list, - ListCell *other_rels); + List *other_rels, + int first_rel_idx); static void make_rels_by_clauseless_joins(PlannerInfo *root, RelOptInfo *old_rel, List *other_rels); static bool has_join_restriction(PlannerInfo *root, RelOptInfo *rel); static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); +static void free_child_join_sjinfo(SpecialJoinInfo *sjinfo); RelOptInfo *pg_hint_plan_make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2); diff --git a/update_copied_funcs.pl b/update_copied_funcs.pl index 4688710..18c9ea6 100755 --- a/update_copied_funcs.pl +++ b/update_copied_funcs.pl @@ -21,7 +21,8 @@ 'build_child_join_sjinfo', 'get_matching_part_pairs', 'compute_partition_bounds', - 'try_partitionwise_join'], + 'try_partitionwise_join', + 'free_child_join_sjinfo'], head => core_c_head()}, 'make_join_rel.c' => {protos => [],