diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index e59f38b6ce0..329419c38d9 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -38,8 +38,6 @@ static EquivalenceMember *add_eq_member(EquivalenceClass *ec, JoinDomain *jdomain, EquivalenceMember *parent, Oid datatype); -static void add_eq_source(PlannerInfo *root, EquivalenceClass *ec, - RestrictInfo *rinfo); static void add_eq_derive(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo); static bool is_exprlist_member(Expr *node, List *exprs); @@ -78,6 +76,49 @@ static Bitmapset *get_eclass_indexes_for_relids(PlannerInfo *root, static Bitmapset *get_common_eclass_indexes(PlannerInfo *root, Relids relids1, Relids relids2); +/* + * add_eq_source - add 'rinfo' in eq_sources for this 'ec' + */ +void +add_eq_source(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo) +{ + int source_idx = list_length(root->eq_sources); + int i; + + ec->ec_source_indexes = bms_add_member(ec->ec_source_indexes, source_idx); + root->eq_sources = lappend(root->eq_sources, rinfo); + + i = -1; + while ((i = bms_next_member(rinfo->clause_relids, i)) >= 0) + { + RangeTblEntry *rte = root->simple_rte_array[i]; + + rte->eclass_source_indexes = bms_add_member(rte->eclass_source_indexes, + source_idx); + } +} + +/* + * add_eq_derive - add 'rinfo' in eq_derives for this 'ec' + */ +static void +add_eq_derive(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo) +{ + int derive_idx = list_length(root->eq_derives); + int i; + + ec->ec_derive_indexes = bms_add_member(ec->ec_derive_indexes, derive_idx); + root->eq_derives = lappend(root->eq_derives, rinfo); + + i = -1; + while ((i = bms_next_member(rinfo->clause_relids, i)) >= 0) + { + RangeTblEntry *rte = root->simple_rte_array[i]; + + rte->eclass_derive_indexes = bms_add_member(rte->eclass_derive_indexes, + derive_idx); + } +} /* * process_equivalence @@ -561,51 +602,6 @@ add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, return em; } -/* - * add_eq_source - add 'rinfo' in eq_sources for this 'ec' - */ -static void -add_eq_source(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo) -{ - int source_idx = list_length(root->eq_sources); - int i; - - ec->ec_source_indexes = bms_add_member(ec->ec_source_indexes, source_idx); - root->eq_sources = lappend(root->eq_sources, rinfo); - - i = -1; - while ((i = bms_next_member(rinfo->clause_relids, i)) >= 0) - { - RangeTblEntry *rte = root->simple_rte_array[i]; - - rte->eclass_source_indexes = bms_add_member(rte->eclass_source_indexes, - source_idx); - } -} - -/* - * add_eq_derive - add 'rinfo' in eq_derives for this 'ec' - */ -static void -add_eq_derive(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo) -{ - int derive_idx = list_length(root->eq_derives); - int i; - - ec->ec_derive_indexes = bms_add_member(ec->ec_derive_indexes, derive_idx); - root->eq_derives = lappend(root->eq_derives, rinfo); - - i = -1; - while ((i = bms_next_member(rinfo->clause_relids, i)) >= 0) - { - RangeTblEntry *rte = root->simple_rte_array[i]; - - rte->eclass_derive_indexes = bms_add_member(rte->eclass_derive_indexes, - derive_idx); - } -} - - /* * get_eclass_for_sort_expr * Given an expression and opfamily/collation info, find an existing @@ -3398,18 +3394,6 @@ get_ec_source_indexes(PlannerInfo *root, EquivalenceClass *ec, Relids relids) rel_esis = bms_add_members(rel_esis, rte->eclass_source_indexes); } -#ifdef USE_ASSERT_CHECKING - /* verify the results look sane */ - i = -1; - while ((i = bms_next_member(rel_esis, i)) >= 0) - { - RestrictInfo *rinfo = list_nth_node(RestrictInfo, root->eq_sources, - i); - - Assert(bms_overlap(relids, rinfo->clause_relids)); - } -#endif - /* bitwise-AND to leave only the ones for this EquivalenceClass */ return bms_int_members(rel_esis, ec->ec_source_indexes); } diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 0298c26166f..92dcbbdf2e0 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -61,7 +61,7 @@ static void remove_leftjoinrel_from_query(PlannerInfo *root, int relid, SpecialJoinInfo *sjinfo); static void remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid); -static void remove_rel_from_eclass(EquivalenceClass *ec, +static void remove_rel_from_eclass(PlannerInfo *root, EquivalenceClass *ec, int relid, int ojrelid); static List *remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved); static bool rel_supports_distinctness(PlannerInfo *root, RelOptInfo *rel); @@ -578,7 +578,7 @@ remove_leftjoinrel_from_query(PlannerInfo *root, int relid, if (bms_is_member(relid, ec->ec_relids) || bms_is_member(ojrelid, ec->ec_relids)) - remove_rel_from_eclass(ec, relid, ojrelid); + remove_rel_from_eclass(root, ec, relid, ojrelid); } /* @@ -663,7 +663,7 @@ remove_rel_from_restrictinfo(RestrictInfo *rinfo, int relid, int ojrelid) * level(s). */ static void -remove_rel_from_eclass(EquivalenceClass *ec, int relid, int ojrelid) +remove_rel_from_eclass(PlannerInfo *root, EquivalenceClass *ec, int relid, int ojrelid) { ListCell *lc; int i; @@ -1530,6 +1530,24 @@ replace_relid(Relids relids, int oldId, int newId) return relids; } +void +del_eq_derives(PlannerInfo *root, EquivalenceClass *ec) +{ + int i = -1; + + while ((i = bms_next_member(ec->ec_derive_indexes, i)) >= 0) + { + /* + * Can't delete the element because we would need to rebuild all + * the eq_derives indexes. But add a nuke to detect potential problems. + */ + list_nth_cell(root->eq_derives, i)->ptr_value = NULL; + } + bms_free(ec->ec_derive_indexes); + ec->ec_derive_indexes = NULL; +} + + /* * Update EC members to point to the remaining relation instead of the removed * one, removing duplicates. @@ -1553,10 +1571,11 @@ replace_relid(Relids relids, int oldId, int newId) * delete them. */ static void -update_eclasses(EquivalenceClass *ec, int from, int to) +update_eclass(PlannerInfo *root, EquivalenceClass *ec, int from, int to) { List *new_members = NIL; List *new_sources = NIL; + int i = -1; ListCell *lc; ListCell *lc1; @@ -1595,16 +1614,13 @@ update_eclasses(EquivalenceClass *ec, int from, int to) new_members = lappend(new_members, em); } - list_free(ec->ec_members); - ec->ec_members = new_members; - - list_free(ec->ec_derives); - ec->ec_derives = NULL; + del_eq_derives(root, ec); /* Update EC source expressions */ - foreach(lc, ec->ec_sources) + while ((i = bms_next_member(ec->ec_source_indexes, i)) > 0) { - RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc); + RestrictInfo *rinfo = list_nth_node(RestrictInfo, + root->eq_sources, i); bool is_redundant = false; if (!bms_is_member(from, rinfo->required_relids)) @@ -1638,8 +1654,21 @@ update_eclasses(EquivalenceClass *ec, int from, int to) new_sources = lappend(new_sources, rinfo); } - list_free(ec->ec_sources); - ec->ec_sources = new_sources; + i=-1; + + while ((i = bms_next_member(ec->ec_source_indexes, i)) > 0) + { + list_nth_cell(root->eq_sources, i)->ptr_value = NULL; + } + bms_free(ec->ec_source_indexes); + ec->ec_source_indexes = NULL; + + foreach(lc, new_sources) + { + RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc); + add_eq_source(root, ec, rinfo); + } + ec->ec_relids = replace_relid(ec->ec_relids, from, to); } @@ -1817,7 +1846,7 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark, { EquivalenceClass *ec = (EquivalenceClass *) list_nth(root->eq_classes, i); - update_eclasses(ec, toRemove->relid, toKeep->relid); + update_eclass(root, ec, toRemove->relid, toKeep->relid); toKeep->eclass_indexes = bms_add_member(toKeep->eclass_indexes, i); } diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 469ca518571..83695e2f66f 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -111,6 +111,9 @@ extern bool have_join_order_restriction(PlannerInfo *root, extern bool have_dangerous_phv(PlannerInfo *root, Relids outer_relids, Relids inner_params); extern void mark_dummy_rel(RelOptInfo *rel); +extern void del_eq_derives(PlannerInfo *root, EquivalenceClass *ec); +extern void add_eq_source(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo); + /* * equivclass.c