]> granicus.if.org Git - postgresql/commitdiff
New C function: bms_add_range
authorRobert Haas <rhaas@postgresql.org>
Wed, 29 Nov 2017 22:06:14 +0000 (17:06 -0500)
committerRobert Haas <rhaas@postgresql.org>
Wed, 29 Nov 2017 22:12:05 +0000 (17:12 -0500)
This will be used by pending patches to improve partition pruning.

Amit Langote and Kyotaro Horiguchi, per a suggestion from David
Rowley.  Review and testing of the larger patch set of which this is a
part by Ashutosh Bapat, David Rowley, Dilip Kumar, Jesper Pedersen,
Rajkumar Raghuwanshi, Beena Emerson, Amul Sul, and Kyotaro Horiguchi.

Discussion: http://postgr.es/m/098b9c71-1915-1a2a-8d52-1a7a50ce79e8@lab.ntt.co.jp

src/backend/nodes/bitmapset.c
src/include/nodes/bitmapset.h

index d4b82c63055f95c6b0826303c46b447568c43e78..e5096e01a798d4ac2b602d45a1c901143ae3c875 100644 (file)
@@ -784,6 +784,78 @@ bms_add_members(Bitmapset *a, const Bitmapset *b)
        return result;
 }
 
+/*
+ * bms_add_range
+ *             Add members in the range of 'lower' to 'upper' to the set.
+ *
+ * Note this could also be done by calling bms_add_member in a loop, however,
+ * using this function will be faster when the range is large as we work with
+ * at the bitmapword level rather than at bit level.
+ */
+Bitmapset *
+bms_add_range(Bitmapset *a, int lower, int upper)
+{
+       int                     lwordnum,
+                               lbitnum,
+                               uwordnum,
+                               ushiftbits,
+                               wordnum;
+
+       if (lower < 0 || upper < 0)
+               elog(ERROR, "negative bitmapset member not allowed");
+       if (lower > upper)
+               elog(ERROR, "lower range must not be above upper range");
+       uwordnum = WORDNUM(upper);
+
+       if (a == NULL)
+       {
+               a = (Bitmapset *) palloc0(BITMAPSET_SIZE(uwordnum + 1));
+               a->nwords = uwordnum + 1;
+       }
+
+       /* ensure we have enough words to store the upper bit */
+       else if (uwordnum >= a->nwords)
+       {
+               int                     oldnwords = a->nwords;
+               int                     i;
+
+               a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1));
+               a->nwords = uwordnum + 1;
+               /* zero out the enlarged portion */
+               for (i = oldnwords; i < a->nwords; i++)
+                       a->words[i] = 0;
+       }
+
+       wordnum = lwordnum = WORDNUM(lower);
+
+       lbitnum = BITNUM(lower);
+       ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(upper) + 1);
+
+       /*
+        * Special case when lwordnum is the same as uwordnum we must perform the
+        * upper and lower masking on the word.
+        */
+       if (lwordnum == uwordnum)
+       {
+               a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
+                                                         & (~(bitmapword) 0) >> ushiftbits;
+       }
+       else
+       {
+               /* turn on lbitnum and all bits left of it */
+               a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
+
+               /* turn on all bits for any intermediate words */
+               while (wordnum < uwordnum)
+                       a->words[wordnum++] = ~(bitmapword) 0;
+
+               /* turn on upper's bit and all bits right of it. */
+               a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
+       }
+
+       return a;
+}
+
 /*
  * bms_int_members - like bms_intersect, but left input is recycled
  */
index aa3fb253c27fd85efb410c07f1d4482788b198fc..3b62a977751558d59ae2df1b97be75b7babf228f 100644 (file)
@@ -90,6 +90,7 @@ extern bool bms_is_empty(const Bitmapset *a);
 extern Bitmapset *bms_add_member(Bitmapset *a, int x);
 extern Bitmapset *bms_del_member(Bitmapset *a, int x);
 extern Bitmapset *bms_add_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_add_range(Bitmapset *a, int lower, int upper);
 extern Bitmapset *bms_int_members(Bitmapset *a, const Bitmapset *b);
 extern Bitmapset *bms_del_members(Bitmapset *a, const Bitmapset *b);
 extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b);