diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index e5dd58efe33417040d3f80ca6a9c9cdb39b358af..c8fac1ad34da9a91d02253ce8ec982370b754ac6 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -2286,9 +2286,11 @@ has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1) * from actually being generated. */ bool -eclass_useful_for_merging(EquivalenceClass *eclass, +eclass_useful_for_merging(PlannerInfo *root, + EquivalenceClass *eclass, RelOptInfo *rel) { + Relids relids; ListCell *lc; Assert(!eclass->ec_merged); @@ -2306,8 +2308,14 @@ eclass_useful_for_merging(EquivalenceClass *eclass, * possibly-overoptimistic heuristic. */ + /* If specified rel is a child, we must consider the topmost parent rel */ + if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL) + relids = find_childrel_top_parent(root, rel)->relids; + else + relids = rel->relids; + /* If rel already includes all members of eclass, no point in searching */ - if (bms_is_subset(eclass->ec_relids, rel->relids)) + if (bms_is_subset(eclass->ec_relids, relids)) return false; /* To join, we need a member not in the given rel */ @@ -2318,7 +2326,7 @@ eclass_useful_for_merging(EquivalenceClass *eclass, if (cur_em->em_is_child) continue; /* ignore children here */ - if (!bms_overlap(cur_em->em_relids, rel->relids)) + 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 5d953dfb45ae1a4547f77a8e1341819726b2b9ef..412db777481d87d61e41fa5ad136d100adc559ed 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -1373,7 +1373,7 @@ pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys) * surely possible to generate a mergejoin clause using them. */ if (rel->has_eclass_joins && - eclass_useful_for_merging(pathkey->pk_eclass, rel)) + eclass_useful_for_merging(root, pathkey->pk_eclass, rel)) matched = true; else { diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 9b22fda1ef49c91fd572bb5322ce8c9e07e6fb1c..65b4d2936d250536e61c200a484f9baeb010d483 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -130,7 +130,8 @@ extern bool have_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2); extern bool has_relevant_eclass_joinclause(PlannerInfo *root, RelOptInfo *rel1); -extern bool eclass_useful_for_merging(EquivalenceClass *eclass, +extern bool eclass_useful_for_merging(PlannerInfo *root, + EquivalenceClass *eclass, RelOptInfo *rel); extern bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist); diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index 56e2c9951509ce6d131432df7ac96dc07994320e..89b6c1caf47e1d71677101c0a4f82275bf6cdefe 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1307,6 +1307,40 @@ DETAIL: drop cascades to table matest1 drop cascades to table matest2 drop cascades to table matest3 -- +-- Check that use of an index with an extraneous column doesn't produce +-- a plan with extraneous sorting +-- +create table matest0 (a int, b int, c int, d int); +create table matest1 () inherits(matest0); +create index matest0i on matest0 (b, c); +create index matest1i on matest1 (b, c); +set enable_nestloop = off; -- we want a plan with two MergeAppends +explain (costs off) +select t1.* from matest0 t1, matest0 t2 +where t1.b = t2.b and t2.c = t2.d +order by t1.b limit 10; + QUERY PLAN +------------------------------------------------------------------- + Limit + -> Merge Join + Merge Cond: (t1.b = t2.b) + -> Merge Append + Sort Key: t1.b + -> Index Scan using matest0i on matest0 t1 + -> Index Scan using matest1i on matest1 t1_1 + -> Materialize + -> Merge Append + Sort Key: t2.b + -> Index Scan using matest0i on matest0 t2 + Filter: (c = d) + -> Index Scan using matest1i on matest1 t2_1 + Filter: (c = d) +(14 rows) + +reset enable_nestloop; +drop table matest0 cascade; +NOTICE: drop cascades to table matest1 +-- -- Test merge-append for UNION ALL append relations -- set enable_seqscan = off; diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index 09bb7507ad9eafe7a1c03db05686f2f9dad30d18..793c216376858a69b3a0c3cfb7f662f0347a8b3c 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -402,6 +402,27 @@ reset enable_seqscan; drop table matest0 cascade; +-- +-- Check that use of an index with an extraneous column doesn't produce +-- a plan with extraneous sorting +-- + +create table matest0 (a int, b int, c int, d int); +create table matest1 () inherits(matest0); +create index matest0i on matest0 (b, c); +create index matest1i on matest1 (b, c); + +set enable_nestloop = off; -- we want a plan with two MergeAppends + +explain (costs off) +select t1.* from matest0 t1, matest0 t2 +where t1.b = t2.b and t2.c = t2.d +order by t1.b limit 10; + +reset enable_nestloop; + +drop table matest0 cascade; + -- -- Test merge-append for UNION ALL append relations --