From b5fd4972a3bc758c0b8e8c9cd4aa32bacdeb6605 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 22 Mar 2019 17:59:19 +0200 Subject: [PATCH] Fix yet more portability bugs in integerset and its tests. There were more large constants that needed UINT64CONST. And one variable was declared as "int", when it needed to be uint64. These bugs were only visible on 32-bit systems; clearly I should've tested on one, given that this code does a lot of work with 64-bit integers. Also, in the test "huge distances" test, the code created some values with random distances between them, but the test logic didn't take into account the possibility that the random distance was exactly 1. That never actually happens with the seed we're using, but let's be tidy. --- src/backend/lib/integerset.c | 12 ++++++------ src/test/modules/test_integerset/test_integerset.c | 7 +++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/backend/lib/integerset.c b/src/backend/lib/integerset.c index fcbb2bd0db..74ed621554 100644 --- a/src/backend/lib/integerset.c +++ b/src/backend/lib/integerset.c @@ -845,7 +845,7 @@ static const struct * This value looks like a 0-mode codeword, but we check for it * specifically. (In a real 0-mode codeword, all the unused bits are zero.) */ -#define EMPTY_CODEWORD (0xFFFFFFFFFFFFFFF0) +#define EMPTY_CODEWORD UINT64CONST(0xFFFFFFFFFFFFFFF0) /* * Encode a number of integers into a Simple-8b codeword. @@ -885,7 +885,7 @@ simple8b_encode(uint64 *ints, int *num_encoded, uint64 base) i = 0; for (;;) { - if (diff >= (1L << bits)) + if (diff >= (UINT64CONST(1) << bits)) { /* too large, step up to next mode */ selector++; @@ -948,7 +948,7 @@ simple8b_decode(uint64 codeword, uint64 *decoded, uint64 base) int selector = codeword & 0x0f; int nints = simple8b_modes[selector].num_ints; uint64 bits = simple8b_modes[selector].bits_per_int; - uint64 mask = (1L << bits) - 1; + uint64 mask = (UINT64CONST(1) << bits) - 1; uint64 prev_value; if (codeword == EMPTY_CODEWORD) @@ -961,7 +961,7 @@ simple8b_decode(uint64 codeword, uint64 *decoded, uint64 base) { uint64 diff = codeword & mask; - decoded[i] = prev_value + 1L + diff; + decoded[i] = prev_value + 1 + diff; prev_value = decoded[i]; codeword >>= bits; } @@ -992,7 +992,7 @@ simple8b_contains(uint64 codeword, uint64 key, uint64 base) } else { - int mask = (1L << bits) - 1; + uint64 mask = (UINT64CONST(1) << bits) - 1; uint64 prev_value; prev_value = base; @@ -1001,7 +1001,7 @@ simple8b_contains(uint64 codeword, uint64 key, uint64 base) uint64 diff = codeword & mask; uint64 curr_value; - curr_value = prev_value + 1L + diff; + curr_value = prev_value + 1 + diff; if (curr_value >= key) { diff --git a/src/test/modules/test_integerset/test_integerset.c b/src/test/modules/test_integerset/test_integerset.c index 0bb6d47f4b..32713f4baa 100644 --- a/src/test/modules/test_integerset/test_integerset.c +++ b/src/test/modules/test_integerset/test_integerset.c @@ -590,12 +590,14 @@ test_huge_distances(void) for (int i = 0; i < num_values; i++) { uint64 x = values[i]; + bool expected; bool result; if (x > 0) { + expected = (values[i - 1] == x - 1); result = intset_is_member(intset, x - 1); - if (result != false) + if (result != expected) elog(ERROR, "intset_is_member failed for " UINT64_FORMAT, x - 1); } @@ -603,8 +605,9 @@ test_huge_distances(void) if (result != true) elog(ERROR, "intset_is_member failed for " UINT64_FORMAT, x); + expected = (i != num_values - 1) ? (values[i + 1] == x + 1) : false; result = intset_is_member(intset, x + 1); - if (result != false) + if (result != expected) elog(ERROR, "intset_is_member failed for " UINT64_FORMAT, x + 1); }