diff options
Diffstat (limited to 'src/test')
7 files changed, 356 insertions, 775 deletions
diff --git a/src/test/modules/test_bitmapset/expected/test_bitmapset.out b/src/test/modules/test_bitmapset/expected/test_bitmapset.out index be7b6399c82..3198614d6ad 100644 --- a/src/test/modules/test_bitmapset/expected/test_bitmapset.out +++ b/src/test/modules/test_bitmapset/expected/test_bitmapset.out @@ -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 -------- - + <> (1 row) SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5 6)') AS result; @@ -104,44 +104,19 @@ SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; (b 500 600) (1 row) --- Test module checks -SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; - result --------- - -(1 row) - -SELECT test_bms_replace_members('(b 5)', NULL) AS result; - result --------- - -(1 row) - -SELECT test_bms_replace_members(NULL, '(b 5)') AS result; - result --------- - (b 5) -(1 row) - -SELECT test_bms_replace_members(NULL, NULL) AS result; - result --------- - -(1 row) - -- bms_del_member() SELECT test_bms_del_member('(b)', -20); -- error ERROR: negative bitmapset member not allowed SELECT test_bms_del_member('(b)', 10) AS result; result -------- - + <> (1 row) SELECT test_bms_del_member('(b 10)', 10) AS result; result -------- - + <> (1 row) SELECT test_bms_del_member('(b 10)', 5) AS result; @@ -190,12 +165,6 @@ SELECT test_bms_del_member('(b 1 50 100 200)', 100) AS result; (1 row) -- Test module checks -SELECT test_bms_del_member('(b 42)', 42) AS result; - result --------- - -(1 row) - SELECT test_bms_del_member('(b 5)', NULL) AS result; result -------- @@ -206,13 +175,13 @@ SELECT test_bms_del_member('(b 5)', NULL) AS result; SELECT test_bms_del_members('(b)', '(b 10)') AS result; result -------- - + <> (1 row) SELECT test_bms_del_members('(b 10)', '(b 10)') AS result; result -------- - + <> (1 row) SELECT test_bms_del_members('(b 10)', '(b 5)') AS result; @@ -252,7 +221,7 @@ SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 200 300)') AS result; (b 1 2 100) (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_del_members('(b 5)', NULL) AS result; result -------- @@ -262,7 +231,7 @@ SELECT test_bms_del_members('(b 5)', NULL) AS result; SELECT test_bms_del_members(NULL, '(b 5)') AS result; result -------- - + <> (1 row) -- bms_join() @@ -303,7 +272,7 @@ SELECT test_bms_join('(b 1 2)', '(b 100 200 300)') AS result; (b 1 2 100 200 300) (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_join('(b 5)', NULL) AS result; result -------- @@ -319,7 +288,7 @@ SELECT test_bms_join(NULL, '(b 5)') AS result; SELECT test_bms_join(NULL, NULL) AS result; result -------- - + <> (1 row) -- bms_union() @@ -341,7 +310,7 @@ SELECT test_bms_union('(b 1 3 5)', '(b)') AS result; SELECT test_bms_union('(b)', '(b)') AS result; result -------- - + <> (1 row) -- Overlapping ranges @@ -354,7 +323,7 @@ SELECT test_bms_union( (b 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20) (1 row) --- Union with varrying word counts +-- Union with varying word counts SELECT test_bms_union('(b 1 2)', '(b 100 300)') AS result; result ----------------- @@ -367,7 +336,7 @@ SELECT test_bms_union('(b 100 300)', '(b 1 2)') AS result; (b 1 2 100 300) (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_union('(b 5)', NULL) AS result; result -------- @@ -383,7 +352,7 @@ SELECT test_bms_union(NULL, '(b 5)') AS result; SELECT test_bms_union(NULL, NULL) AS result; result -------- - + <> (1 row) -- bms_intersect() @@ -398,17 +367,17 @@ 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 -------- - + <> (1 row) -- Intersect with empty SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result; result -------- - + <> (1 row) --- Intersect with varrying word counts +-- Intersect with varying word counts SELECT test_bms_intersect('(b 1 300)', '(b 1 2 3 4 5)') AS result; result -------- @@ -421,29 +390,23 @@ SELECT test_bms_intersect('(b 1 2 3 4 5)', '(b 1 300)') AS result; (b 1) (1 row) --- Test module checks -SELECT test_bms_intersect('(b 1)', '(b 2)') AS result; - result --------- - -(1 row) - +-- NULL inputs SELECT test_bms_intersect('(b 5)', NULL) AS result; result -------- - + <> (1 row) SELECT test_bms_intersect(NULL, '(b 5)') AS result; result -------- - + <> (1 row) SELECT test_bms_intersect(NULL, NULL) AS result; result -------- - + <> (1 row) -- bms_int_members() @@ -458,14 +421,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 -------- - + <> (1 row) -- Intersect with empty SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result; result -------- - + <> (1 row) -- Multiple members @@ -475,29 +438,23 @@ SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result; (b 31 32 64) (1 row) --- Test module checks -SELECT test_bms_int_members('(b 1)', '(b 2)') AS result; - result --------- - -(1 row) - +-- NULL inputs SELECT test_bms_int_members('(b 5)', NULL) AS result; result -------- - + <> (1 row) SELECT test_bms_int_members(NULL, '(b 5)') AS result; result -------- - + <> (1 row) SELECT test_bms_int_members(NULL, NULL) AS result; result -------- - + <> (1 row) -- bms_difference() @@ -519,14 +476,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 -------- - + <> (1 row) -- Substraction to empty SELECT test_bms_difference('(b 42)', '(b 42)') AS result; result -------- - + <> (1 row) -- Subtraction edge case @@ -552,13 +509,7 @@ SELECT test_bms_difference('(b 1 2 100 200)', '(b 1 2)') AS result; (b 100 200) (1 row) --- Test module checks -SELECT test_bms_difference('(b 5)', '(b 5 10)') AS result; - result --------- - -(1 row) - +-- NULL inputs SELECT test_bms_difference('(b 5)', NULL) AS result; result -------- @@ -568,13 +519,13 @@ SELECT test_bms_difference('(b 5)', NULL) AS result; SELECT test_bms_difference(NULL, '(b 5)') AS result; result -------- - + <> (1 row) SELECT test_bms_difference(NULL, NULL) AS result; result -------- - + <> (1 row) -- bms_is_member() @@ -608,7 +559,7 @@ SELECT test_bms_is_member('(b)', 1) AS result; SELECT test_bms_is_member('(b 5)', NULL) AS result; result -------- - f + (1 row) -- bms_member_index() @@ -655,17 +606,11 @@ SELECT test_bms_member_index('(b 1 50 100 200)', 200) AS result; 3 (1 row) --- Test module checks -SELECT test_bms_member_index('', 5) AS result; - result --------- - -1 -(1 row) - -SELECT test_bms_member_index(NULL, 5) AS result; +-- Test module check +SELECT test_bms_member_index('(b 1 3 5)', NULL) AS result; result -------- - -1 + (1 row) -- bms_num_members() @@ -731,7 +676,7 @@ SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result; f (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_equal('(b 5)', NULL) AS result; result -------- @@ -796,7 +741,7 @@ SELECT test_bms_compare( -1 (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_compare('(b 5)', NULL) AS result; result -------- @@ -902,6 +847,7 @@ SELECT test_bms_add_range('(b 5)', NULL, NULL) AS result; (1 row) +-- NULL inputs SELECT test_bms_add_range(NULL, 5, 10) AS result; result ------------------ @@ -911,13 +857,7 @@ SELECT test_bms_add_range(NULL, 5, 10) AS result; SELECT test_bms_add_range(NULL, 10, 5) AS result; result -------- - -(1 row) - -SELECT test_bms_add_range(NULL, NULL, NULL) AS result; - result --------- - + <> (1 row) -- bms_membership() @@ -939,7 +879,7 @@ SELECT test_bms_membership('(b 1 2)') AS result; 2 (1 row) --- Test module check +-- NULL input SELECT test_bms_membership(NULL) AS result; result -------- @@ -965,13 +905,6 @@ SELECT test_bms_is_empty('(b 1)') AS result; f (1 row) --- Test module check -SELECT test_bms_is_empty(NULL) AS result; - result --------- - t -(1 row) - -- bms_singleton_member() SELECT test_bms_singleton_member('(b)'); -- error ERROR: bitmapset is empty @@ -983,7 +916,7 @@ SELECT test_bms_singleton_member('(b 42)') AS result; 42 (1 row) --- Test module check +-- NULL input SELECT test_bms_singleton_member(NULL) AS result; result -------- @@ -991,37 +924,31 @@ SELECT test_bms_singleton_member(NULL) AS result; (1 row) -- bms_get_singleton_member() -SELECT test_bms_get_singleton_member('(b)', 1000); +SELECT test_bms_get_singleton_member('(b)'); test_bms_get_singleton_member ------------------------------- - 1000 -(1 row) - --- Not a singleton, returns input default -SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result; - result --------- - 1000 + -1 (1 row) --- Singletone, returns sole member -SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result; +-- Try with an empty set +SELECT test_bms_get_singleton_member(NULL) AS result; result -------- - 400 + -1 (1 row) --- Test module checks -SELECT test_bms_get_singleton_member('', 1000) AS result; +-- Not a singleton, returns input default +SELECT test_bms_get_singleton_member('(b 3 6)') AS result; result -------- - 1000 + -1 (1 row) -SELECT test_bms_get_singleton_member(NULL, -1) AS result; +-- Singletone, returns sole member +SELECT test_bms_get_singleton_member('(b 400)') AS result; result -------- - -1 + 400 (1 row) -- bms_next_member() and bms_prev_member() @@ -1088,47 +1015,30 @@ SELECT test_bms_prev_member('(b 0 63 64 127)', -1) AS result; 127 (1 row) --- Test module checks -SELECT test_bms_next_member('', 5) AS result; - result --------- - -2 -(1 row) - -SELECT test_bms_next_member('(b 5)', NULL) AS result; - result --------- - -2 -(1 row) - +-- NULL inputs SELECT test_bms_next_member(NULL, 5) AS result; result -------- -2 (1 row) -SELECT test_bms_next_member(NULL, NULL) AS result; - result --------- - -2 -(1 row) - -SELECT test_bms_prev_member('', 5) AS result; +SELECT test_bms_prev_member(NULL, 5) AS result; result -------- -2 (1 row) -SELECT test_bms_prev_member('(b 5)', NULL) AS result; +-- Test module check +SELECT test_bms_next_member('(b 5 10)', NULL) AS result; result -------- - -2 + (1 row) -SELECT test_bms_prev_member(NULL, 5) AS result; +SELECT test_bms_prev_member('(b 5 10)', NULL) AS result; result -------- - -2 + (1 row) -- bms_hash_value() @@ -1150,7 +1060,7 @@ SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS r t (1 row) --- Test module check +-- NULL input SELECT test_bms_hash_value(NULL) AS result; result -------- @@ -1176,7 +1086,7 @@ SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result; f (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_overlap('(b 5)', NULL) AS result; result -------- @@ -1240,7 +1150,7 @@ SELECT test_bms_is_subset('(b 1 2 50 100)', '(b 1 2)') AS result; f (1 row) --- Test module checks +-- NULL inputs SELECT test_bms_is_subset('(b 5)', NULL) AS result; result -------- @@ -1398,30 +1308,11 @@ SELECT test_bms_subset_compare('(b 2 64 128)', '(b 1 65)') AS result; 3 (1 row) --- Test module checks -SELECT test_bms_subset_compare('(b 5)', NULL) AS result; - result --------- - 2 -(1 row) - -SELECT test_bms_subset_compare(NULL, '(b 5)') AS result; - result --------- - 1 -(1 row) - -SELECT test_bms_subset_compare(NULL, NULL) AS result; - result --------- - 0 -(1 row) - -- bms_copy() SELECT test_bms_copy(NULL) AS result; result -------- - + <> (1 row) SELECT test_bms_copy('(b 1 3 5 7)') AS result; @@ -1430,13 +1321,6 @@ SELECT test_bms_copy('(b 1 3 5 7)') AS result; (b 1 3 5 7) (1 row) --- Test module check -SELECT test_bms_copy(NULL) AS result; - result --------- - -(1 row) - -- bms_add_members() SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result; result @@ -1547,7 +1431,7 @@ SELECT (test_bitmap_match('(b)', '(b)') = 0) = t (1 row) --- Test module checks +-- NULL inputs SELECT test_bitmap_match('(b 5)', NULL) AS result; result -------- @@ -1609,7 +1493,7 @@ SELECT test_bms_overlap_list('(b 5 10)', ARRAY[-1,5]) AS result; -- error ERROR: negative bitmapset member not allowed SELECT test_bms_overlap_list('(b 1 2 3)', ARRAY[-5,-1,0]) AS result; -- error ERROR: negative bitmapset member not allowed --- Test module checks +-- NULL inputs SELECT test_bms_overlap_list('(b 5)', NULL) AS result; result -------- @@ -1641,6 +1525,12 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', NULL) AS result; t (1 row) +SELECT test_bms_nonempty_difference(NULL, NULL) AS result; + result +-------- + f +(1 row) + SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 2 4 6)') AS result; result -------- @@ -1678,25 +1568,6 @@ SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 100)') AS result; t (1 row) --- Test module checks -SELECT test_bms_nonempty_difference('(b 5)', NULL) AS result; - result --------- - t -(1 row) - -SELECT test_bms_nonempty_difference(NULL, '(b 5)') AS result; - result --------- - f -(1 row) - -SELECT test_bms_nonempty_difference(NULL, NULL) AS result; - result --------- - f -(1 row) - -- random operations SELECT test_random_operations(-1, 10000, 81920, 0) > 0 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 c6e6bce60a3..0a2fa151093 100644 --- a/src/test/modules/test_bitmapset/sql/test_bitmapset.sql +++ b/src/test/modules/test_bitmapset/sql/test_bitmapset.sql @@ -29,11 +29,6 @@ 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; -- Force repalloc() with larger set SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result; --- Test module checks -SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result; -SELECT test_bms_replace_members('(b 5)', NULL) AS result; -SELECT test_bms_replace_members(NULL, '(b 5)') AS result; -SELECT test_bms_replace_members(NULL, NULL) AS result; -- bms_del_member() SELECT test_bms_del_member('(b)', -20); -- error @@ -50,7 +45,6 @@ SELECT test_bms_del_member('(b 1 200)', 200) AS result; SELECT test_bms_del_member('(b 1 50 100 200)', 200) AS result; SELECT test_bms_del_member('(b 1 50 100 200)', 100) AS result; -- Test module checks -SELECT test_bms_del_member('(b 42)', 42) AS result; SELECT test_bms_del_member('(b 5)', NULL) AS result; -- bms_del_members() @@ -63,7 +57,7 @@ SELECT test_bms_del_members('(b 5 100 200)', '(b 200)') AS result; -- Force word count changes SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 1 2)') AS result; SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 200 300)') AS result; --- Test module checks +-- NULL inputs SELECT test_bms_del_members('(b 5)', NULL) AS result; SELECT test_bms_del_members(NULL, '(b 5)') AS result; @@ -75,7 +69,7 @@ SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') 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; --- Test module checks +-- NULL inputs SELECT test_bms_join('(b 5)', NULL) AS result; SELECT test_bms_join(NULL, '(b 5)') AS result; SELECT test_bms_join(NULL, NULL) AS result; @@ -92,10 +86,10 @@ SELECT test_bms_union( test_bms_add_range('(b)', 0, 15), test_bms_add_range('(b)', 10, 20) ) AS result; --- Union with varrying word counts +-- Union with varying word counts SELECT test_bms_union('(b 1 2)', '(b 100 300)') AS result; SELECT test_bms_union('(b 100 300)', '(b 1 2)') AS result; --- Test module checks +-- NULL inputs SELECT test_bms_union('(b 5)', NULL) AS result; SELECT test_bms_union(NULL, '(b 5)') AS result; SELECT test_bms_union(NULL, NULL) AS result; @@ -107,11 +101,10 @@ 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; -- Intersect with empty SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result; --- Intersect with varrying word counts +-- Intersect with varying word counts SELECT test_bms_intersect('(b 1 300)', '(b 1 2 3 4 5)') AS result; SELECT test_bms_intersect('(b 1 2 3 4 5)', '(b 1 300)') AS result; --- Test module checks -SELECT test_bms_intersect('(b 1)', '(b 2)') AS result; +-- NULL inputs SELECT test_bms_intersect('(b 5)', NULL) AS result; SELECT test_bms_intersect(NULL, '(b 5)') AS result; SELECT test_bms_intersect(NULL, NULL) AS result; @@ -125,8 +118,7 @@ SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result; -- Multiple members SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result; --- Test module checks -SELECT test_bms_int_members('(b 1)', '(b 2)') AS result; +-- NULL inputs SELECT test_bms_int_members('(b 5)', NULL) AS result; SELECT test_bms_int_members(NULL, '(b 5)') AS result; SELECT test_bms_int_members(NULL, NULL) AS result; @@ -148,8 +140,7 @@ SELECT test_bms_difference( -- Difference with different word counts SELECT test_bms_difference('(b 5 100)', '(b 5)') AS result; SELECT test_bms_difference('(b 1 2 100 200)', '(b 1 2)') AS result; --- Test module checks -SELECT test_bms_difference('(b 5)', '(b 5 10)') AS result; +-- NULL inputs SELECT test_bms_difference('(b 5)', NULL) AS result; SELECT test_bms_difference(NULL, '(b 5)') AS result; SELECT test_bms_difference(NULL, NULL) AS result; @@ -172,9 +163,8 @@ SELECT test_bms_member_index('(b 1 3 5)', 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; --- Test module checks -SELECT test_bms_member_index('', 5) AS result; -SELECT test_bms_member_index(NULL, 5) AS result; +-- Test module check +SELECT test_bms_member_index('(b 1 3 5)', NULL) AS result; -- bms_num_members() SELECT test_bms_num_members('(b)') AS result; @@ -190,7 +180,7 @@ SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; -- Equal with different word counts SELECT test_bms_equal('(b 5)', '(b 100)') AS result; SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result; --- Test module checks +-- NULL inputs SELECT test_bms_equal('(b 5)', NULL) AS result; SELECT test_bms_equal(NULL, '(b 5)') AS result; SELECT test_bms_equal(NULL, NULL) AS result; @@ -206,7 +196,7 @@ SELECT test_bms_compare( test_bms_add_range('(b)', 0, 63), test_bms_add_range('(b)', 0, 64) ) AS result; --- Test module checks +-- NULL inputs SELECT test_bms_compare('(b 5)', NULL) AS result; SELECT test_bms_compare(NULL, '(b 5)') AS result; SELECT test_bms_compare(NULL, NULL) AS result; @@ -232,40 +222,37 @@ SELECT length(test_bms_add_range('(b 1 2)', 200, 250)) AS result; SELECT test_bms_add_range('(b 5)', 5, NULL) AS result; SELECT test_bms_add_range('(b 5)', NULL, 10) AS result; SELECT test_bms_add_range('(b 5)', NULL, NULL) AS result; +-- NULL inputs SELECT test_bms_add_range(NULL, 5, 10) AS result; SELECT test_bms_add_range(NULL, 10, 5) AS result; -SELECT test_bms_add_range(NULL, NULL, NULL) AS result; -- bms_membership() SELECT test_bms_membership('(b)') AS result; SELECT test_bms_membership('(b 42)') AS result; SELECT test_bms_membership('(b 1 2)') AS result; --- Test module check +-- NULL input SELECT test_bms_membership(NULL) AS result; -- bms_is_empty() SELECT test_bms_is_empty(NULL) AS result; SELECT test_bms_is_empty('(b)') AS result; SELECT test_bms_is_empty('(b 1)') AS result; --- Test module check -SELECT test_bms_is_empty(NULL) AS result; -- bms_singleton_member() 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; --- Test module check +-- NULL input 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 @@ -286,27 +273,25 @@ SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result; 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; --- Test module checks -SELECT test_bms_next_member('', 5) AS result; -SELECT test_bms_next_member('(b 5)', NULL) AS result; +-- NULL inputs SELECT test_bms_next_member(NULL, 5) AS result; -SELECT test_bms_next_member(NULL, NULL) AS result; -SELECT test_bms_prev_member('', 5) AS result; -SELECT test_bms_prev_member('(b 5)', NULL) AS result; SELECT test_bms_prev_member(NULL, 5) AS result; +-- Test module check +SELECT test_bms_next_member('(b 5 10)', NULL) AS result; +SELECT test_bms_prev_member('(b 5 10)', NULL) AS result; -- bms_hash_value() 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; --- Test module check +-- NULL input SELECT test_bms_hash_value(NULL) AS result; -- bms_overlap() 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; --- Test module checks +-- NULL inputs SELECT test_bms_overlap('(b 5)', NULL) AS result; SELECT test_bms_overlap(NULL, '(b 5)') AS result; SELECT test_bms_overlap(NULL, NULL) AS result; @@ -321,7 +306,7 @@ SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31), -- Is subset with shorter word counts? SELECT test_bms_is_subset('(b 5 100)', '(b 5)') AS result; SELECT test_bms_is_subset('(b 1 2 50 100)', '(b 1 2)') AS result; --- Test module checks +-- NULL inputs SELECT test_bms_is_subset('(b 5)', NULL) AS result; SELECT test_bms_is_subset(NULL, '(b 5)') AS result; SELECT test_bms_is_subset(NULL, NULL) AS result; @@ -350,16 +335,10 @@ SELECT test_bms_subset_compare('(b 1 2)', '(b 1 2 64)') AS result; SELECT test_bms_subset_compare('(b 64 200)', '(b 1 201)') AS result; SELECT test_bms_subset_compare('(b 1 64 65)', '(b 1 2 64)') AS result; SELECT test_bms_subset_compare('(b 2 64 128)', '(b 1 65)') AS result; --- Test module checks -SELECT test_bms_subset_compare('(b 5)', NULL) AS result; -SELECT test_bms_subset_compare(NULL, '(b 5)') AS result; -SELECT test_bms_subset_compare(NULL, NULL) AS result; -- bms_copy() SELECT test_bms_copy(NULL) AS result; SELECT test_bms_copy('(b 1 3 5 7)') AS result; --- Test module check -SELECT test_bms_copy(NULL) AS result; -- bms_add_members() SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result; @@ -388,7 +367,7 @@ SELECT (test_bitmap_match('(b 1 3 5)', '(b 2 4 6)') = 0) = test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result; SELECT (test_bitmap_match('(b)', '(b)') = 0) = test_bms_equal('(b)', '(b)') AS result; --- Test module checks +-- NULL inputs SELECT test_bitmap_match('(b 5)', NULL) AS result; SELECT test_bitmap_match(NULL, '(b 5)') AS result; SELECT test_bitmap_match(NULL, NULL) AS result; @@ -404,7 +383,7 @@ SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result; -- Overlap list with negative numbers SELECT test_bms_overlap_list('(b 5 10)', ARRAY[-1,5]) AS result; -- error SELECT test_bms_overlap_list('(b 1 2 3)', ARRAY[-5,-1,0]) AS result; -- error --- Test module checks +-- NULL inputs SELECT test_bms_overlap_list('(b 5)', NULL) AS result; SELECT test_bms_overlap_list(NULL, ARRAY[1,2,3]) AS result; SELECT test_bms_overlap_list(NULL, NULL) AS result; @@ -412,6 +391,7 @@ SELECT test_bms_overlap_list(NULL, NULL) AS result; -- bms_nonempty_difference() SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result; SELECT test_bms_nonempty_difference('(b 1 3 5)', NULL) AS result; +SELECT test_bms_nonempty_difference(NULL, NULL) AS result; 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; @@ -419,10 +399,6 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') 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; --- Test module checks -SELECT test_bms_nonempty_difference('(b 5)', NULL) AS result; -SELECT test_bms_nonempty_difference(NULL, '(b 5)') AS result; -SELECT test_bms_nonempty_difference(NULL, NULL) AS result; -- random operations SELECT test_random_operations(-1, 10000, 81920, 0) > 0 AS result; 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..0d6c2e7aa1b 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; @@ -89,100 +88,98 @@ PG_FUNCTION_INFO_V1(test_random_operations); #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, returning the + * resulting text representation of the set. + */ +#define PG_RETURN_BITMAPSET_AS_TEXT(bms) \ + PG_RETURN_TEXT_P(BITMAPSET_TO_TEXT(bms)) + +/* * 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 result generated by nodeToString(). */ 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; - - if (!PG_ARGISNULL(0)) - bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0)); + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); - 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); - 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); PG_RETURN_BOOL(result); } @@ -190,150 +187,89 @@ 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); - PG_RETURN_INT32(result); } 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); - 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); - PG_RETURN_BOOL(result); } 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); - 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); - PG_RETURN_INT32((int32) result); } 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); PG_RETURN_INT32(result); } @@ -341,212 +277,115 @@ 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); - 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); - 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); - PG_RETURN_INT32(result); } 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); - PG_RETURN_BOOL(result); } 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); - PG_RETURN_BOOL(result); } 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); - PG_RETURN_INT32((int32) result); } 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); - PG_RETURN_INT32(result); } 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 is not a singleton + * set, otherwise return the singleton member. */ - success = bms_get_singleton_member(bms, &member); - bms_free(bms); - - if (success) - PG_RETURN_INT32(member); + if (!bms_get_singleton_member(bms, &member)) + member = -1; - 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); PG_RETURN_INT32(result); } @@ -554,75 +393,57 @@ 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); - PG_RETURN_BOOL(result); } 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); - 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,47 +451,29 @@ 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); - PG_RETURN_BOOL(result); } 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); PG_RETURN_INT32(result); } @@ -678,191 +481,92 @@ 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); - - 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)); + /* left input gets recycled */ + bms1 = bms_del_members(bms1, bms2); - 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); - - 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)); + Bitmapset *bms1 = PG_ARG_GETBITMAPSET(0); + Bitmapset *bms2 = PG_ARG_GETBITMAPSET(1); - /* IMPORTANT: bms_replace_members modifies/frees the first argument */ - result_bms = bms_replace_members(bms1, bms2); + /* left input gets recycled */ + bms1 = bms_replace_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); - - PG_RETURN_TEXT_P(result); + 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. */ - - if (result_bms == NULL) - PG_RETURN_NULL(); - - result = BITMAPSET_TO_TEXT(result_bms); - bms_free(result_bms); + /* memory cleanup seems more tricky than it's worth here */ - 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); - PG_RETURN_INT32(hash_result); } 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 *)); PG_RETURN_INT32(hash_result); } @@ -870,30 +574,12 @@ 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 *)); PG_RETURN_INT32(match_result); } @@ -1031,8 +717,7 @@ test_random_operations(PG_FUNCTION_ARGS) total_ops++; } - if (bms) - bms_free(bms); + bms_free(bms); PG_RETURN_INT32(total_ops); } diff --git a/src/test/modules/test_json_parser/README b/src/test/modules/test_json_parser/README index ceccd499f43..61e7c78d588 100644 --- a/src/test/modules/test_json_parser/README +++ b/src/test/modules/test_json_parser/README @@ -6,10 +6,12 @@ This module contains two programs for testing the json parsers. - `test_json_parser_incremental` is for testing the incremental parser, It reads in a file and passes it in very small chunks (default is 60 bytes at a time) to the incremental parser. It's not meant to be a speed test but to - test the accuracy of the incremental parser. There are two option arguments, - "-c nn" specifies an alternative chunk size, and "-s" specifies using - semantic routines. The semantic routines re-output the json, although not in - a very pretty form. The required non-option argument is the input file name. + test the accuracy of the incremental parser. The option "-c nn" specifies an + alternative chunk size, "-r nn" runs a range of chunk sizes down to one byte + on the same input (with output separated by null bytes), and "-s" specifies + using semantic routines. The semantic routines re-output the json, although + not in a very pretty form. The required non-option argument is the input file + name. - `test_json_parser_perf` is for speed testing both the standard recursive descent parser and the non-recursive incremental parser. If given the `-i` flag it uses the non-recursive parser, diff --git a/src/test/modules/test_json_parser/t/002_inline.pl b/src/test/modules/test_json_parser/t/002_inline.pl index 7c8b64977ec..3dd16731e90 100644 --- a/src/test/modules/test_json_parser/t/002_inline.pl +++ b/src/test/modules/test_json_parser/t/002_inline.pl @@ -33,23 +33,37 @@ sub test print $fh "$json"; close($fh); + # The -r mode runs the parser in a loop, with output separated by nulls. + # Unpack that as a list of null-terminated ASCII strings (Z*) and check that + # each run produces the same result. + my ($all_stdout, $all_stderr) = + run_command([ @exe, "-r", $chunk, $fname ]); + + my @stdout = unpack("(Z*)*", $all_stdout); + my @stderr = unpack("(Z*)*", $all_stderr); + + is(scalar @stdout, $chunk, "$name: stdout has correct number of entries"); + is(scalar @stderr, $chunk, "$name: stderr has correct number of entries"); + + my $i = 0; + foreach my $size (reverse(1 .. $chunk)) { - my ($stdout, $stderr) = run_command([ @exe, "-c", $size, $fname ]); - if (defined($params{error})) { - unlike($stdout, qr/SUCCESS/, + unlike($stdout[$i], qr/SUCCESS/, "$name, chunk size $size: test fails"); - like($stderr, $params{error}, + like($stderr[$i], $params{error}, "$name, chunk size $size: correct error output"); } else { - like($stdout, qr/SUCCESS/, + like($stdout[$i], qr/SUCCESS/, "$name, chunk size $size: test succeeds"); - is($stderr, "", "$name, chunk size $size: no error output"); + is($stderr[$i], "", "$name, chunk size $size: no error output"); } + + $i++; } } diff --git a/src/test/modules/test_json_parser/test_json_parser_incremental.c b/src/test/modules/test_json_parser/test_json_parser_incremental.c index d1e3e4ab4ea..8c78061ee46 100644 --- a/src/test/modules/test_json_parser/test_json_parser_incremental.c +++ b/src/test/modules/test_json_parser/test_json_parser_incremental.c @@ -12,9 +12,14 @@ * the parser in very small chunks. In practice you would normally use * much larger chunks, but doing this makes it more likely that the * full range of increment handling, especially in the lexer, is exercised. + * * If the "-c SIZE" option is provided, that chunk size is used instead * of the default of 60. * + * If the "-r SIZE" option is provided, a range of chunk sizes from SIZE down to + * 1 are run sequentially. A null byte is printed to the streams after each + * iteration. + * * If the -s flag is given, the program does semantic processing. This should * just mirror back the json, albeit with white space changes. * @@ -88,8 +93,8 @@ main(int argc, char **argv) StringInfoData json; int n_read; size_t chunk_size = DEFAULT_CHUNK_SIZE; + bool run_chunk_ranges = false; struct stat statbuf; - off_t bytes_left; const JsonSemAction *testsem = &nullSemAction; char *testfile; int c; @@ -102,11 +107,14 @@ main(int argc, char **argv) if (!lex) pg_fatal("out of memory"); - while ((c = getopt(argc, argv, "c:os")) != -1) + while ((c = getopt(argc, argv, "r:c:os")) != -1) { switch (c) { - case 'c': /* chunksize */ + case 'r': /* chunk range */ + run_chunk_ranges = true; + /* fall through */ + case 'c': /* chunk size */ chunk_size = strtou64(optarg, NULL, 10); if (chunk_size > BUFSIZE) pg_fatal("chunk size cannot exceed %d", BUFSIZE); @@ -135,8 +143,6 @@ main(int argc, char **argv) exit(1); } - makeJsonLexContextIncremental(lex, PG_UTF8, need_strings); - setJsonLexContextOwnsTokens(lex, lex_owns_tokens); initStringInfo(&json); if ((json_file = fopen(testfile, PG_BINARY_R)) == NULL) @@ -145,61 +151,88 @@ main(int argc, char **argv) if (fstat(fileno(json_file), &statbuf) != 0) pg_fatal("error statting input: %m"); - bytes_left = statbuf.st_size; - - for (;;) + do { - /* We will break when there's nothing left to read */ - - if (bytes_left < chunk_size) - chunk_size = bytes_left; + /* + * This outer loop only repeats in -r mode. Reset the parse state and + * our position in the input file for the inner loop, which performs + * the incremental parsing. + */ + off_t bytes_left = statbuf.st_size; + size_t to_read = chunk_size; - n_read = fread(buff, 1, chunk_size, json_file); - if (n_read < chunk_size) - pg_fatal("error reading input file: %d", ferror(json_file)); + makeJsonLexContextIncremental(lex, PG_UTF8, need_strings); + setJsonLexContextOwnsTokens(lex, lex_owns_tokens); - appendBinaryStringInfo(&json, buff, n_read); + rewind(json_file); + resetStringInfo(&json); - /* - * Append some trailing junk to the buffer passed to the parser. This - * helps us ensure that the parser does the right thing even if the - * chunk isn't terminated with a '\0'. - */ - appendStringInfoString(&json, "1+23 trailing junk"); - bytes_left -= n_read; - if (bytes_left > 0) + for (;;) { - result = pg_parse_json_incremental(lex, testsem, - json.data, n_read, - false); - if (result != JSON_INCOMPLETE) + /* We will break when there's nothing left to read */ + + if (bytes_left < to_read) + to_read = bytes_left; + + n_read = fread(buff, 1, to_read, json_file); + if (n_read < to_read) + pg_fatal("error reading input file: %d", ferror(json_file)); + + appendBinaryStringInfo(&json, buff, n_read); + + /* + * Append some trailing junk to the buffer passed to the parser. + * This helps us ensure that the parser does the right thing even + * if the chunk isn't terminated with a '\0'. + */ + appendStringInfoString(&json, "1+23 trailing junk"); + bytes_left -= n_read; + if (bytes_left > 0) { - fprintf(stderr, "%s\n", json_errdetail(result, lex)); - ret = 1; - goto cleanup; + result = pg_parse_json_incremental(lex, testsem, + json.data, n_read, + false); + if (result != JSON_INCOMPLETE) + { + fprintf(stderr, "%s\n", json_errdetail(result, lex)); + ret = 1; + goto cleanup; + } + resetStringInfo(&json); } - resetStringInfo(&json); - } - else - { - result = pg_parse_json_incremental(lex, testsem, - json.data, n_read, - true); - if (result != JSON_SUCCESS) + else { - fprintf(stderr, "%s\n", json_errdetail(result, lex)); - ret = 1; - goto cleanup; + result = pg_parse_json_incremental(lex, testsem, + json.data, n_read, + true); + if (result != JSON_SUCCESS) + { + fprintf(stderr, "%s\n", json_errdetail(result, lex)); + ret = 1; + goto cleanup; + } + if (!need_strings) + printf("SUCCESS!\n"); + break; } - if (!need_strings) - printf("SUCCESS!\n"); - break; } - } cleanup: + freeJsonLexContext(lex); + + /* + * In -r mode, separate output with nulls so that the calling test can + * split it up, decrement the chunk size, and loop back to the top. + * All other modes immediately fall out of the loop and exit. + */ + if (run_chunk_ranges) + { + fputc('\0', stdout); + fputc('\0', stderr); + } + } while (run_chunk_ranges && (--chunk_size > 0)); + fclose(json_file); - freeJsonLexContext(lex); free(json.data); free(lex); |