From 55edee49819cac42b9f579391c9e3ea1eaa99e60 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 2 Mar 2026 17:13:02 +1300 Subject: [PATCH v1] Teach bitmapset.c to pass small sets by value. 1. The node system is slightly extended to recognize tagged pointers and infer the NodeTag. 2. Bitmapset encodes set of up to 31/63 bits as an immediate value. This fits the existing semantics of the bitmapset API, since set-modifying functions always return a new data structure (cf NULL for empty). XXX Highly experimental! May contain nuts. --- src/backend/nodes/bitmapset.c | 416 +++++++- src/include/nodes/nodes.h | 24 +- .../expected/test_bitmapset.out | 892 +++++++++++++++++- .../test_bitmapset/sql/test_bitmapset.sql | 150 +++ src/tools/pgindent/typedefs.list | 1 + 5 files changed, 1461 insertions(+), 22 deletions(-) diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index 786f343b3c9..f853a837da2 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -50,6 +50,132 @@ #define BITMAPSET_SIZE(nwords) \ (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword)) + +/* + * Sets that fit in one word with a small overhead are encoded in an + * "immediate" form with pass-by-value semantics. Immediate values carry a + * special tag in the lower NOTE_PTR_TAG_MASK_WIDTH bits, which must be zero + * for a real pointer due to alignment rules. This allows us to avoid a lot + * of small allocations when manipulating sets in the planner. + */ + +/* The highest word value that be converted to an immediate value. */ +#define BITMAPSET_IMMEDIATE_MAX_WORD \ + ((~(bitmapword) 0) >> NODE_PTR_TAG_MASK_WIDTH) +/* The highest bitnum that can be set in an immediate value. */ +#define BITMAPSET_IMMEDIATE_MAX_BITNO \ + ((sizeof(bitmapword) * 8) - NODE_PTR_TAG_MASK_WIDTH - 1) + +/* Temporary container used to "box" immediate values on the stack. */ +typedef union BitmapsetBoxed +{ + Bitmapset bms; + char buffer[offsetof(Bitmapset, words) + sizeof(bitmapword)]; +} BitmapsetBoxed; + +/* + * Check if a bitmapset is in 'immediate' form. This means it's not really a + * pointer, it's single word. + */ +static bool +bms_is_immediate(const Bitmapset *a) +{ + return (((uintptr_t) a) & NODE_PTR_TAG_MASK) == NODE_PTR_T_Bitmapset; +} + +static bitmapword +bms_immediate_to_word(const Bitmapset *a) +{ + return ((bitmapword) a) >> NODE_PTR_TAG_MASK_WIDTH; +} + +static bool +bms_word_fits_in_immediate(bitmapword aw) +{ + return aw <= BITMAPSET_IMMEDIATE_MAX_WORD; +} + +static bool +bms_is_one_word(const Bitmapset *a) +{ + return bms_is_immediate(a) || a->nwords == 1; +} + +static Bitmapset * +bms_word_to_immediate(bitmapword aw) +{ + Assert(bms_word_fits_in_immediate(aw)); + + if (aw == 0) + return NULL; + + aw <<= NODE_PTR_TAG_MASK_WIDTH; + aw |= NODE_PTR_T_Bitmapset; + return (Bitmapset *) aw; +} + +static Bitmapset * +bms_make_from_one_word(bitmapword aw) +{ + if (likely(bms_word_fits_in_immediate(aw))) + return bms_word_to_immediate(aw); + else + { + Bitmapset *result = (Bitmapset *) palloc(BITMAPSET_SIZE(1)); + + result->type = T_Bitmapset; + result->nwords = 1; + result->words[0] = aw; + return result; + } +} + +static bitmapword +bms_first_word(const Bitmapset *a) +{ + Assert(a != NULL); + return bms_is_immediate(a) ? bms_immediate_to_word(a) : a->words[0]; +} + +/* + * Convert immediate format to boxed format in a temporary object on the + * stack. In most interesting codepaths there is a direct handling of + * immediate values, but in a few places this trick is used to harmonize the + * immediate/non-immediate code. + */ +static Bitmapset * +bms_box(BitmapsetBoxed *box, const Bitmapset *a) +{ + box->bms.type = T_Bitmapset; + box->bms.nwords = 1; + box->bms.words[0] = bms_immediate_to_word(a); + return &box->bms; +} + +/* + * Whenever returning a Bitmapset that might have had some bits cleared, this + * should be used to check if it can be converted to immediate format. It's + * important to do this because several codepaths assume that non-immedate + * Bitmapsets must have a member > BITMAPSET_IMMEDIATE_MAX_BITNO. + */ +static Bitmapset * +bms_unbox_and_free_if_possible(Bitmapset *a) +{ + Assert(a == NULL || !bms_is_immediate(a)); + if (a && + a->nwords == 1 && + bms_word_fits_in_immediate(a->words[0])) + { + Bitmapset *result = bms_word_to_immediate(a->words[0]); + + pfree(a); + return result; + } + return a; +} + + + /*---------- * This is a well-known cute trick for isolating the rightmost one-bit * in a word. It assumes two's complement arithmetic. Consider any @@ -82,6 +208,10 @@ bms_is_valid_set(const Bitmapset *a) if (a == NULL) return true; + /* Tagged immediate values must have at least one other bit set. */ + if (bms_is_immediate(a)) + return bms_immediate_to_word(a) != 0; + /* check the node tag is set correctly. pfree'd pointer, maybe? */ if (!IsA(a, Bitmapset)) return false; @@ -115,6 +245,7 @@ bms_copy_and_free(Bitmapset *a) } #endif + /* * bms_copy - make a palloc'd copy of a bitmapset */ @@ -128,6 +259,8 @@ bms_copy(const Bitmapset *a) if (a == NULL) return NULL; + if (bms_is_immediate(a)) + return unconstify(Bitmapset *, a); size = BITMAPSET_SIZE(a->nwords); result = (Bitmapset *) palloc(size); @@ -156,6 +289,12 @@ bms_equal(const Bitmapset *a, const Bitmapset *b) else if (b == NULL) return false; + /* immediate values have equal pseudo-pointers */ + if (bms_is_immediate(a)) + return a == b; + else if (bms_is_immediate(b)) + return false; + /* can't be equal if the word counts don't match */ if (a->nwords != b->nwords) return false; @@ -193,6 +332,22 @@ bms_compare(const Bitmapset *a, const Bitmapset *b) else if (b == NULL) return +1; + /* handle immediate values */ + if (bms_is_immediate(a)) + { + if (bms_is_immediate(b)) + { + bitmapword aw = bms_immediate_to_word(a); + bitmapword bw = bms_immediate_to_word(b); + + return aw < bw ? -1 : aw == bw ? 0 : +1; + } + else + return -1; + } + else if (bms_is_immediate(b)) + return +1; + /* the set with the most words must be greater */ if (a->nwords != b->nwords) return (a->nwords > b->nwords) ? +1 : -1; @@ -218,11 +373,18 @@ bms_make_singleton(int x) Bitmapset *result; int wordnum, bitnum; + bitmapword word; if (x < 0) elog(ERROR, "negative bitmapset member not allowed"); + wordnum = WORDNUM(x); bitnum = BITNUM(x); + word = (bitmapword) 1 << bitnum; + + if (wordnum == 0 && bms_word_fits_in_immediate(word)) + return bms_word_to_immediate(word); + result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1)); result->type = T_Bitmapset; result->nwords = wordnum + 1; @@ -233,12 +395,12 @@ bms_make_singleton(int x) /* * bms_free - free a bitmapset * - * Same as pfree except for allowing NULL input + * Same as pfree except for allowing NULL and immediate inputs */ void bms_free(Bitmapset *a) { - if (a) + if (a && !bms_is_immediate(a)) pfree(a); } @@ -263,6 +425,26 @@ bms_union(const Bitmapset *a, const Bitmapset *b) return bms_copy(b); if (b == NULL) return bms_copy(a); + + /* Handle immediates. */ + if (bms_is_immediate(a)) + { + if (bms_is_one_word(b)) + return bms_make_from_one_word(bms_immediate_to_word(a) | + bms_first_word(b)); + /* b is bigger */ + result = bms_copy(b); + result->words[0] |= bms_immediate_to_word(a); + return result; + } + else if (bms_is_immediate(b)) + { + /* a is bigger */ + result = bms_copy(a); + result->words[0] |= bms_immediate_to_word(b); + return result; + } + /* Identify shorter and longer input; copy the longer one */ if (a->nwords <= b->nwords) { @@ -304,6 +486,15 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b) if (a == NULL || b == NULL) return NULL; + /* Handle immediate values. */ + if (bms_is_immediate(a) || bms_is_immediate(b)) + { + bitmapword aw = bms_first_word(a); + bitmapword bw = bms_first_word(b); + + return bms_make_from_one_word(aw & bw); + } + /* Identify shorter and longer input; copy the shorter one */ if (a->nwords <= b->nwords) { @@ -329,13 +520,13 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b) /* If we computed an empty result, we must return NULL */ if (lastnonzero == -1) { - pfree(result); + bms_free(result); return NULL; } /* get rid of trailing zero words */ result->nwords = lastnonzero + 1; - return result; + return bms_unbox_and_free_if_possible(result); } /* @@ -347,6 +538,7 @@ bms_difference(const Bitmapset *a, const Bitmapset *b) { Bitmapset *result; int i; + BitmapsetBoxed b_tmp; Assert(bms_is_valid_set(a)); Assert(bms_is_valid_set(b)); @@ -357,6 +549,17 @@ bms_difference(const Bitmapset *a, const Bitmapset *b) if (b == NULL) return bms_copy(a); + /* Handle immediate values, or fall back to boxing b. */ + if (bms_is_immediate(a)) + { + bitmapword aw = bms_immediate_to_word(a); + bitmapword bw = bms_first_word(b); + + return bms_make_from_one_word(aw & ~bw); + } + else if (bms_is_immediate(b)) + b = bms_box(&b_tmp, b); + /* * In Postgres' usage, an empty result is a very common case, so it's * worth optimizing for that by testing bms_nonempty_difference(). This @@ -402,7 +605,7 @@ bms_difference(const Bitmapset *a, const Bitmapset *b) Assert(result->nwords != 0); /* Need not check for empty result, since we handled that case above */ - return result; + return bms_unbox_and_free_if_possible(result); } /* @@ -422,6 +625,19 @@ bms_is_subset(const Bitmapset *a, const Bitmapset *b) if (b == NULL) return false; + /* Handle immediate values. */ + if (bms_is_immediate(a)) + { + bitmapword aw = bms_immediate_to_word(a); + bitmapword bw = bms_first_word(b); + + return (aw & ~bw) == 0; + } + else if (bms_is_immediate(b)) + { + return false; /* a must have a higher member */ + } + /* 'a' can't be a subset of 'b' if it contains more words */ if (a->nwords > b->nwords) return false; @@ -447,6 +663,8 @@ bms_subset_compare(const Bitmapset *a, const Bitmapset *b) BMS_Comparison result; int shortlen; int i; + BitmapsetBoxed a_tmp; + BitmapsetBoxed b_tmp; Assert(bms_is_valid_set(a)); Assert(bms_is_valid_set(b)); @@ -461,6 +679,12 @@ bms_subset_compare(const Bitmapset *a, const Bitmapset *b) if (b == NULL) return BMS_SUBSET2; + /* Handle immediate values. */ + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); + if (bms_is_immediate(b)) + b = bms_box(&b_tmp, b); + /* Check common words */ result = BMS_EQUAL; /* status so far */ shortlen = Min(a->nwords, b->nwords); @@ -520,6 +744,10 @@ bms_is_member(int x, const Bitmapset *a) if (a == NULL) return false; + if (bms_is_immediate(a)) + return x <= BITMAPSET_IMMEDIATE_MAX_BITNO && + (bms_immediate_to_word(a) & ((bitmapword) 1 << x)); + wordnum = WORDNUM(x); bitnum = BITNUM(x); if (wordnum >= a->nwords) @@ -542,6 +770,7 @@ bms_member_index(Bitmapset *a, int x) int wordnum; int result = 0; bitmapword mask; + BitmapsetBoxed a_tmp; Assert(bms_is_valid_set(a)); @@ -549,6 +778,9 @@ bms_member_index(Bitmapset *a, int x) if (!bms_is_member(x, a)) return -1; + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); + wordnum = WORDNUM(x); bitnum = BITNUM(x); @@ -583,6 +815,10 @@ bms_overlap(const Bitmapset *a, const Bitmapset *b) /* Handle cases where either input is NULL */ if (a == NULL || b == NULL) return false; + + if (bms_is_immediate(a) || bms_is_immediate(b)) + return bms_first_word(a) & bms_first_word(b); + /* Check words in common */ shortlen = Min(a->nwords, b->nwords); i = 0; @@ -603,12 +839,16 @@ bms_overlap_list(const Bitmapset *a, const List *b) ListCell *lc; int wordnum, bitnum; + BitmapsetBoxed a_tmp; Assert(bms_is_valid_set(a)); if (a == NULL || b == NIL) return false; + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); + foreach(lc, b) { int x = lfirst_int(lc); @@ -643,6 +883,12 @@ bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b) return false; if (b == NULL) return true; + + if (bms_is_immediate(a)) + return bms_immediate_to_word(a) & ~bms_first_word(b); + else if (bms_is_immediate(b)) + return true; /* a is bigger */ + /* if 'a' has more words then it must contain additional members */ if (a->nwords > b->nwords) return true; @@ -667,12 +913,16 @@ bms_singleton_member(const Bitmapset *a) int result = -1; int nwords; int wordnum; + BitmapsetBoxed a_tmp; Assert(bms_is_valid_set(a)); if (a == NULL) elog(ERROR, "bitmapset is empty"); + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); + nwords = a->nwords; wordnum = 0; do @@ -710,12 +960,16 @@ bms_get_singleton_member(const Bitmapset *a, int *member) int result = -1; int nwords; int wordnum; + BitmapsetBoxed a_tmp; Assert(bms_is_valid_set(a)); if (a == NULL) return false; + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); + nwords = a->nwords; wordnum = 0; do @@ -748,9 +1002,8 @@ bms_num_members(const Bitmapset *a) if (a == NULL) return 0; - /* fast-path for common case */ - if (a->nwords == 1) - return bmw_popcount(a->words[0]); + if (bms_is_immediate(a)) + return bmw_popcount(bms_immediate_to_word(a)); return pg_popcount((const char *) a->words, a->nwords * sizeof(bitmapword)); @@ -773,6 +1026,18 @@ bms_membership(const Bitmapset *a) if (a == NULL) return BMS_EMPTY_SET; + if (bms_is_immediate(a)) + { + int n = bmw_popcount(bms_immediate_to_word(a)); + + if (n == 0) + return BMS_EMPTY_SET; + else if (n == 1) + return BMS_SINGLETON; + else + return BMS_MULTIPLE; + } + nwords = a->nwords; wordnum = 0; do @@ -808,6 +1073,18 @@ bms_add_member(Bitmapset *a, int x) if (a == NULL) return bms_make_singleton(x); + if (bms_is_immediate(a)) + { + bitmapword aw = bms_immediate_to_word(a); + + if (x <= BITMAPSET_IMMEDIATE_MAX_BITNO) + return bms_word_to_immediate(aw | ((bitmapword) 1 << x)); + + a = bms_make_singleton(x); + a->words[0] |= aw; + return a; + } + wordnum = WORDNUM(x); bitnum = BITNUM(x); @@ -861,6 +1138,18 @@ bms_del_member(Bitmapset *a, int x) if (a == NULL) return NULL; + if (bms_is_immediate(a)) + { + if (x <= BITMAPSET_IMMEDIATE_MAX_BITNO) + { + bitmapword aw = bms_immediate_to_word(a); + + aw &= ~((bitmapword) 1 << x); + a = bms_word_to_immediate(aw); + } + return a; + } + wordnum = WORDNUM(x); bitnum = BITNUM(x); @@ -891,7 +1180,7 @@ bms_del_member(Bitmapset *a, int x) pfree(a); return NULL; } - return a; + return bms_unbox_and_free_if_possible(a); } /* @@ -919,6 +1208,11 @@ bms_add_members(Bitmapset *a, const Bitmapset *b) return a; } + + /* If the left input is immediate, call bms_union instead. */ + if (bms_is_immediate(a) || bms_is_immediate(b)) + return bms_union(a, b); + /* Identify shorter and longer input; copy the longer one if needed */ if (a->nwords < b->nwords) { @@ -938,13 +1232,13 @@ bms_add_members(Bitmapset *a, const Bitmapset *b) result->words[i] |= other->words[i]; } while (++i < otherlen); if (result != a) - pfree(a); + bms_free(a); #ifdef REALLOCATE_BITMAPSETS else result = bms_copy_and_free(result); #endif - return result; + return bms_unbox_and_free_if_possible(result); } /* @@ -964,10 +1258,18 @@ bms_replace_members(Bitmapset *a, const Bitmapset *b) return bms_copy(b); if (b == NULL) { - pfree(a); + bms_free(a); return NULL; } + if (bms_is_immediate(a)) + return bms_copy(b); + else if (bms_is_immediate(b)) + { + bms_free(a); + return unconstify(Bitmapset *, b); + } + if (a->nwords < b->nwords) a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords)); @@ -1030,6 +1332,26 @@ bms_add_range(Bitmapset *a, int lower, int upper) a->type = T_Bitmapset; a->nwords = uwordnum + 1; } + else if (bms_is_immediate(a)) + { + bitmapword aw = bms_immediate_to_word(a); + + if (upper <= BITMAPSET_IMMEDIATE_MAX_BITNO) + { + /* Immediate result. */ + for (int i = lower; i <= upper; ++i) + aw |= ((bitmapword) 1 << i); + return bms_word_to_immediate(aw); + } + else + { + /* Need more space. */ + a = (Bitmapset *) palloc0(BITMAPSET_SIZE(uwordnum + 1)); + a->type = T_Bitmapset; + a->nwords = uwordnum + 1; + a->words[0] = aw; + } + } else if (uwordnum >= a->nwords) { int oldnwords = a->nwords; @@ -1104,10 +1426,20 @@ bms_int_members(Bitmapset *a, const Bitmapset *b) return NULL; if (b == NULL) { - pfree(a); + bms_free(a); return NULL; } + /* If either is immediate, result is immediate or NULL. */ + if (bms_is_immediate(a) || bms_is_immediate(b)) + { + bitmapword aw = bms_first_word(a); + bitmapword bw = bms_first_word(b); + + bms_free(a); + return bms_make_from_one_word(aw & bw); + } + /* Intersect b into a; we need never copy */ shortlen = Min(a->nwords, b->nwords); lastnonzero = -1; @@ -1123,7 +1455,7 @@ bms_int_members(Bitmapset *a, const Bitmapset *b) /* If we computed an empty result, we must return NULL */ if (lastnonzero == -1) { - pfree(a); + bms_free(a); return NULL; } @@ -1145,6 +1477,7 @@ Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b) { int i; + BitmapsetBoxed b_tmp; Assert(bms_is_valid_set(a)); Assert(bms_is_valid_set(b)); @@ -1161,6 +1494,17 @@ bms_del_members(Bitmapset *a, const Bitmapset *b) return a; } + /* Handle immediate values, or box. */ + if (bms_is_immediate(a)) + { + bitmapword aw = bms_immediate_to_word(a); + bitmapword bw = bms_first_word(b); + + return bms_make_from_one_word(aw & ~bw); + } + else if (bms_is_immediate(b)) + b = bms_box(&b_tmp, b); + /* Remove b's bits from a; we need never copy */ if (a->nwords > b->nwords) { @@ -1192,7 +1536,7 @@ bms_del_members(Bitmapset *a, const Bitmapset *b) /* check if 'a' has become empty */ if (lastnonzero == -1) { - pfree(a); + bms_free(a); return NULL; } @@ -1204,7 +1548,7 @@ bms_del_members(Bitmapset *a, const Bitmapset *b) a = bms_copy_and_free(a); #endif - return a; + return bms_unbox_and_free_if_possible(a); } /* @@ -1238,6 +1582,25 @@ bms_join(Bitmapset *a, Bitmapset *b) return a; } + if (a == b) + return a; /* pure paranoia */ + + /* Handle immediates. */ + if (bms_is_immediate(a)) + { + if (bms_is_one_word(b)) + return bms_make_from_one_word(bms_immediate_to_word(a) | + bms_first_word(b)); + result = b; + result->words[0] |= bms_immediate_to_word(a); + return result; + } + else if (bms_is_immediate(b)) + { + result = a; + result->words[0] |= bms_immediate_to_word(b); + return result; + } /* Identify shorter and longer input; use longer one as result */ if (a->nwords < b->nwords) @@ -1257,8 +1620,6 @@ bms_join(Bitmapset *a, Bitmapset *b) { result->words[i] |= other->words[i]; } while (++i < otherlen); - if (other != result) /* pure paranoia */ - pfree(other); #ifdef REALLOCATE_BITMAPSETS result = bms_copy_and_free(result); @@ -1296,9 +1657,18 @@ bms_next_member(const Bitmapset *a, int prevbit) if (a == NULL) return -2; - nwords = a->nwords; + prevbit++; mask = (~(bitmapword) 0) << BITNUM(prevbit); + + if (bms_is_immediate(a)) + { + bitmapword w = bms_immediate_to_word(a) & mask; + + return w == 0 ? -2 : bmw_rightmost_one_pos(w); + } + + nwords = a->nwords; for (int wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++) { bitmapword w = a->words[wordnum]; @@ -1351,6 +1721,7 @@ bms_prev_member(const Bitmapset *a, int prevbit) { int ushiftbits; bitmapword mask; + BitmapsetBoxed a_tmp; Assert(bms_is_valid_set(a)); @@ -1361,6 +1732,9 @@ bms_prev_member(const Bitmapset *a, int prevbit) if (a == NULL || prevbit == 0) return -2; + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); + /* Validate callers didn't give us something out of range */ Assert(prevbit <= a->nwords * BITS_PER_BITMAPWORD); Assert(prevbit >= -1); @@ -1401,10 +1775,14 @@ bms_prev_member(const Bitmapset *a, int prevbit) uint32 bms_hash_value(const Bitmapset *a) { + BitmapsetBoxed a_tmp; + Assert(bms_is_valid_set(a)); if (a == NULL) return 0; /* All empty sets hash to 0 */ + if (bms_is_immediate(a)) + a = bms_box(&a_tmp, a); return DatumGetUInt32(hash_any((const unsigned char *) a->words, a->nwords * sizeof(bitmapword))); } diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 59a7df31aba..0e2a7c1e153 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -136,7 +136,29 @@ typedef struct Node NodeTag type; } Node; -#define nodeTag(nodeptr) (((const Node*)(nodeptr))->type) +/* + * The least significant bit(s) of a pointer to a Node should never be set, + * due to the rules of alignment. We can therefore mark immediate values that + * are meaningful to a given node type, with a scheme to map them back to a + * NodeTag value to find its functions. For now there is only one node type + * doing this, so a single bit suffices. + */ +#define NODE_PTR_TAG_MASK 0x1 +#define NODE_PTR_TAG_MASK_WIDTH 1 +#define NODE_PTR_T_Bitmapset 1 + +static inline NodeTag +nodeTag(const void *nodePtr) +{ + uintptr_t p = (uintptr_t) nodePtr; + int ptr_tag = p & NODE_PTR_TAG_MASK; + + /* XXX hard-coded for now */ + if (ptr_tag == NODE_PTR_T_Bitmapset) + return T_Bitmapset; + + return ((const Node *) nodePtr)->type; +} /* * newNode - diff --git a/src/test/modules/test_bitmapset/expected/test_bitmapset.out b/src/test/modules/test_bitmapset/expected/test_bitmapset.out index f75cb46b869..2d6114818df 100644 --- a/src/test/modules/test_bitmapset/expected/test_bitmapset.out +++ b/src/test/modules/test_bitmapset/expected/test_bitmapset.out @@ -39,12 +39,30 @@ SELECT test_bms_add_member('(b)', 10) AS result; (b 10) (1 row) +SELECT test_bms_add_member('(b)', 100) AS result; + result +--------- + (b 100) +(1 row) + SELECT test_bms_add_member('(b 5)', 10) AS result; result ---------- (b 5 10) (1 row) +SELECT test_bms_add_member('(b 100)', 10) AS result; + result +------------ + (b 10 100) +(1 row) + +SELECT test_bms_add_member('(b 10)', 100) AS result; + result +------------ + (b 10 100) +(1 row) + -- sort check SELECT test_bms_add_member('(b 10)', 5) AS result; result @@ -59,6 +77,12 @@ SELECT test_bms_add_member('(b 10)', 10) AS result; (b 10) (1 row) +SELECT test_bms_add_member('(b 100)', 100) AS result; + result +--------- + (b 100) +(1 row) + -- Test module check SELECT test_bms_add_member('(b)', NULL) AS result; result @@ -97,6 +121,24 @@ SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result; (b 3 5 7) (1 row) +SELECT test_bms_replace_members('(b 1 2 100)', '(b 3 5 7)') AS result; + result +----------- + (b 3 5 7) +(1 row) + +SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7 100)') AS result; + result +--------------- + (b 3 5 7 100) +(1 row) + +SELECT test_bms_replace_members('(b 1 2 100)', '(b 3 5 7 100)') AS result; + result +--------------- + (b 3 5 7 100) +(1 row) + -- Force repalloc() with larger set SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; result @@ -125,12 +167,48 @@ SELECT test_bms_del_member('(b 10)', 5) AS result; (b 10) (1 row) +SELECT test_bms_del_member('(b 63)', 5) AS result; + result +-------- + (b 63) +(1 row) + +SELECT test_bms_del_member('(b 63)', 63) AS result; + result +-------- + <> +(1 row) + SELECT test_bms_del_member('(b 1 2 3)', 2) AS result; result --------- (b 1 3) (1 row) +SELECT test_bms_del_member('(b 1 2 3 63)', 100) AS result; + result +-------------- + (b 1 2 3 63) +(1 row) + +SELECT test_bms_del_member('(b 1 2 3 63)', 63) AS result; + result +----------- + (b 1 2 3) +(1 row) + +SELECT test_bms_del_member('(b 1 2 3 100)', 100) AS result; + result +----------- + (b 1 2 3) +(1 row) + +SELECT test_bms_del_member('(b 1 2 3 100)', 3) AS result; + result +------------- + (b 1 2 100) +(1 row) + -- Reallocation check SELECT test_bms_del_member(test_bms_del_member('(b 0 31 32 63 64)', 32), 63) AS result; result @@ -259,6 +337,30 @@ SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result; (b 1 3 4 5) (1 row) +SELECT test_bms_join('(b 1 3 5 100)', NULL) AS result; + result +--------------- + (b 1 3 5 100) +(1 row) + +SELECT test_bms_join(NULL, '(b 2 4 6 100)') AS result; + result +--------------- + (b 2 4 6 100) +(1 row) + +SELECT test_bms_join('(b 1 3 5 100)', '(b 2 4 6)') AS result; + result +--------------------- + (b 1 2 3 4 5 6 100) +(1 row) + +SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5 100)') AS result; + result +----------------- + (b 1 3 4 5 100) +(1 row) + -- Force word count changes SELECT test_bms_join('(b 5)', '(b 100)') AS result; result @@ -299,6 +401,54 @@ SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result; (b 1 3 5 7) (1 row) +SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7 63)') AS result; + result +---------------- + (b 1 3 5 7 63) +(1 row) + +SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7 100)') AS result; + result +----------------- + (b 1 3 5 7 100) +(1 row) + +SELECT test_bms_union('(b 1 3 5 63)', '(b 3 5 7)') AS result; + result +---------------- + (b 1 3 5 7 63) +(1 row) + +SELECT test_bms_union('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; + result +---------------- + (b 1 3 5 7 63) +(1 row) + +SELECT test_bms_union('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; + result +-------------------- + (b 1 3 5 7 63 100) +(1 row) + +SELECT test_bms_union('(b 1 3 5 100)', '(b 3 5 7)') AS result; + result +----------------- + (b 1 3 5 7 100) +(1 row) + +SELECT test_bms_union('(b 1 3 5 100)', '(b 3 5 7 63)') AS result; + result +-------------------- + (b 1 3 5 7 63 100) +(1 row) + +SELECT test_bms_union('(b 1 3 5 100)', '(b 3 5 7 100)') AS result; + result +----------------- + (b 1 3 5 7 100) +(1 row) + -- Union with NULL SELECT test_bms_union('(b 1 3 5)', '(b)') AS result; result @@ -363,6 +513,36 @@ SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result; (b 3 5) (1 row) +SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7 63)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7 100)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_intersect('(b 1 3 5 63)', '(b 3 5 7)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_intersect('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; + result +------------ + (b 3 5 63) +(1 row) + +SELECT test_bms_intersect('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; + result +--------- + (b 3 5) +(1 row) + -- Disjoint sets SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result; result @@ -417,6 +597,54 @@ SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result; (b 3 5) (1 row) +SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7 63)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7 100)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5 63)', '(b 3 5 7)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; + result +------------ + (b 3 5 63) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5 100)', '(b 3 5 7)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5 100)', '(b 3 5 7 63)') AS result; + result +--------- + (b 3 5) +(1 row) + +SELECT test_bms_int_members('(b 1 3 5 100)', '(b 3 5 7 100)') AS result; + result +------------- + (b 3 5 100) +(1 row) + -- Disjoint sets SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result; result @@ -465,6 +693,54 @@ SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7)') AS result; (b 1) (1 row) +SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7 63)') AS result; + result +-------- + (b 1) +(1 row) + +SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7 100)') AS result; + result +-------- + (b 1) +(1 row) + +SELECT test_bms_difference('(b 1 3 5 63)', '(b 3 5 7)') AS result; + result +---------- + (b 1 63) +(1 row) + +SELECT test_bms_difference('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; + result +-------- + (b 1) +(1 row) + +SELECT test_bms_difference('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; + result +---------- + (b 1 63) +(1 row) + +SELECT test_bms_difference('(b 1 3 5 100)', '(b 3 5 7)') AS result; + result +----------- + (b 1 100) +(1 row) + +SELECT test_bms_difference('(b 1 3 5 100)', '(b 3 5 7 63)') AS result; + result +----------- + (b 1 100) +(1 row) + +SELECT test_bms_difference('(b 1 3 5 100)', '(b 3 5 7 100)') AS result; + result +-------- + (b 1) +(1 row) + -- Disjoint sets SELECT test_bms_difference('(b 1 3 5)', '(b 2 4 6)') AS result; result @@ -549,6 +825,30 @@ SELECT test_bms_is_member('(b 1 3 5)', 3) AS result; t (1 row) +SELECT test_bms_is_member('(b 1 3 5 63)', 2) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_member('(b 1 3 5 63)', 63) AS result; + result +-------- + t +(1 row) + +SELECT test_bms_is_member('(b 1 3 5 100)', 2) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_member('(b 1 3 5 100)', 100) AS result; + result +-------- + t +(1 row) + SELECT test_bms_is_member('(b)', 1) AS result; result -------- @@ -588,6 +888,42 @@ SELECT test_bms_member_index('(b 1 3 5)', 3) AS result; (1 row) -- Member index with various word positions +SELECT test_bms_member_index('(b 1 3 5 63)', 2) AS result; + result +-------- + -1 +(1 row) + +SELECT test_bms_member_index('(b 1 3 5 63)', 63) AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_member_index('(b 1 3 5 63)', 3) AS result; + result +-------- + 1 +(1 row) + +SELECT test_bms_member_index('(b 1 3 5 100)', 2) AS result; + result +-------- + -1 +(1 row) + +SELECT test_bms_member_index('(b 1 3 5 100)', 100) AS result; + result +-------- + 3 +(1 row) + +SELECT test_bms_member_index('(b 1 3 5 100)', 3) AS result; + result +-------- + 1 +(1 row) + SELECT test_bms_member_index('(b 100 200)', 100) AS result; result -------- @@ -632,6 +968,18 @@ SELECT test_bms_num_members('(b 2 4 6 8 10)') AS result; 5 (1 row) +SELECT test_bms_num_members('(b 2 4 6 8 63)') AS result; + result +-------- + 5 +(1 row) + +SELECT test_bms_num_members('(b 2 4 6 8 100)') AS result; + result +-------- + 5 +(1 row) + -- test_bms_equal() SELECT test_bms_equal('(b)', '(b)') AS result; result @@ -664,6 +1012,42 @@ SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; (1 row) -- Equal with different word counts +SELECT test_bms_equal('(b 1 3 5 63)', '(b 1 3 5)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal('(b 1 3 5 63)', '(b 1 3 5 63)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_equal('(b 1 3 5 63)', '(b 1 3 5 100)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal('(b 1 3 5 100)', '(b 1 3 5)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal('(b 1 3 5 100)', '(b 1 3 5 63)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_equal('(b 1 3 5 100)', '(b 1 3 5 100)') AS result; + result +-------- + t +(1 row) + SELECT test_bms_equal('(b 5)', '(b 100)') AS result; result -------- @@ -782,14 +1166,194 @@ SELECT test_bms_add_range('(b 1 10)', 5, 7) AS result; (1 row) -- Word boundary of 31 +SELECT test_bms_add_range('(b)', 30, 30) AS result; + result +-------- + (b 30) +(1 row) + +SELECT test_bms_add_range('(b)', 30, 31) AS result; + result +----------- + (b 30 31) +(1 row) + +SELECT test_bms_add_range('(b)', 30, 32) AS result; + result +-------------- + (b 30 31 32) +(1 row) + SELECT test_bms_add_range('(b)', 30, 34) AS result; result -------------------- (b 30 31 32 33 34) (1 row) --- Word boundary of 63 -SELECT test_bms_add_range('(b)', 62, 66) AS result; +SELECT test_bms_add_range('(b 30)', 30, 30) AS result; + result +-------- + (b 30) +(1 row) + +SELECT test_bms_add_range('(b 30)', 30, 31) AS result; + result +----------- + (b 30 31) +(1 row) + +SELECT test_bms_add_range('(b 30)', 30, 32) AS result; + result +-------------- + (b 30 31 32) +(1 row) + +SELECT test_bms_add_range('(b 30)', 30, 34) AS result; + result +-------------------- + (b 30 31 32 33 34) +(1 row) + +SELECT test_bms_add_range('(b 31)', 30, 30) AS result; + result +----------- + (b 30 31) +(1 row) + +SELECT test_bms_add_range('(b 31)', 30, 31) AS result; + result +----------- + (b 30 31) +(1 row) + +SELECT test_bms_add_range('(b 31)', 30, 32) AS result; + result +-------------- + (b 30 31 32) +(1 row) + +SELECT test_bms_add_range('(b 31)', 30, 34) AS result; + result +-------------------- + (b 30 31 32 33 34) +(1 row) + +SELECT test_bms_add_range('(b 32)', 30, 30) AS result; + result +----------- + (b 30 32) +(1 row) + +SELECT test_bms_add_range('(b 32)', 30, 31) AS result; + result +-------------- + (b 30 31 32) +(1 row) + +SELECT test_bms_add_range('(b 32)', 30, 32) AS result; + result +-------------- + (b 30 31 32) +(1 row) + +SELECT test_bms_add_range('(b 32)', 30, 34) AS result; + result +-------------------- + (b 30 31 32 33 34) +(1 row) + +-- Word boundary of 63 +SELECT test_bms_add_range('(b)', 62, 62) AS result; + result +-------- + (b 62) +(1 row) + +SELECT test_bms_add_range('(b)', 62, 63) AS result; + result +----------- + (b 62 63) +(1 row) + +SELECT test_bms_add_range('(b)', 62, 64) AS result; + result +-------------- + (b 62 63 64) +(1 row) + +SELECT test_bms_add_range('(b)', 62, 66) AS result; + result +-------------------- + (b 62 63 64 65 66) +(1 row) + +SELECT test_bms_add_range('(b 62)', 62, 62) AS result; + result +-------- + (b 62) +(1 row) + +SELECT test_bms_add_range('(b 62)', 62, 63) AS result; + result +----------- + (b 62 63) +(1 row) + +SELECT test_bms_add_range('(b 62)', 62, 64) AS result; + result +-------------- + (b 62 63 64) +(1 row) + +SELECT test_bms_add_range('(b 62)', 62, 66) AS result; + result +-------------------- + (b 62 63 64 65 66) +(1 row) + +SELECT test_bms_add_range('(b 63)', 62, 62) AS result; + result +----------- + (b 62 63) +(1 row) + +SELECT test_bms_add_range('(b 63)', 62, 63) AS result; + result +----------- + (b 62 63) +(1 row) + +SELECT test_bms_add_range('(b 63)', 62, 64) AS result; + result +-------------- + (b 62 63 64) +(1 row) + +SELECT test_bms_add_range('(b 63)', 62, 66) AS result; + result +-------------------- + (b 62 63 64 65 66) +(1 row) + +SELECT test_bms_add_range('(b 64)', 62, 62) AS result; + result +----------- + (b 62 64) +(1 row) + +SELECT test_bms_add_range('(b 64)', 62, 63) AS result; + result +-------------- + (b 62 63 64) +(1 row) + +SELECT test_bms_add_range('(b 64)', 62, 64) AS result; + result +-------------- + (b 62 63 64) +(1 row) + +SELECT test_bms_add_range('(b 64)', 62, 66) AS result; result -------------------- (b 62 63 64 65 66) @@ -879,6 +1443,24 @@ SELECT test_bms_membership('(b 1 2)') AS result; 2 (1 row) +SELECT test_bms_membership('(b 1 2 62)') AS result; + result +-------- + 2 +(1 row) + +SELECT test_bms_membership('(b 1 2 63)') AS result; + result +-------- + 2 +(1 row) + +SELECT test_bms_membership('(b 1 2 64)') AS result; + result +-------- + 2 +(1 row) + -- NULL input SELECT test_bms_membership(NULL) AS result; result @@ -916,6 +1498,30 @@ SELECT test_bms_singleton_member('(b 42)') AS result; 42 (1 row) +SELECT test_bms_singleton_member('(b 61 62)'); -- error +ERROR: bitmapset has multiple members +SELECT test_bms_singleton_member('(b 62 63)'); -- error +ERROR: bitmapset has multiple members +SELECT test_bms_singleton_member('(b 63 64)'); -- error +ERROR: bitmapset has multiple members +SELECT test_bms_singleton_member('(b 62)') AS result; + result +-------- + 62 +(1 row) + +SELECT test_bms_singleton_member('(b 63)') AS result; + result +-------- + 63 +(1 row) + +SELECT test_bms_singleton_member('(b 64)') AS result; + result +-------- + 64 +(1 row) + -- NULL input SELECT test_bms_singleton_member(NULL) AS result; result @@ -945,6 +1551,18 @@ SELECT test_bms_get_singleton_member('(b 3 6)') AS result; (1 row) -- Singletone, returns sole member +SELECT test_bms_get_singleton_member('(b 62)') AS result; + result +-------- + 62 +(1 row) + +SELECT test_bms_get_singleton_member('(b 63)') AS result; + result +-------- + 63 +(1 row) + SELECT test_bms_get_singleton_member('(b 400)') AS result; result -------- @@ -966,6 +1584,24 @@ SELECT test_bms_next_member('(b 5 10 15 20)', 5) AS result; 10 (1 row) +SELECT test_bms_next_member('(b 5 62)', 5) AS result; + result +-------- + 62 +(1 row) + +SELECT test_bms_next_member('(b 5 63)', 5) AS result; + result +-------- + 63 +(1 row) + +SELECT test_bms_next_member('(b 5 64)', 5) AS result; + result +-------- + 64 +(1 row) + -- Member past the end SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result; result @@ -973,6 +1609,24 @@ SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result; -2 (1 row) +SELECT test_bms_next_member('(b 5 10 15 62)', 62) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_next_member('(b 5 10 15 63)', 63) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_next_member('(b 5 10 15 64)', 64) AS result; + result +-------- + -2 +(1 row) + -- Empty set SELECT test_bms_next_member('(b)', -1) AS result; result @@ -987,6 +1641,24 @@ SELECT test_bms_prev_member('(b 5 10 15 20)', 21) AS result; 20 (1 row) +SELECT test_bms_prev_member('(b 5 10 15 62)', 63) AS result; + result +-------- + 62 +(1 row) + +SELECT test_bms_prev_member('(b 5 10 15 63)', 64) AS result; + result +-------- + 63 +(1 row) + +SELECT test_bms_prev_member('(b 5 10 15 64)', 65) AS result; + result +-------- + 64 +(1 row) + -- Penultimate member SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result; result @@ -994,6 +1666,24 @@ SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result; 15 (1 row) +SELECT test_bms_prev_member('(b 5 10 15 62)', 62) AS result; + result +-------- + 15 +(1 row) + +SELECT test_bms_prev_member('(b 5 10 15 63)', 63) AS result; + result +-------- + 15 +(1 row) + +SELECT test_bms_prev_member('(b 5 10 15 64)', 64) AS result; + result +-------- + 15 +(1 row) + -- Past beginning member SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result; result @@ -1001,6 +1691,24 @@ SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result; -2 (1 row) +SELECT test_bms_prev_member('(b 5 10 15 62)', 5) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_prev_member('(b 5 10 15 63)', 5) AS result; + result +-------- + -2 +(1 row) + +SELECT test_bms_prev_member('(b 5 10 15 64)', 5) AS result; + result +-------- + -2 +(1 row) + -- Empty set SELECT test_bms_prev_member('(b)', 100) AS result; result @@ -1015,6 +1723,24 @@ SELECT test_bms_prev_member('(b 0 63 64 127)', -1) AS result; 127 (1 row) +SELECT test_bms_prev_member('(b 0 62)', -1) AS result; + result +-------- + 62 +(1 row) + +SELECT test_bms_prev_member('(b 0 63)', -1) AS result; + result +-------- + 63 +(1 row) + +SELECT test_bms_prev_member('(b 0 64)', -1) AS result; + result +-------- + 64 +(1 row) + -- NULL inputs SELECT test_bms_next_member(NULL, 5) AS result; result @@ -1060,6 +1786,24 @@ SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS r t (1 row) +SELECT test_bms_hash_value('(b 1 3 62)') = test_bms_hash_value('(b 1 3 62)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_hash_value('(b 1 3 63)') = test_bms_hash_value('(b 1 3 63)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_hash_value('(b 1 3 64)') = test_bms_hash_value('(b 1 3 64)') AS result; + result +-------- + t +(1 row) + -- NULL input SELECT test_bms_hash_value(NULL) AS result; result @@ -1086,6 +1830,30 @@ SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result; f (1 row) +SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7 63)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6 63)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7 64)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6 64)') AS result; + result +-------- + f +(1 row) + -- NULL inputs SELECT test_bms_overlap('(b 5)', NULL) AS result; result @@ -1130,6 +1898,54 @@ SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result; f (1 row) +SELECT test_bms_is_subset('(b)', '(b 1 3 5 63)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5 63)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3 63)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_subset('(b 1 3)', '(b 2 4 63)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_subset('(b)', '(b 1 3 5 64)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5 64)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3 64)') AS result; + result +-------- + f +(1 row) + +SELECT test_bms_is_subset('(b 1 3)', '(b 2 4 64)') AS result; + result +-------- + f +(1 row) + SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31), test_bms_add_range(NULL, 0, 63)) AS result; result @@ -1321,6 +2137,18 @@ SELECT test_bms_copy('(b 1 3 5 7)') AS result; (b 1 3 5 7) (1 row) +SELECT test_bms_copy('(b 1 3 5 63)') AS result; + result +-------------- + (b 1 3 5 63) +(1 row) + +SELECT test_bms_copy('(b 1 3 5 64)') AS result; + result +-------------- + (b 1 3 5 64) +(1 row) + -- bms_add_members() SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result; result @@ -1334,6 +2162,12 @@ SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 7)') AS result; (b 1 2 3 5 7) (1 row) +SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 63)') AS result; + result +---------------- + (b 1 2 3 5 63) +(1 row) + SELECT test_bms_add_members('(b 1 3 5)', '(b 100 200 300)') AS result; result ----------------------- @@ -1481,6 +2315,42 @@ SELECT test_bms_overlap_list('(b 1 5)', ARRAY[6,7,8,9]) AS result; f (1 row) +SELECT test_bms_overlap_list('(b 63)', ARRAY[63]) AS result; + result +-------- + t +(1 row) + +SELECT test_bms_overlap_list('(b 63 64)', ARRAY[62,63]) AS result; + result +-------- + t +(1 row) + +SELECT test_bms_overlap_list('(b 64 65)', ARRAY[64,65,66]) AS result; + result +-------- + t +(1 row) + +SELECT test_bms_overlap_list('(b 63)', ARRAY[66]) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap_list('(b 63 64)', ARRAY[66]) AS result; + result +-------- + f +(1 row) + +SELECT test_bms_overlap_list('(b 64 65)', ARRAY[66]) AS result; + result +-------- + f +(1 row) + -- Empty list SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result; result @@ -1550,6 +2420,24 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result; (1 row) -- Difference with different word counts +SELECT test_bms_nonempty_difference('(b 5)', '(b 63)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_nonempty_difference('(b 63)', '(b 5)') AS result; + result +-------- + t +(1 row) + +SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 63)') AS result; + result +-------- + t +(1 row) + SELECT test_bms_nonempty_difference('(b 5)', '(b 100)') AS result; result -------- diff --git a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql index e75ab8f620a..7f238ed6f09 100644 --- a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql +++ b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql @@ -13,11 +13,15 @@ SELECT test_bms_make_singleton(NULL) AS result; SELECT test_bms_add_member('(b 1)', -1); -- error SELECT test_bms_add_member('(b)', -10); -- error SELECT test_bms_add_member('(b)', 10) AS result; +SELECT test_bms_add_member('(b)', 100) AS result; SELECT test_bms_add_member('(b 5)', 10) AS result; +SELECT test_bms_add_member('(b 100)', 10) AS result; +SELECT test_bms_add_member('(b 10)', 100) AS result; -- sort check SELECT test_bms_add_member('(b 10)', 5) AS result; -- idempotent change SELECT test_bms_add_member('(b 10)', 10) AS result; +SELECT test_bms_add_member('(b 100)', 100) AS result; -- Test module check SELECT test_bms_add_member('(b)', NULL) AS result; @@ -27,6 +31,9 @@ SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5 6)') AS result; SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5)') AS result; SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result; +SELECT test_bms_replace_members('(b 1 2 100)', '(b 3 5 7)') AS result; +SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7 100)') AS result; +SELECT test_bms_replace_members('(b 1 2 100)', '(b 3 5 7 100)') AS result; -- Force repalloc() with larger set SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; @@ -35,7 +42,13 @@ SELECT test_bms_del_member('(b)', -20); -- error SELECT test_bms_del_member('(b)', 10) AS result; SELECT test_bms_del_member('(b 10)', 10) AS result; SELECT test_bms_del_member('(b 10)', 5) AS result; +SELECT test_bms_del_member('(b 63)', 5) AS result; +SELECT test_bms_del_member('(b 63)', 63) AS result; SELECT test_bms_del_member('(b 1 2 3)', 2) AS result; +SELECT test_bms_del_member('(b 1 2 3 63)', 100) AS result; +SELECT test_bms_del_member('(b 1 2 3 63)', 63) AS result; +SELECT test_bms_del_member('(b 1 2 3 100)', 100) AS result; +SELECT test_bms_del_member('(b 1 2 3 100)', 3) AS result; -- Reallocation check SELECT test_bms_del_member(test_bms_del_member('(b 0 31 32 63 64)', 32), 63) AS result; -- Word boundary @@ -66,6 +79,10 @@ SELECT test_bms_join('(b 1 3 5)', NULL) AS result; SELECT test_bms_join(NULL, '(b 2 4 6)') AS result; SELECT test_bms_join('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result; +SELECT test_bms_join('(b 1 3 5 100)', NULL) AS result; +SELECT test_bms_join(NULL, '(b 2 4 6 100)') AS result; +SELECT test_bms_join('(b 1 3 5 100)', '(b 2 4 6)') AS result; +SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5 100)') AS result; -- Force word count changes SELECT test_bms_join('(b 5)', '(b 100)') AS result; SELECT test_bms_join('(b 1 2)', '(b 100 200 300)') AS result; @@ -77,6 +94,14 @@ SELECT test_bms_join(NULL, NULL) AS result; -- bms_union() -- Overlapping sets SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result; +SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7 63)') AS result; +SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7 100)') AS result; +SELECT test_bms_union('(b 1 3 5 63)', '(b 3 5 7)') AS result; +SELECT test_bms_union('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; +SELECT test_bms_union('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; +SELECT test_bms_union('(b 1 3 5 100)', '(b 3 5 7)') AS result; +SELECT test_bms_union('(b 1 3 5 100)', '(b 3 5 7 63)') AS result; +SELECT test_bms_union('(b 1 3 5 100)', '(b 3 5 7 100)') AS result; -- Union with NULL SELECT test_bms_union('(b 1 3 5)', '(b)') AS result; -- Union of empty with empty @@ -97,6 +122,11 @@ SELECT test_bms_union(NULL, NULL) AS result; -- bms_intersect() -- Overlapping sets SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result; +SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7 63)') AS result; +SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7 100)') AS result; +SELECT test_bms_intersect('(b 1 3 5 63)', '(b 3 5 7)') AS result; +SELECT test_bms_intersect('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; +SELECT test_bms_intersect('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; -- Disjoint sets SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result; -- Intersect with empty @@ -112,6 +142,14 @@ SELECT test_bms_intersect(NULL, NULL) AS result; -- bms_int_members() -- Overlapping sets SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result; +SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7 63)') AS result; +SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7 100)') AS result; +SELECT test_bms_int_members('(b 1 3 5 63)', '(b 3 5 7)') AS result; +SELECT test_bms_int_members('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; +SELECT test_bms_int_members('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; +SELECT test_bms_int_members('(b 1 3 5 100)', '(b 3 5 7)') AS result; +SELECT test_bms_int_members('(b 1 3 5 100)', '(b 3 5 7 63)') AS result; +SELECT test_bms_int_members('(b 1 3 5 100)', '(b 3 5 7 100)') AS result; -- Disjoint sets SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result; -- Intersect with empty @@ -126,6 +164,14 @@ SELECT test_bms_int_members(NULL, NULL) AS result; -- bms_difference() -- Overlapping sets SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7)') AS result; +SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7 63)') AS result; +SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7 100)') AS result; +SELECT test_bms_difference('(b 1 3 5 63)', '(b 3 5 7)') AS result; +SELECT test_bms_difference('(b 1 3 5 63)', '(b 3 5 7 63)') AS result; +SELECT test_bms_difference('(b 1 3 5 63)', '(b 3 5 7 100)') AS result; +SELECT test_bms_difference('(b 1 3 5 100)', '(b 3 5 7)') AS result; +SELECT test_bms_difference('(b 1 3 5 100)', '(b 3 5 7 63)') AS result; +SELECT test_bms_difference('(b 1 3 5 100)', '(b 3 5 7 100)') AS result; -- Disjoint sets SELECT test_bms_difference('(b 1 3 5)', '(b 2 4 6)') AS result; -- Identical sets @@ -150,6 +196,10 @@ SELECT test_bms_is_member('(b)', -5); -- error SELECT test_bms_is_member('(b 1 3 5)', 1) AS result; SELECT test_bms_is_member('(b 1 3 5)', 2) AS result; SELECT test_bms_is_member('(b 1 3 5)', 3) AS result; +SELECT test_bms_is_member('(b 1 3 5 63)', 2) AS result; +SELECT test_bms_is_member('(b 1 3 5 63)', 63) AS result; +SELECT test_bms_is_member('(b 1 3 5 100)', 2) AS result; +SELECT test_bms_is_member('(b 1 3 5 100)', 100) AS result; SELECT test_bms_is_member('(b)', 1) AS result; -- Test module check SELECT test_bms_is_member('(b 5)', NULL) AS result; @@ -160,6 +210,12 @@ SELECT test_bms_member_index('(b 1 3 5)', 2) AS result; SELECT test_bms_member_index('(b 1 3 5)', 1) AS result; SELECT test_bms_member_index('(b 1 3 5)', 3) AS result; -- Member index with various word positions +SELECT test_bms_member_index('(b 1 3 5 63)', 2) AS result; +SELECT test_bms_member_index('(b 1 3 5 63)', 63) AS result; +SELECT test_bms_member_index('(b 1 3 5 63)', 3) AS result; +SELECT test_bms_member_index('(b 1 3 5 100)', 2) AS result; +SELECT test_bms_member_index('(b 1 3 5 100)', 100) AS result; +SELECT test_bms_member_index('(b 1 3 5 100)', 3) AS result; SELECT test_bms_member_index('(b 100 200)', 100) AS result; SELECT test_bms_member_index('(b 100 200)', 200) AS result; SELECT test_bms_member_index('(b 1 50 100 200)', 200) AS result; @@ -170,6 +226,8 @@ SELECT test_bms_member_index('(b 1 3 5)', NULL) AS result; SELECT test_bms_num_members('(b)') AS result; SELECT test_bms_num_members('(b 1 3 5)') AS result; SELECT test_bms_num_members('(b 2 4 6 8 10)') AS result; +SELECT test_bms_num_members('(b 2 4 6 8 63)') AS result; +SELECT test_bms_num_members('(b 2 4 6 8 100)') AS result; -- test_bms_equal() SELECT test_bms_equal('(b)', '(b)') AS result; @@ -178,6 +236,12 @@ SELECT test_bms_equal('(b 1 3 5)', '(b)') AS result; SELECT test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result; SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; -- Equal with different word counts +SELECT test_bms_equal('(b 1 3 5 63)', '(b 1 3 5)') AS result; +SELECT test_bms_equal('(b 1 3 5 63)', '(b 1 3 5 63)') AS result; +SELECT test_bms_equal('(b 1 3 5 63)', '(b 1 3 5 100)') AS result; +SELECT test_bms_equal('(b 1 3 5 100)', '(b 1 3 5)') AS result; +SELECT test_bms_equal('(b 1 3 5 100)', '(b 1 3 5 63)') AS result; +SELECT test_bms_equal('(b 1 3 5 100)', '(b 1 3 5 100)') AS result; SELECT test_bms_equal('(b 5)', '(b 100)') AS result; SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result; -- NULL inputs @@ -207,9 +271,39 @@ SELECT test_bms_add_range('(b)', 5, 7) AS result; SELECT test_bms_add_range('(b)', 5, 5) AS result; SELECT test_bms_add_range('(b 1 10)', 5, 7) AS result; -- Word boundary of 31 +SELECT test_bms_add_range('(b)', 30, 30) AS result; +SELECT test_bms_add_range('(b)', 30, 31) AS result; +SELECT test_bms_add_range('(b)', 30, 32) AS result; SELECT test_bms_add_range('(b)', 30, 34) AS result; +SELECT test_bms_add_range('(b 30)', 30, 30) AS result; +SELECT test_bms_add_range('(b 30)', 30, 31) AS result; +SELECT test_bms_add_range('(b 30)', 30, 32) AS result; +SELECT test_bms_add_range('(b 30)', 30, 34) AS result; +SELECT test_bms_add_range('(b 31)', 30, 30) AS result; +SELECT test_bms_add_range('(b 31)', 30, 31) AS result; +SELECT test_bms_add_range('(b 31)', 30, 32) AS result; +SELECT test_bms_add_range('(b 31)', 30, 34) AS result; +SELECT test_bms_add_range('(b 32)', 30, 30) AS result; +SELECT test_bms_add_range('(b 32)', 30, 31) AS result; +SELECT test_bms_add_range('(b 32)', 30, 32) AS result; +SELECT test_bms_add_range('(b 32)', 30, 34) AS result; -- Word boundary of 63 +SELECT test_bms_add_range('(b)', 62, 62) AS result; +SELECT test_bms_add_range('(b)', 62, 63) AS result; +SELECT test_bms_add_range('(b)', 62, 64) AS result; SELECT test_bms_add_range('(b)', 62, 66) AS result; +SELECT test_bms_add_range('(b 62)', 62, 62) AS result; +SELECT test_bms_add_range('(b 62)', 62, 63) AS result; +SELECT test_bms_add_range('(b 62)', 62, 64) AS result; +SELECT test_bms_add_range('(b 62)', 62, 66) AS result; +SELECT test_bms_add_range('(b 63)', 62, 62) AS result; +SELECT test_bms_add_range('(b 63)', 62, 63) AS result; +SELECT test_bms_add_range('(b 63)', 62, 64) AS result; +SELECT test_bms_add_range('(b 63)', 62, 66) AS result; +SELECT test_bms_add_range('(b 64)', 62, 62) AS result; +SELECT test_bms_add_range('(b 64)', 62, 63) AS result; +SELECT test_bms_add_range('(b 64)', 62, 64) AS result; +SELECT test_bms_add_range('(b 64)', 62, 66) AS result; -- Large range SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result; -- Force reallocations @@ -230,6 +324,9 @@ SELECT test_bms_add_range(NULL, 10, 5) AS result; SELECT test_bms_membership('(b)') AS result; SELECT test_bms_membership('(b 42)') AS result; SELECT test_bms_membership('(b 1 2)') AS result; +SELECT test_bms_membership('(b 1 2 62)') AS result; +SELECT test_bms_membership('(b 1 2 63)') AS result; +SELECT test_bms_membership('(b 1 2 64)') AS result; -- NULL input SELECT test_bms_membership(NULL) AS result; @@ -242,6 +339,12 @@ SELECT test_bms_is_empty('(b 1)') AS result; SELECT test_bms_singleton_member('(b)'); -- error SELECT test_bms_singleton_member('(b 1 2)'); -- error SELECT test_bms_singleton_member('(b 42)') AS result; +SELECT test_bms_singleton_member('(b 61 62)'); -- error +SELECT test_bms_singleton_member('(b 62 63)'); -- error +SELECT test_bms_singleton_member('(b 63 64)'); -- error +SELECT test_bms_singleton_member('(b 62)') AS result; +SELECT test_bms_singleton_member('(b 63)') AS result; +SELECT test_bms_singleton_member('(b 64)') AS result; -- NULL input SELECT test_bms_singleton_member(NULL) AS result; @@ -252,6 +355,8 @@ SELECT test_bms_get_singleton_member(NULL) AS result; -- Not a singleton, returns input default SELECT test_bms_get_singleton_member('(b 3 6)') AS result; -- Singletone, returns sole member +SELECT test_bms_get_singleton_member('(b 62)') AS result; +SELECT test_bms_get_singleton_member('(b 63)') AS result; SELECT test_bms_get_singleton_member('(b 400)') AS result; -- bms_next_member() and bms_prev_member() @@ -259,20 +364,38 @@ SELECT test_bms_get_singleton_member('(b 400)') AS result; SELECT test_bms_next_member('(b 5 10 15 20)', -1) AS result; -- Second member SELECT test_bms_next_member('(b 5 10 15 20)', 5) AS result; +SELECT test_bms_next_member('(b 5 62)', 5) AS result; +SELECT test_bms_next_member('(b 5 63)', 5) AS result; +SELECT test_bms_next_member('(b 5 64)', 5) AS result; -- Member past the end SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result; +SELECT test_bms_next_member('(b 5 10 15 62)', 62) AS result; +SELECT test_bms_next_member('(b 5 10 15 63)', 63) AS result; +SELECT test_bms_next_member('(b 5 10 15 64)', 64) AS result; -- Empty set SELECT test_bms_next_member('(b)', -1) AS result; -- Last member SELECT test_bms_prev_member('(b 5 10 15 20)', 21) AS result; +SELECT test_bms_prev_member('(b 5 10 15 62)', 63) AS result; +SELECT test_bms_prev_member('(b 5 10 15 63)', 64) AS result; +SELECT test_bms_prev_member('(b 5 10 15 64)', 65) AS result; -- Penultimate member SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result; +SELECT test_bms_prev_member('(b 5 10 15 62)', 62) AS result; +SELECT test_bms_prev_member('(b 5 10 15 63)', 63) AS result; +SELECT test_bms_prev_member('(b 5 10 15 64)', 64) AS result; -- Past beginning member SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result; +SELECT test_bms_prev_member('(b 5 10 15 62)', 5) AS result; +SELECT test_bms_prev_member('(b 5 10 15 63)', 5) AS result; +SELECT test_bms_prev_member('(b 5 10 15 64)', 5) AS result; -- Empty set SELECT test_bms_prev_member('(b)', 100) AS result; -- Negative prevbit should result in highest possible bit in set SELECT test_bms_prev_member('(b 0 63 64 127)', -1) AS result; +SELECT test_bms_prev_member('(b 0 62)', -1) AS result; +SELECT test_bms_prev_member('(b 0 63)', -1) AS result; +SELECT test_bms_prev_member('(b 0 64)', -1) AS result; -- NULL inputs SELECT test_bms_next_member(NULL, 5) AS result; SELECT test_bms_prev_member(NULL, 5) AS result; @@ -284,6 +407,9 @@ SELECT test_bms_prev_member('(b 5 10)', NULL) AS result; SELECT test_bms_hash_value('(b)') = 0 AS result; SELECT test_bms_hash_value('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result; SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS result; +SELECT test_bms_hash_value('(b 1 3 62)') = test_bms_hash_value('(b 1 3 62)') AS result; +SELECT test_bms_hash_value('(b 1 3 63)') = test_bms_hash_value('(b 1 3 63)') AS result; +SELECT test_bms_hash_value('(b 1 3 64)') = test_bms_hash_value('(b 1 3 64)') AS result; -- NULL input SELECT test_bms_hash_value(NULL) AS result; @@ -291,6 +417,10 @@ SELECT test_bms_hash_value(NULL) AS result; SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result; SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result; +SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7 63)') AS result; +SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6 63)') AS result; +SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7 64)') AS result; +SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6 64)') AS result; -- NULL inputs SELECT test_bms_overlap('(b 5)', NULL) AS result; SELECT test_bms_overlap(NULL, '(b 5)') AS result; @@ -301,6 +431,14 @@ SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result; SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5)') AS result; SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3)') AS result; SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result; +SELECT test_bms_is_subset('(b)', '(b 1 3 5 63)') AS result; +SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5 63)') AS result; +SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3 63)') AS result; +SELECT test_bms_is_subset('(b 1 3)', '(b 2 4 63)') AS result; +SELECT test_bms_is_subset('(b)', '(b 1 3 5 64)') AS result; +SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5 64)') AS result; +SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3 64)') AS result; +SELECT test_bms_is_subset('(b 1 3)', '(b 2 4 64)') AS result; SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31), test_bms_add_range(NULL, 0, 63)) AS result; -- Is subset with shorter word counts? @@ -339,10 +477,13 @@ SELECT test_bms_subset_compare('(b 2 64 128)', '(b 1 65)') AS result; -- bms_copy() SELECT test_bms_copy(NULL) AS result; SELECT test_bms_copy('(b 1 3 5 7)') AS result; +SELECT test_bms_copy('(b 1 3 5 63)') AS result; +SELECT test_bms_copy('(b 1 3 5 64)') AS result; -- bms_add_members() SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result; SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 7)') AS result; +SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 63)') AS result; SELECT test_bms_add_members('(b 1 3 5)', '(b 100 200 300)') AS result; -- bitmap_hash() @@ -378,6 +519,12 @@ SELECT test_bms_overlap_list('(b 2 3)', ARRAY[1,2]) AS result; SELECT test_bms_overlap_list('(b 3 4)', ARRAY[3,4,5]) AS result; SELECT test_bms_overlap_list('(b 7 10)', ARRAY[6,7,8,9]) AS result; SELECT test_bms_overlap_list('(b 1 5)', ARRAY[6,7,8,9]) AS result; +SELECT test_bms_overlap_list('(b 63)', ARRAY[63]) AS result; +SELECT test_bms_overlap_list('(b 63 64)', ARRAY[62,63]) AS result; +SELECT test_bms_overlap_list('(b 64 65)', ARRAY[64,65,66]) AS result; +SELECT test_bms_overlap_list('(b 63)', ARRAY[66]) AS result; +SELECT test_bms_overlap_list('(b 63 64)', ARRAY[66]) AS result; +SELECT test_bms_overlap_list('(b 64 65)', ARRAY[66]) AS result; -- Empty list SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result; -- Overlap list with negative numbers @@ -396,6 +543,9 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 5)') AS result; SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result; -- Difference with different word counts +SELECT test_bms_nonempty_difference('(b 5)', '(b 63)') AS result; +SELECT test_bms_nonempty_difference('(b 63)', '(b 5)') AS result; +SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 63)') AS result; SELECT test_bms_nonempty_difference('(b 5)', '(b 100)') AS result; SELECT test_bms_nonempty_difference('(b 100)', '(b 5)') AS result; SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 100)') AS result; diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 77e3c04144e..30eb6a347b9 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -285,6 +285,7 @@ BitmapOr BitmapOrPath BitmapOrState Bitmapset +BitmapsetBoxed Block BlockId BlockIdData -- 2.53.0