diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index 26a0f872b3b9297d9dab75d3a5bf990f914f2fd8..c4e1d26a49d9c2707465d573d2f9d782a4a75302 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -524,6 +524,50 @@ bms_singleton_member(const Bitmapset *a) return result; } +/* + * bms_get_singleton_member + * + * Test whether the given set is a singleton. + * If so, set *member to the value of its sole member, and return TRUE. + * If not, return FALSE, without changing *member. + * + * This is more convenient and faster than calling bms_membership() and then + * bms_singleton_member(), if we don't care about distinguishing empty sets + * from multiple-member sets. + */ +bool +bms_get_singleton_member(const Bitmapset *a, int *member) +{ + int result = -1; + int nwords; + int wordnum; + + if (a == NULL) + return false; + nwords = a->nwords; + for (wordnum = 0; wordnum < nwords; wordnum++) + { + bitmapword w = a->words[wordnum]; + + if (w != 0) + { + if (result >= 0 || HAS_MULTIPLE_ONES(w)) + return false; + result = wordnum * BITS_PER_BITMAPWORD; + while ((w & 255) == 0) + { + w >>= 8; + result += 8; + } + result += rightmost_one_pos[w & 255]; + } + } + if (result < 0) + return false; + *member = result; + return true; +} + /* * bms_num_members - count members of set */ diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index e5dd58efe33417040d3f80ca6a9c9cdb39b358af..9919d27374f68ad400ad1cd32e1e63982aadbcf4 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -867,9 +867,8 @@ generate_base_implied_equalities_no_const(PlannerInfo *root, int relid; Assert(!cur_em->em_is_child); /* no children yet */ - if (bms_membership(cur_em->em_relids) != BMS_SINGLETON) + if (!bms_get_singleton_member(cur_em->em_relids, &relid)) continue; - relid = bms_singleton_member(cur_em->em_relids); Assert(relid < root->simple_rel_array_size); if (prev_ems[relid] != NULL) diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 773f8a458e22319656e6c9a54b88a0e954708cc9..e99d416e852a1a2497ae95a28db365f4888974a1 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -162,11 +162,12 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo) * going to be able to do anything with it. */ if (sjinfo->jointype != JOIN_LEFT || - sjinfo->delay_upper_joins || - bms_membership(sjinfo->min_righthand) != BMS_SINGLETON) + sjinfo->delay_upper_joins) + return false; + + if (!bms_get_singleton_member(sjinfo->min_righthand, &innerrelid)) return false; - innerrelid = bms_singleton_member(sjinfo->min_righthand); innerrel = find_base_rel(root, innerrelid); if (innerrel->reloptkind != RELOPT_BASEREL) diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c index 8d7c4feca465efe245c485c6c26925dc7bfcd158..36d19b84e88c266835cef35f9944e6da707e72b0 100644 --- a/src/backend/optimizer/util/placeholder.c +++ b/src/backend/optimizer/util/placeholder.c @@ -383,10 +383,10 @@ add_placeholders_to_base_rels(PlannerInfo *root) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); Relids eval_at = phinfo->ph_eval_at; + int varno; - if (bms_membership(eval_at) == BMS_SINGLETON) + if (bms_get_singleton_member(eval_at, &varno)) { - int varno = bms_singleton_member(eval_at); RelOptInfo *rel = find_base_rel(root, varno); /* add it to reltargetlist if needed above the rel scan level */ diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h index a78ff4886d61fca48d3d59444645c615bd7eaed8..a314192b71acdf9c59bf5cb702cb08e718f17535 100644 --- a/src/include/nodes/bitmapset.h +++ b/src/include/nodes/bitmapset.h @@ -72,6 +72,7 @@ extern bool bms_is_member(int x, const Bitmapset *a); extern bool bms_overlap(const Bitmapset *a, const Bitmapset *b); extern bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b); extern int bms_singleton_member(const Bitmapset *a); +extern bool bms_get_singleton_member(const Bitmapset *a, int *member); extern int bms_num_members(const Bitmapset *a); /* optimized tests when we don't need to know exact membership count: */