]> granicus.if.org Git - postgresql/commitdiff
Add bms_get_singleton_member(), and use it where appropriate.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 28 Nov 2014 19:16:24 +0000 (14:16 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 28 Nov 2014 19:16:24 +0000 (14:16 -0500)
This patch adds a function that replaces a bms_membership() test followed
by a bms_singleton_member() call, performing both the test and the
extraction of a singleton set's member in one scan of the bitmapset.
The performance advantage over the old way is probably minimal in current
usage, but it seems worthwhile on notational grounds anyway.

David Rowley

src/backend/nodes/bitmapset.c
src/backend/optimizer/path/equivclass.c
src/backend/optimizer/plan/analyzejoins.c
src/backend/optimizer/util/placeholder.c
src/include/nodes/bitmapset.h

index 26a0f872b3b9297d9dab75d3a5bf990f914f2fd8..c4e1d26a49d9c2707465d573d2f9d782a4a75302 100644 (file)
@@ -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
  */
index e5dd58efe33417040d3f80ca6a9c9cdb39b358af..9919d27374f68ad400ad1cd32e1e63982aadbcf4 100644 (file)
@@ -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)
index 773f8a458e22319656e6c9a54b88a0e954708cc9..e99d416e852a1a2497ae95a28db365f4888974a1 100644 (file)
@@ -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)
index 8d7c4feca465efe245c485c6c26925dc7bfcd158..36d19b84e88c266835cef35f9944e6da707e72b0 100644 (file)
@@ -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 */
index a78ff4886d61fca48d3d59444645c615bd7eaed8..a314192b71acdf9c59bf5cb702cb08e718f17535 100644 (file)
@@ -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: */