diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 5ace28eab0..7212f2d3bc 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -675,7 +675,10 @@ get_eclass_for_sort_expr(PlannerInfo *root, */ if (cur_em->em_is_child && !bms_equal(cur_em->em_relids, rel)) + { + verify_em_child(root, cur_em); continue; + } /* * If below an outer join, don't match constants: they're not as @@ -2002,7 +2005,10 @@ exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2) EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2); if (em->em_is_child) + { + verify_em_child(root, em); continue; /* ignore children here */ + } if (equal(item1, em->em_expr)) item1member = true; else if (equal(item2, em->em_expr)) @@ -2059,7 +2065,10 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root, Var *var; if (em->em_is_child) + { + verify_em_child(root, em); continue; /* ignore children here */ + } /* EM must be a Var, possibly with RelabelType */ var = (Var *) em->em_expr; @@ -2286,7 +2295,10 @@ generate_implied_equalities_for_column(PlannerInfo *root, RestrictInfo *rinfo; if (other_em->em_is_child) + { + verify_em_child(root, other_em); continue; /* ignore children here */ + } /* Make sure it'll be a join to a different rel */ if (other_em == cur_em || @@ -2386,6 +2398,21 @@ have_relevant_eclass_joinclause(PlannerInfo *root, return false; } +void +verify_em_child(PlannerInfo *root, EquivalenceMember *em) +{ + int relid; + Assert(em->em_is_child); + + relid = -1; + while ((relid = bms_next_member(em->em_relids, relid)) >= 0) + { + if (root->simple_rel_array[relid]->reloptkind == RELOPT_BASEREL) + elog(WARNING, "child EquivalenceMember skipped: %s", nodeToString(em->em_expr)); + } +} + + /* * has_relevant_eclass_joinclause @@ -2476,7 +2503,10 @@ eclass_useful_for_merging(PlannerInfo *root, EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc); if (cur_em->em_is_child) + { + verify_em_child(root, cur_em); continue; /* ignore children here */ + } if (!bms_overlap(cur_em->em_relids, relids)) return true; diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index ec66cb9c3c..27bff4a56d 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -717,7 +717,10 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, ListCell *k; if (sub_member->em_is_child) + { + verify_em_child(rel->subroot, sub_member); continue; /* ignore children here */ + } foreach(k, subquery_tlist) { @@ -1179,6 +1182,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root, if (!em->em_is_const && !em->em_is_child && !bms_overlap(em->em_relids, joinrel->relids)) score++; + else if (em->em_is_child) + verify_em_child(root, em); } ecs[necs] = oeclass; diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 28c4b53fea..56a7c69775 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -237,7 +237,7 @@ static MergeJoin *make_mergejoin(List *tlist, static Sort *make_sort(Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst); -static Plan *prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, +static Plan *prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, Relids relids, const AttrNumber *reqColIdx, bool adjust_tlist_in_place, @@ -246,10 +246,10 @@ static Plan *prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Oid **p_sortOperators, Oid **p_collations, bool **p_nullsFirst); -static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec, +static EquivalenceMember *find_ec_member_for_tle(PlannerInfo *root,EquivalenceClass *ec, TargetEntry *tle, Relids relids); -static Sort *make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, +static Sort *make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, Relids relids); static Sort *make_sort_from_groupcols(List *groupcls, AttrNumber *grpColIdx, @@ -266,7 +266,7 @@ static Group *make_group(List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Plan *lefttree); static Unique *make_unique_from_sortclauses(Plan *lefttree, List *distinctList); -static Unique *make_unique_from_pathkeys(Plan *lefttree, +static Unique *make_unique_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, int numCols); static Gather *make_gather(List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan); @@ -1147,7 +1147,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path) plan->righttree = NULL; /* Compute sort column info, and adjust MergeAppend's tlist as needed */ - (void) prepare_sort_from_pathkeys(plan, pathkeys, + (void) prepare_sort_from_pathkeys(root, plan, pathkeys, best_path->path.parent->relids, NULL, true, @@ -1177,7 +1177,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path) subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST); /* Compute sort column info, and adjust subplan's tlist as needed */ - subplan = prepare_sort_from_pathkeys(subplan, pathkeys, + subplan = prepare_sort_from_pathkeys(root, subplan, pathkeys, subpath->parent->relids, node->sortColIdx, false, @@ -1606,7 +1606,7 @@ create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path) Assert(pathkeys != NIL); /* Compute sort column info, and adjust subplan's tlist as needed */ - subplan = prepare_sort_from_pathkeys(subplan, pathkeys, + subplan = prepare_sort_from_pathkeys(root, subplan, pathkeys, best_path->subpath->parent->relids, gm_plan->sortColIdx, false, @@ -1788,7 +1788,7 @@ create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags) * relids. Thus, if this sort path is based on a child relation, we must * pass its relids. */ - plan = make_sort_from_pathkeys(subplan, best_path->path.pathkeys, + plan = make_sort_from_pathkeys(root, subplan, best_path->path.pathkeys, IS_OTHER_REL(best_path->subpath->parent) ? best_path->path.parent->relids : NULL); @@ -1853,7 +1853,7 @@ create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flag subplan = create_plan_recurse(root, best_path->subpath, flags | CP_LABEL_TLIST); - plan = make_unique_from_pathkeys(subplan, + plan = make_unique_from_pathkeys(root, subplan, best_path->path.pathkeys, best_path->numkeys); @@ -3879,7 +3879,7 @@ create_mergejoin_plan(PlannerInfo *root, if (best_path->outersortkeys) { Relids outer_relids = outer_path->parent->relids; - Sort *sort = make_sort_from_pathkeys(outer_plan, + Sort *sort = make_sort_from_pathkeys(root, outer_plan, best_path->outersortkeys, outer_relids); @@ -3893,7 +3893,7 @@ create_mergejoin_plan(PlannerInfo *root, if (best_path->innersortkeys) { Relids inner_relids = inner_path->parent->relids; - Sort *sort = make_sort_from_pathkeys(inner_plan, + Sort *sort = make_sort_from_pathkeys(root, inner_plan, best_path->innersortkeys, inner_relids); @@ -5604,7 +5604,7 @@ make_sort(Plan *lefttree, int numCols, * or a Result stacked atop lefttree). */ static Plan * -prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, +prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, Relids relids, const AttrNumber *reqColIdx, bool adjust_tlist_in_place, @@ -5671,7 +5671,7 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]); if (tle) { - em = find_ec_member_for_tle(ec, tle, relids); + em = find_ec_member_for_tle(root, ec, tle, relids); if (em) { /* found expr at right place in tlist */ @@ -5702,7 +5702,7 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, foreach(j, tlist) { tle = (TargetEntry *) lfirst(j); - em = find_ec_member_for_tle(ec, tle, relids); + em = find_ec_member_for_tle(root, ec, tle, relids); if (em) { /* found expr already in tlist */ @@ -5745,7 +5745,10 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, */ if (em->em_is_child && !bms_is_subset(em->em_relids, relids)) + { + verify_em_child(root, em); continue; + } sortexpr = em->em_expr; exprvars = pull_var_clause((Node *) sortexpr, @@ -5831,7 +5834,7 @@ prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, * Child EC members are ignored unless they belong to given 'relids'. */ static EquivalenceMember * -find_ec_member_for_tle(EquivalenceClass *ec, +find_ec_member_for_tle(PlannerInfo *root, EquivalenceClass *ec, TargetEntry *tle, Relids relids) { @@ -5860,7 +5863,10 @@ find_ec_member_for_tle(EquivalenceClass *ec, */ if (em->em_is_child && !bms_is_subset(em->em_relids, relids)) + { + verify_em_child(root, em); continue; + } /* Match if same expression (after stripping relabel) */ emexpr = em->em_expr; @@ -5883,7 +5889,7 @@ find_ec_member_for_tle(EquivalenceClass *ec, * 'relids' is the set of relations required by prepare_sort_from_pathkeys() */ static Sort * -make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids) +make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, Relids relids) { int numsortkeys; AttrNumber *sortColIdx; @@ -5892,7 +5898,7 @@ make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids) bool *nullsFirst; /* Compute sort column info, and adjust lefttree as needed */ - lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys, + lefttree = prepare_sort_from_pathkeys(root, lefttree, pathkeys, relids, NULL, false, @@ -6204,7 +6210,7 @@ make_unique_from_sortclauses(Plan *lefttree, List *distinctList) * as above, but use pathkeys to identify the sort columns and semantics */ static Unique * -make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols) +make_unique_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, int numCols) { Unique *node = makeNode(Unique); Plan *plan = &node->plan; @@ -6265,7 +6271,7 @@ make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols) foreach(j, plan->targetlist) { tle = (TargetEntry *) lfirst(j); - em = find_ec_member_for_tle(ec, tle, NULL); + em = find_ec_member_for_tle(root, ec, tle, NULL); if (em) { /* found expr already in tlist */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index cafde307ad..a3f34a5c8c 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -169,6 +169,7 @@ extern List *generate_implied_equalities_for_column(PlannerInfo *root, Relids prohibited_rels); extern bool have_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2); +extern void verify_em_child(PlannerInfo *root, EquivalenceMember *em); extern bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1); extern bool eclass_useful_for_merging(PlannerInfo *root,