diff --git a/src/test/modules/test_bitmapset/expected/test_bitmapset.out b/src/test/modules/test_bitmapset/expected/test_bitmapset.out index be7b6399c82..2e204d687df 100644 --- a/src/test/modules/test_bitmapset/expected/test_bitmapset.out +++ b/src/test/modules/test_bitmapset/expected/test_bitmapset.out @@ -63,7 +63,7 @@ SELECT test_bms_add_member('(b 10)', 10) AS result; SELECT test_bms_add_member('(b)', NULL) AS result; result -------- - + (b) (1 row) -- bms_replace_members() @@ -76,7 +76,7 @@ SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result; SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; result -------- - + (b) (1 row) SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5 6)') AS result; @@ -108,13 +108,13 @@ SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; result -------- - + (b) (1 row) SELECT test_bms_replace_members('(b 5)', NULL) AS result; result -------- - + (b) (1 row) SELECT test_bms_replace_members(NULL, '(b 5)') AS result; @@ -126,7 +126,7 @@ SELECT test_bms_replace_members(NULL, '(b 5)') AS result; SELECT test_bms_replace_members(NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_del_member() @@ -135,13 +135,13 @@ ERROR: negative bitmapset member not allowed SELECT test_bms_del_member('(b)', 10) AS result; result -------- - + (b) (1 row) SELECT test_bms_del_member('(b 10)', 10) AS result; result -------- - + (b) (1 row) SELECT test_bms_del_member('(b 10)', 5) AS result; @@ -193,26 +193,26 @@ SELECT test_bms_del_member('(b 1 50 100 200)', 100) AS result; SELECT test_bms_del_member('(b 42)', 42) AS result; result -------- - + (b) (1 row) SELECT test_bms_del_member('(b 5)', NULL) AS result; result -------- - + (b 5) (1 row) -- bms_del_members() SELECT test_bms_del_members('(b)', '(b 10)') AS result; result -------- - + (b) (1 row) SELECT test_bms_del_members('(b 10)', '(b 10)') AS result; result -------- - + (b) (1 row) SELECT test_bms_del_members('(b 10)', '(b 5)') AS result; @@ -262,7 +262,7 @@ SELECT test_bms_del_members('(b 5)', NULL) AS result; SELECT test_bms_del_members(NULL, '(b 5)') AS result; result -------- - + (b) (1 row) -- bms_join() @@ -319,7 +319,7 @@ SELECT test_bms_join(NULL, '(b 5)') AS result; SELECT test_bms_join(NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_union() @@ -341,7 +341,7 @@ SELECT test_bms_union('(b 1 3 5)', '(b)') AS result; SELECT test_bms_union('(b)', '(b)') AS result; result -------- - + (b) (1 row) -- Overlapping ranges @@ -383,7 +383,7 @@ SELECT test_bms_union(NULL, '(b 5)') AS result; SELECT test_bms_union(NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_intersect() @@ -398,14 +398,14 @@ SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result; SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result; result -------- - + (b) (1 row) -- Intersect with empty SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result; result -------- - + (b) (1 row) -- Intersect with varrying word counts @@ -425,25 +425,25 @@ SELECT test_bms_intersect('(b 1 2 3 4 5)', '(b 1 300)') AS result; SELECT test_bms_intersect('(b 1)', '(b 2)') AS result; result -------- - + (b) (1 row) SELECT test_bms_intersect('(b 5)', NULL) AS result; result -------- - + (b) (1 row) SELECT test_bms_intersect(NULL, '(b 5)') AS result; result -------- - + (b) (1 row) SELECT test_bms_intersect(NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_int_members() @@ -458,14 +458,14 @@ 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 2 4 6)') AS result; result -------- - + (b) (1 row) -- Intersect with empty SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result; result -------- - + (b) (1 row) -- Multiple members @@ -479,25 +479,25 @@ SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result; SELECT test_bms_int_members('(b 1)', '(b 2)') AS result; result -------- - + (b) (1 row) SELECT test_bms_int_members('(b 5)', NULL) AS result; result -------- - + (b) (1 row) SELECT test_bms_int_members(NULL, '(b 5)') AS result; result -------- - + (b) (1 row) SELECT test_bms_int_members(NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_difference() @@ -519,14 +519,14 @@ SELECT test_bms_difference('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_difference('(b 1 3 5)', '(b 1 3 5)') AS result; result -------- - + (b) (1 row) -- Substraction to empty SELECT test_bms_difference('(b 42)', '(b 42)') AS result; result -------- - + (b) (1 row) -- Subtraction edge case @@ -556,7 +556,7 @@ SELECT test_bms_difference('(b 1 2 100 200)', '(b 1 2)') AS result; SELECT test_bms_difference('(b 5)', '(b 5 10)') AS result; result -------- - + (b) (1 row) SELECT test_bms_difference('(b 5)', NULL) AS result; @@ -568,13 +568,13 @@ SELECT test_bms_difference('(b 5)', NULL) AS result; SELECT test_bms_difference(NULL, '(b 5)') AS result; result -------- - + (b) (1 row) SELECT test_bms_difference(NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_is_member() @@ -887,19 +887,19 @@ SELECT length(test_bms_add_range('(b 1 2)', 200, 250)) AS result; SELECT test_bms_add_range('(b 5)', 5, NULL) AS result; result -------- - + (b 5) (1 row) SELECT test_bms_add_range('(b 5)', NULL, 10) AS result; result -------- - + (b 5) (1 row) SELECT test_bms_add_range('(b 5)', NULL, NULL) AS result; result -------- - + (b 5) (1 row) SELECT test_bms_add_range(NULL, 5, 10) AS result; @@ -911,13 +911,13 @@ SELECT test_bms_add_range(NULL, 5, 10) AS result; SELECT test_bms_add_range(NULL, 10, 5) AS result; result -------- - + (b) (1 row) SELECT test_bms_add_range(NULL, NULL, NULL) AS result; result -------- - + (b) (1 row) -- bms_membership() @@ -1421,7 +1421,7 @@ SELECT test_bms_subset_compare(NULL, NULL) AS result; SELECT test_bms_copy(NULL) AS result; result -------- - + (b) (1 row) SELECT test_bms_copy('(b 1 3 5 7)') AS result; @@ -1434,7 +1434,7 @@ SELECT test_bms_copy('(b 1 3 5 7)') AS result; SELECT test_bms_copy(NULL) AS result; result -------- - + (b) (1 row) -- bms_add_members() diff --git a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql index c6e6bce60a3..c7c3cce93d3 100644 --- a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql +++ b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql @@ -258,14 +258,13 @@ SELECT test_bms_singleton_member('(b 42)') AS result; SELECT test_bms_singleton_member(NULL) AS result; -- bms_get_singleton_member() -SELECT test_bms_get_singleton_member('(b)', 1000); +SELECT test_bms_get_singleton_member('(b)'); +-- Try with an empty set +SELECT test_bms_get_singleton_member(NULL) AS result; -- Not a singleton, returns input default -SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result; +SELECT test_bms_get_singleton_member('(b 3 6)') AS result; -- Singletone, returns sole member -SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result; --- Test module checks -SELECT test_bms_get_singleton_member('', 1000) AS result; -SELECT test_bms_get_singleton_member(NULL, -1) AS result; +SELECT test_bms_get_singleton_member('(b 400)') AS result; -- bms_next_member() and bms_prev_member() -- First member diff --git a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql index b95c4d0dda5..227ecb5aa3b 100644 --- a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql +++ b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql @@ -68,7 +68,7 @@ CREATE FUNCTION test_bms_singleton_member(text) RETURNS integer STRICT AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION test_bms_get_singleton_member(text, integer) +CREATE FUNCTION test_bms_get_singleton_member(text) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_bitmapset/test_bitmapset.c b/src/test/modules/test_bitmapset/test_bitmapset.c index 2e821320836..88fd71d5495 100644 --- a/src/test/modules/test_bitmapset/test_bitmapset.c +++ b/src/test/modules/test_bitmapset/test_bitmapset.c @@ -26,7 +26,6 @@ #include "nodes/pg_list.h" #include "utils/builtins.h" #include "utils/timestamp.h" -#include "varatt.h" PG_MODULE_MAGIC; @@ -84,105 +83,109 @@ PG_FUNCTION_INFO_V1(test_random_operations); #expr, __FILE__, __LINE__); \ } while (0) +static const char *emptyset = "(b)"; + /* Encode/Decode to/from TEXT and Bitmapset */ -#define BITMAPSET_TO_TEXT(bms) cstring_to_text(nodeToString(bms)) +#define BITMAPSET_TO_TEXT(bms) cstring_to_text(bms ? nodeToString(bms) : emptyset) #define TEXT_TO_BITMAPSET(str) ((Bitmapset *) stringToNode(text_to_cstring(str))) +/* Helper macro to fetch Text parameters as Bitmapsets. SQL-NULL means empty set */ +#define PG_ARG_GETBITMAPSET(n) \ + (PG_ARGISNULL(n) ? NULL : TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(n))) + +/* + * Helper macro to handle converting sets back to text, freeing the set and + * returning the resulting text representation of the set. Beware of double + * evaluation hazard of 'bms'. + */ +#define PG_RETURN_BITMAPSET_AS_TEXT(bms) \ + do { \ + text *result = BITMAPSET_TO_TEXT(bms); \ + bms_free(bms); \ + PG_RETURN_TEXT_P(result); \ + } while (0); + /* * Individual test functions for each bitmapset API function + * + * Primarily, we aim to keep these as close to simple wrapper functions as + * possible in order to publish the functions of bitmapset.c to the SQL layer + * with as little interference as possible. We opt to return SQL NULL in + * cases where the input given to the SQL function isn't valid to pass to the + * underlying bitmapset.c function. For example we cannot do much useful + * testing if someone calls test_bms_make_singleton(NULL) since + * bms_make_singleton() expects an integer argument. + * + * For function arguments which are to be converted to Bitmapsets, we accept + * SQL NULL as a valid argument to mean an empty set. Optionally callers may + * pass '(b)'. + * + * For the test functions which return a Bitmapset, these are converted back + * to Text with empty sets being represented as '(b)'. */ Datum test_bms_add_member(PG_FUNCTION_ARGS) { + Bitmapset *bms; int member; - Bitmapset *bms = NULL; - text *result; if (PG_ARGISNULL(1)) - PG_RETURN_NULL(); - - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + PG_RETURN_NULL(); /* invalid input */ + bms = PG_ARG_GETBITMAPSET(0); member = PG_GETARG_INT32(1); - bms = bms_add_member(bms, member); - result = BITMAPSET_TO_TEXT(bms); - if (bms) - bms_free(bms); + bms = bms_add_member(bms, member); - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms); } Datum test_bms_add_members(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; - text *result; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - - /* IMPORTANT: bms_add_members modifies/frees the first argument */ + /* left input is recycled */ bms1 = bms_add_members(bms1, bms2); + bms_free(bms2); - if (bms2) - bms_free(bms2); - - result = BITMAPSET_TO_TEXT(bms1); - bms_free(bms1); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms1); } Datum test_bms_del_member(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms; int32 member; - text *result; if (PG_ARGISNULL(1)) - PG_RETURN_NULL(); - - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + PG_RETURN_NULL(); /* invalid input */ + bms = PG_ARG_GETBITMAPSET(0); member = PG_GETARG_INT32(1); - bms = bms_del_member(bms, member); - - if (bms_is_empty(bms)) - PG_RETURN_NULL(); - result = BITMAPSET_TO_TEXT(bms); - bms_free(bms); + bms = bms_del_member(bms, member); - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms); } Datum test_bms_is_member(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms; int32 member; bool result; if (PG_ARGISNULL(1)) - PG_RETURN_BOOL(false); - - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + PG_RETURN_NULL(); /* invalid input */ + bms = PG_ARG_GETBITMAPSET(0); member = PG_GETARG_INT32(1); - result = bms_is_member(member, bms); - if (bms) - bms_free(bms); + result = bms_is_member(member, bms); + bms_free(bms); PG_RETURN_BOOL(result); } @@ -190,16 +193,11 @@ test_bms_is_member(PG_FUNCTION_ARGS) Datum test_bms_num_members(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; - int result = 0; - - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); + int result; result = bms_num_members(bms); - - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_INT32(result); } @@ -207,65 +205,40 @@ test_bms_num_members(PG_FUNCTION_ARGS) Datum test_bms_make_singleton(PG_FUNCTION_ARGS) { - int32 member; Bitmapset *bms; - text *result; + int32 member; if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); + PG_RETURN_NULL(); /* invalid input */ member = PG_GETARG_INT32(0); bms = bms_make_singleton(member); - result = BITMAPSET_TO_TEXT(bms); - bms_free(bms); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms); } Datum test_bms_copy(PG_FUNCTION_ARGS) { - text *bms_data; - Bitmapset *bms = NULL; + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); Bitmapset *copy_bms; - text *result; - if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); - - bms_data = PG_GETARG_TEXT_PP(0); - bms = TEXT_TO_BITMAPSET(bms_data); copy_bms = bms_copy(bms); - result = BITMAPSET_TO_TEXT(copy_bms); - - if (bms) - bms_free(bms); - if (copy_bms) - bms_free(copy_bms); + bms_free(bms); - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(copy_bms); } Datum test_bms_equal(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); bool result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - result = bms_equal(bms1, bms2); - - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + bms_free(bms1); + bms_free(bms2); PG_RETURN_BOOL(result); } @@ -273,47 +246,25 @@ test_bms_equal(PG_FUNCTION_ARGS) Datum test_bms_union(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); Bitmapset *result_bms; - text *result; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); result_bms = bms_union(bms1, bms2); + bms_free(bms1); + bms_free(bms2); - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); - - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(result_bms); } Datum test_bms_membership(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); BMS_Membership result; - if (PG_ARGISNULL(0)) - PG_RETURN_INT32(BMS_EMPTY_SET); - - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); result = bms_membership(bms); - - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_INT32((int32) result); } @@ -321,19 +272,18 @@ test_bms_membership(PG_FUNCTION_ARGS) Datum test_bms_next_member(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms; int32 prevmember; int result; - if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) - PG_RETURN_INT32(-2); + if (PG_ARGISNULL(1)) + PG_RETURN_NULL(); /* invalid input */ - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + bms = PG_ARG_GETBITMAPSET(0); prevmember = PG_GETARG_INT32(1); - result = bms_next_member(bms, prevmember); - if (bms) - bms_free(bms); + result = bms_next_member(bms, prevmember); + bms_free(bms); PG_RETURN_INT32(result); } @@ -341,82 +291,41 @@ test_bms_next_member(PG_FUNCTION_ARGS) Datum test_bms_intersect(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); Bitmapset *result_bms; - text *result; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); result_bms = bms_intersect(bms1, bms2); + bms_free(bms1); + bms_free(bms2); - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); - - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(result_bms); } Datum test_bms_difference(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); Bitmapset *result_bms; - text *result; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); result_bms = bms_difference(bms1, bms2); + bms_free(bms1); + bms_free(bms2); - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); - - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(result_bms); } Datum test_bms_compare(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); int result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - result = bms_compare(bms1, bms2); - - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + bms_free(bms1); + bms_free(bms2); PG_RETURN_INT32(result); } @@ -424,16 +333,11 @@ test_bms_compare(PG_FUNCTION_ARGS) Datum test_bms_is_empty(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); bool result; - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - result = bms_is_empty(bms); - - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_BOOL(result); } @@ -441,22 +345,13 @@ test_bms_is_empty(PG_FUNCTION_ARGS) Datum test_bms_is_subset(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); bool result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - result = bms_is_subset(bms1, bms2); - - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + bms_free(bms1); + bms_free(bms2); PG_RETURN_BOOL(result); } @@ -464,22 +359,13 @@ test_bms_is_subset(PG_FUNCTION_ARGS) Datum test_bms_subset_compare(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); BMS_Comparison result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - result = bms_subset_compare(bms1, bms2); - - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + bms_free(bms1); + bms_free(bms2); PG_RETURN_INT32((int32) result); } @@ -487,16 +373,11 @@ test_bms_subset_compare(PG_FUNCTION_ARGS) Datum test_bms_singleton_member(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); int result; - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - result = bms_singleton_member(bms); - - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_INT32(result); } @@ -504,47 +385,34 @@ test_bms_singleton_member(PG_FUNCTION_ARGS) Datum test_bms_get_singleton_member(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; - int32 default_member = PG_GETARG_INT32(1); - bool success; - int member = -1; - - if (PG_ARGISNULL(0)) - PG_RETURN_INT32(default_member); - - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); + int member; /* - * bms_get_singleton_member returns bool and stores result in member - * pointer + * Keep this simple. Return -1 when we detect the set isn't a singleton + * set, otherwise return the singleton member. */ - success = bms_get_singleton_member(bms, &member); - bms_free(bms); + if (!bms_get_singleton_member(bms, &member)) + member = -1; - if (success) - PG_RETURN_INT32(member); + bms_free(bms); - PG_RETURN_INT32(default_member); + PG_RETURN_INT32(member); } Datum test_bms_prev_member(PG_FUNCTION_ARGS) { - text *bms_data; - Bitmapset *bms = NULL; + Bitmapset *bms; int32 prevmember; int result; - if (PG_ARGISNULL(0)) - PG_RETURN_INT32(-2); + if (PG_ARGISNULL(1)) + PG_RETURN_NULL(); /* invalid input */ - bms_data = PG_GETARG_TEXT_PP(0); + bms = PG_ARG_GETBITMAPSET(0); prevmember = PG_GETARG_INT32(1); - if (VARSIZE_ANY_EXHDR(bms_data) == 0) - PG_RETURN_INT32(-2); - - bms = TEXT_TO_BITMAPSET(bms_data); result = bms_prev_member(bms, prevmember); bms_free(bms); @@ -554,22 +422,13 @@ test_bms_prev_member(PG_FUNCTION_ARGS) Datum test_bms_overlap(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); bool result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - result = bms_overlap(bms1, bms2); - - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + bms_free(bms1); + bms_free(bms2); PG_RETURN_BOOL(result); } @@ -577,52 +436,47 @@ test_bms_overlap(PG_FUNCTION_ARGS) Datum test_bms_overlap_list(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms; ArrayType *array; List *int_list = NIL; bool result; - Datum *elem_datums; - bool *elem_nulls; + Datum *elem_datums = NULL; + bool *elem_nulls = NULL; int elem_count; int i; - if (PG_ARGISNULL(0)) - PG_RETURN_BOOL(false); + bms = PG_ARG_GETBITMAPSET(0); - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (PG_ARGISNULL(1)) + if (!PG_ARGISNULL(1)) { - if (bms) - bms_free(bms); - PG_RETURN_BOOL(false); - } - - array = PG_GETARG_ARRAYTYPE_P(1); + array = PG_GETARG_ARRAYTYPE_P(1); - deconstruct_array(array, - INT4OID, sizeof(int32), true, 'i', - &elem_datums, &elem_nulls, &elem_count); + deconstruct_array(array, + INT4OID, sizeof(int32), true, 'i', + &elem_datums, &elem_nulls, &elem_count); - for (i = 0; i < elem_count; i++) - { - if (!elem_nulls[i]) + for (i = 0; i < elem_count; i++) { - int32 member = DatumGetInt32(elem_datums[i]); + if (!elem_nulls[i]) + { + int32 member = DatumGetInt32(elem_datums[i]); - int_list = lappend_int(int_list, member); + int_list = lappend_int(int_list, member); + } } } result = bms_overlap_list(bms, int_list); - if (bms) - bms_free(bms); + bms_free(bms); list_free(int_list); - pfree(elem_datums); - pfree(elem_nulls); + if (elem_datums) + pfree(elem_datums); + + if (elem_nulls) + pfree(elem_nulls); PG_RETURN_BOOL(result); } @@ -630,22 +484,13 @@ test_bms_overlap_list(PG_FUNCTION_ARGS) Datum test_bms_nonempty_difference(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); bool result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - result = bms_nonempty_difference(bms1, bms2); - - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + bms_free(bms1); + bms_free(bms2); PG_RETURN_BOOL(result); } @@ -653,22 +498,16 @@ test_bms_nonempty_difference(PG_FUNCTION_ARGS) Datum test_bms_member_index(PG_FUNCTION_ARGS) { - text *bms_data; - Bitmapset *bms = NULL; + Bitmapset *bms; int32 member; int result; - if (PG_ARGISNULL(0)) - PG_RETURN_INT32(-1); + if (PG_ARGISNULL(1)) + PG_RETURN_NULL(); /* invalid input */ - bms_data = PG_GETARG_TEXT_PP(0); + bms = PG_ARG_GETBITMAPSET(0); member = PG_GETARG_INT32(1); - if (VARSIZE_ANY_EXHDR(bms_data) == 0) - PG_RETURN_INT32(-1); - - bms = TEXT_TO_BITMAPSET(bms_data); - result = bms_member_index(bms, member); bms_free(bms); @@ -678,169 +517,85 @@ test_bms_member_index(PG_FUNCTION_ARGS) Datum test_bms_add_range(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms; int32 lower, upper; - text *result; if (PG_ARGISNULL(1) || PG_ARGISNULL(2)) - PG_RETURN_NULL(); - - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + PG_RETURN_NULL(); /* invalid input */ + bms = PG_ARG_GETBITMAPSET(0); lower = PG_GETARG_INT32(1); upper = PG_GETARG_INT32(2); - /* Check for invalid range */ - if (upper < lower) - { - if (bms) - bms_free(bms); - PG_RETURN_NULL(); - } - bms = bms_add_range(bms, lower, upper); - result = BITMAPSET_TO_TEXT(bms); - if (bms) - bms_free(bms); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms); } Datum test_bms_int_members(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; - text *result; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); + /* left input gets recycled */ bms1 = bms_int_members(bms1, bms2); - if (bms2) - bms_free(bms2); - - if (bms1 == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(bms1); - - if (bms1) - bms_free(bms1); + bms_free(bms2); - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms1); } Datum test_bms_del_members(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; - Bitmapset *result_bms; - text *result; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - - /* IMPORTANT: bms_del_members modifies/frees the first argument */ - result_bms = bms_del_members(bms1, bms2); - - /* bms1 is now invalid, do not free it */ - - if (bms2) - bms_free(bms2); - - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); + /* left input gets recycled */ + bms1 = bms_del_members(bms1, bms2); + bms_free(bms2); - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(bms1); } Datum test_bms_replace_members(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; - Bitmapset *result_bms; - text *result; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - - /* IMPORTANT: bms_replace_members modifies/frees the first argument */ - result_bms = bms_replace_members(bms1, bms2); + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); - /* bms1 is now invalid, do not free it */ + /* left input gets recycled */ + bms1 = bms_replace_members(bms1, bms2); - if (bms2) - bms_free(bms2); - - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); - - PG_RETURN_TEXT_P(result); + bms_free(bms2); + PG_RETURN_BITMAPSET_AS_TEXT(bms1); } Datum test_bms_join(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); Bitmapset *result_bms; - text *result; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - /* IMPORTANT: bms_join may recycle either input arguments */ + /* either input can be recycled */ result_bms = bms_join(bms1, bms2); - /* bms1 and bms2 may have been recycled! Do not free any of them. */ + /* memory cleanup seems more tricky than it's worth here */ - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); - - PG_RETURN_TEXT_P(result); + PG_RETURN_BITMAPSET_AS_TEXT(result_bms); } Datum test_bms_hash_value(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); uint32 hash_result; - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - hash_result = bms_hash_value(bms); - - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_INT32(hash_result); } @@ -848,21 +603,12 @@ test_bms_hash_value(PG_FUNCTION_ARGS) Datum test_bitmap_hash(PG_FUNCTION_ARGS) { - Bitmapset *bms = NULL; - Bitmapset *bms_ptr; + Bitmapset *bms = PG_ARG_GETBITMAPSET(0); uint32 hash_result; - if (!PG_ARGISNULL(0)) - bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - bms_ptr = bms; - /* Call bitmap_hash */ - hash_result = bitmap_hash(&bms_ptr, sizeof(Bitmapset *)); - - /* Clean up */ - if (!PG_ARGISNULL(0) && bms_ptr) - bms_free(bms_ptr); + hash_result = bitmap_hash(&bms, sizeof(Bitmapset *)); + bms_free(bms); PG_RETURN_INT32(hash_result); } @@ -870,30 +616,14 @@ test_bitmap_hash(PG_FUNCTION_ARGS) Datum test_bitmap_match(PG_FUNCTION_ARGS) { - Bitmapset *bms1 = NULL, - *bms2 = NULL; - Bitmapset *bms_ptr1, - *bms_ptr2; + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); int match_result; - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); - - if (!PG_ARGISNULL(1)) - bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1)); - - /* Set up pointers to the Bitmapsets */ - bms_ptr1 = bms1; - bms_ptr2 = bms2; - /* Call bitmap_match with addresses of the Bitmapset pointers */ - match_result = bitmap_match(&bms_ptr1, &bms_ptr2, sizeof(Bitmapset *)); - - /* Clean up */ - if (bms1) - bms_free(bms1); - if (bms2) - bms_free(bms2); + match_result = bitmap_match(&bms1, &bms2, sizeof(Bitmapset *)); + bms_free(bms1); + bms_free(bms2); PG_RETURN_INT32(match_result); } @@ -1031,8 +761,7 @@ test_random_operations(PG_FUNCTION_ARGS) total_ops++; } - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_INT32(total_ops); }