test_bitmapset: Expand more the test coverage
authorMichael Paquier <[email protected]>
Mon, 29 Sep 2025 06:17:27 +0000 (15:17 +0900)
committerMichael Paquier <[email protected]>
Mon, 29 Sep 2025 06:17:27 +0000 (15:17 +0900)
This commit expands the set of tests added by 00c3d87a5cab, to bring the
coverage of bitmapset.c close to 100% by addressing a lot of corner
cases (most of these relate to word counts and reallocations).

Some of the functions of this module also have their own idea of the
result to return depending on the input values given.  These are
specific to the module, still let's add more coverage for all of them.

Some comments are made more consistent in the tests, while on it.

Author: Greg Burd <[email protected]>
Reviewed-by: Michael Paquier <[email protected]>
Discussion: https://postgr.es/m/[email protected]

src/test/modules/test_bitmapset/expected/test_bitmapset.out
src/test/modules/test_bitmapset/sql/test_bitmapset.sql
src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
src/test/modules/test_bitmapset/test_bitmapset.c

index abbfef1f7a61fe8883a8b601d967ca57fa2795a8..be7b6399c826fd28c2ca99200fb9b792ad200e3e 100644 (file)
@@ -21,6 +21,13 @@ SELECT test_bms_make_singleton(1000) AS result;
  (b 1000)
 (1 row)
 
+-- Test module check
+SELECT test_bms_make_singleton(NULL) AS result;
+ result 
+--------
+(1 row)
+
 -- bms_add_member()
 SELECT test_bms_add_member('(b 1)', -1); -- error
 ERROR:  negative bitmapset member not allowed
@@ -52,6 +59,13 @@ SELECT test_bms_add_member('(b 10)', 10) AS result;
  (b 10)
 (1 row)
 
+-- Test module check
+SELECT test_bms_add_member('(b)', NULL) AS result;
+ result 
+--------
+(1 row)
+
 -- bms_replace_members()
 SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result;
   result   
@@ -83,6 +97,38 @@ SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result;
  (b 3 5 7)
 (1 row)
 
+-- Force repalloc() with larger set
+SELECT test_bms_replace_members('(b 1 2 3 4 5)', '(b 500 600)') AS result;
+   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
@@ -124,6 +170,101 @@ SELECT test_bms_del_member(test_bms_add_range('(b)', 30, 34), 32) AS result;
  (b 30 31 33 34)
 (1 row)
 
+-- Force word count changes
+SELECT test_bms_del_member('(b 1 200)', 200) AS result;
+ result 
+--------
+ (b 1)
+(1 row)
+
+SELECT test_bms_del_member('(b 1 50 100 200)', 200) AS result;
+    result    
+--------------
+ (b 1 50 100)
+(1 row)
+
+SELECT test_bms_del_member('(b 1 50 100 200)', 100) AS result;
+    result    
+--------------
+ (b 1 50 200)
+(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 
+--------
+(1 row)
+
+-- bms_del_members()
+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;
+ result 
+--------
+ (b 10)
+(1 row)
+
+SELECT test_bms_del_members('(b 1 2 3)', '(b 2)') AS result;
+ result  
+---------
+ (b 1 3)
+(1 row)
+
+SELECT test_bms_del_members('(b 5 100)', '(b 100)') AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_del_members('(b 5 100 200)', '(b 200)') AS result;
+  result   
+-----------
+ (b 5 100)
+(1 row)
+
+-- Force word count changes
+SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 1 2)') AS result;
+     result      
+-----------------
+ (b 100 200 300)
+(1 row)
+
+SELECT test_bms_del_members('(b 1 2 100 200 300)', '(b 200 300)') AS result;
+   result    
+-------------
+ (b 1 2 100)
+(1 row)
+
+-- Test module checks
+SELECT test_bms_del_members('(b 5)', NULL) AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_del_members(NULL, '(b 5)') AS result;
+ result 
+--------
+(1 row)
+
 -- bms_join()
 SELECT test_bms_join('(b 1 3 5)', NULL) AS result;
   result   
@@ -149,8 +290,40 @@ SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result;
  (b 1 3 4 5)
 (1 row)
 
+-- Force word count changes
+SELECT test_bms_join('(b 5)', '(b 100)') AS result;
+  result   
+-----------
+ (b 5 100)
+(1 row)
+
+SELECT test_bms_join('(b 1 2)', '(b 100 200 300)') AS result;
+       result        
+---------------------
+ (b 1 2 100 200 300)
+(1 row)
+
+-- Test module checks
+SELECT test_bms_join('(b 5)', NULL) AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_join(NULL, '(b 5)') AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_join(NULL, NULL) AS result;
+ result 
+--------
+(1 row)
+
 -- bms_union()
--- Overlapping sets.
+-- Overlapping sets
 SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result;
    result    
 -------------
@@ -181,6 +354,38 @@ 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
+SELECT test_bms_union('(b 1 2)', '(b 100 300)') AS result;
+     result      
+-----------------
+ (b 1 2 100 300)
+(1 row)
+
+SELECT test_bms_union('(b 100 300)', '(b 1 2)') AS result;
+     result      
+-----------------
+ (b 1 2 100 300)
+(1 row)
+
+-- Test module checks
+SELECT test_bms_union('(b 5)', NULL) AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_union(NULL, '(b 5)') AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_union(NULL, NULL) AS result;
+ result 
+--------
+(1 row)
+
 -- bms_intersect()
 -- Overlapping sets
 SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result;
@@ -196,13 +401,51 @@ SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result;
  
 (1 row)
 
--- Intersect with empty.
+-- Intersect with empty
 SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result;
  result 
 --------
  
 (1 row)
 
+-- Intersect with varrying word counts
+SELECT test_bms_intersect('(b 1 300)', '(b 1 2 3 4 5)') AS result;
+ result 
+--------
+ (b 1)
+(1 row)
+
+SELECT test_bms_intersect('(b 1 2 3 4 5)', '(b 1 300)') AS result;
+ result 
+--------
+ (b 1)
+(1 row)
+
+-- Test module checks
+SELECT test_bms_intersect('(b 1)', '(b 2)') AS result;
+ result 
+--------
+(1 row)
+
+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()
 -- Overlapping sets
 SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result;
@@ -218,7 +461,7 @@ SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result;
  
 (1 row)
 
--- Intersect with empty.
+-- Intersect with empty
 SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result;
  result 
 --------
@@ -232,6 +475,31 @@ 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)
+
+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()
 -- Overlapping sets
 SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7)') AS result;
@@ -271,6 +539,44 @@ SELECT test_bms_difference(
  (b 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49)
 (1 row)
 
+-- Difference with different word counts
+SELECT test_bms_difference('(b 5 100)', '(b 5)') AS result;
+ result  
+---------
+ (b 100)
+(1 row)
+
+SELECT test_bms_difference('(b 1 2 100 200)', '(b 1 2)') AS result;
+   result    
+-------------
+ (b 100 200)
+(1 row)
+
+-- Test module checks
+SELECT test_bms_difference('(b 5)', '(b 5 10)') AS result;
+ result 
+--------
+(1 row)
+
+SELECT test_bms_difference('(b 5)', NULL) AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+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()
 SELECT test_bms_is_member('(b)', -5); -- error
 ERROR:  negative bitmapset member not allowed
@@ -298,6 +604,13 @@ SELECT test_bms_is_member('(b)', 1) AS result;
  f
 (1 row)
 
+-- Test module check
+SELECT test_bms_is_member('(b 5)', NULL) AS result;
+ result 
+--------
+ f
+(1 row)
+
 -- bms_member_index()
 SELECT test_bms_member_index(NULL, 1) AS result;
  result 
@@ -323,45 +636,77 @@ SELECT test_bms_member_index('(b 1 3 5)', 3) AS result;
       1
 (1 row)
 
--- bms_num_members()
-SELECT test_bms_num_members('(b)') AS result;
+-- Member index with various word positions
+SELECT test_bms_member_index('(b 100 200)', 100) AS result;
  result 
 --------
       0
 (1 row)
 
-SELECT test_bms_num_members('(b 1 3 5)') AS result;
+SELECT test_bms_member_index('(b 100 200)', 200) AS result;
  result 
 --------
-      3
+      1
 (1 row)
 
-SELECT test_bms_num_members('(b 2 4 6 8 10)') AS result;
+SELECT test_bms_member_index('(b 1 50 100 200)', 200) AS result;
  result 
 --------
-      5
+      3
 (1 row)
 
--- test_bms_equal()
-SELECT test_bms_equal('(b)', '(b)') AS result;
+-- Test module checks
+SELECT test_bms_member_index('', 5) AS result;
  result 
 --------
- t
+     -1
 (1 row)
 
-SELECT test_bms_equal('(b)', '(b 1 3 5)') AS result;
+SELECT test_bms_member_index(NULL, 5) AS result;
  result 
 --------
- f
+     -1
 (1 row)
 
-SELECT test_bms_equal('(b 1 3 5)', '(b)') AS result;
+-- bms_num_members()
+SELECT test_bms_num_members('(b)') AS result;
  result 
 --------
- f
+      0
 (1 row)
 
-SELECT test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result;
+SELECT test_bms_num_members('(b 1 3 5)') AS result;
+ result 
+--------
+      3
+(1 row)
+
+SELECT test_bms_num_members('(b 2 4 6 8 10)') AS result;
+ result 
+--------
+      5
+(1 row)
+
+-- test_bms_equal()
+SELECT test_bms_equal('(b)', '(b)') AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_equal('(b)', '(b 1 3 5)') AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_equal('(b 1 3 5)', '(b)') AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result;
  result 
 --------
  t
@@ -373,6 +718,38 @@ SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result;
  f
 (1 row)
 
+-- Equal with different word counts
+SELECT test_bms_equal('(b 5)', '(b 100)') AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result;
+ result 
+--------
+ f
+(1 row)
+
+-- Test module checks
+SELECT test_bms_equal('(b 5)', NULL) AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_equal(NULL, '(b 5)') AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_equal(NULL, NULL) AS result;
+ result 
+--------
+ t
+(1 row)
+
 -- bms_compare()
 SELECT test_bms_compare('(b)', '(b)') AS result;
  result 
@@ -419,6 +796,25 @@ SELECT test_bms_compare(
      -1
 (1 row)
 
+-- Test module checks
+SELECT test_bms_compare('(b 5)', NULL) AS result;
+ result 
+--------
+      1
+(1 row)
+
+SELECT test_bms_compare(NULL, '(b 5)') AS result;
+ result 
+--------
+     -1
+(1 row)
+
+SELECT test_bms_compare(NULL, NULL) AS result;
+ result 
+--------
+      0
+(1 row)
+
 -- bms_add_range()
 SELECT test_bms_add_range('(b)', -5, 10); -- error
 ERROR:  negative bitmapset member not allowed
@@ -428,282 +824,597 @@ SELECT test_bms_add_range('(b)', 5, 7) AS result;
  (b 5 6 7)
 (1 row)
 
-SELECT test_bms_add_range('(b)', 5, 5) AS result;
+SELECT test_bms_add_range('(b)', 5, 5) AS result;
+ result 
+--------
+ (b 5)
+(1 row)
+
+SELECT test_bms_add_range('(b 1 10)', 5, 7) AS result;
+     result     
+----------------
+ (b 1 5 6 7 10)
+(1 row)
+
+-- Word boundary of 31
+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;
+       result       
+--------------------
+ (b 62 63 64 65 66)
+(1 row)
+
+-- Large range
+SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result;
+ result 
+--------
+   3898
+(1 row)
+
+-- Force reallocations
+SELECT length(test_bms_add_range('(b)', 0, 200)) AS result;
+ result 
+--------
+    697
+(1 row)
+
+SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result;
+ result 
+--------
+    508
+(1 row)
+
+-- Force word count expansion
+SELECT test_bms_add_range('(b 5)', 100, 105) AS result;
+            result             
+-------------------------------
+ (b 5 100 101 102 103 104 105)
+(1 row)
+
+SELECT length(test_bms_add_range('(b 1 2)', 200, 250)) AS result;
+ result 
+--------
+    211
+(1 row)
+
+-- Test module checks
+SELECT test_bms_add_range('(b 5)', 5, NULL) AS result;
+ result 
+--------
+(1 row)
+
+SELECT test_bms_add_range('(b 5)', NULL, 10) AS result;
+ result 
+--------
+(1 row)
+
+SELECT test_bms_add_range('(b 5)', NULL, NULL) AS result;
+ result 
+--------
+(1 row)
+
+SELECT test_bms_add_range(NULL, 5, 10) AS result;
+      result      
+------------------
+ (b 5 6 7 8 9 10)
+(1 row)
+
+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()
+SELECT test_bms_membership('(b)') AS result;
+ result 
+--------
+      0
+(1 row)
+
+SELECT test_bms_membership('(b 42)') AS result;
+ result 
+--------
+      1
+(1 row)
+
+SELECT test_bms_membership('(b 1 2)') AS result;
+ result 
+--------
+      2
+(1 row)
+
+-- Test module check
+SELECT test_bms_membership(NULL) AS result;
+ result 
+--------
+      0
+(1 row)
+
+-- bms_is_empty()
+SELECT test_bms_is_empty(NULL) AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_is_empty('(b)') AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_is_empty('(b 1)') AS result;
+ 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
+SELECT test_bms_singleton_member('(b 1 2)'); -- error
+ERROR:  bitmapset has multiple members
+SELECT test_bms_singleton_member('(b 42)') AS result;
+ result 
+--------
+     42
+(1 row)
+
+-- Test module check
+SELECT test_bms_singleton_member(NULL) AS result;
+ result 
+--------
+       
+(1 row)
+
+-- bms_get_singleton_member()
+SELECT test_bms_get_singleton_member('(b)', 1000);
+ 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 row)
+
+-- Singletone, returns sole member
+SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result;
+ result 
+--------
+    400
+(1 row)
+
+-- Test module checks
+SELECT test_bms_get_singleton_member('', 1000) AS result;
+ result 
+--------
+   1000
+(1 row)
+
+SELECT test_bms_get_singleton_member(NULL, -1) AS result;
+ result 
+--------
+     -1
+(1 row)
+
+-- bms_next_member() and bms_prev_member()
+-- First member
+SELECT test_bms_next_member('(b 5 10 15 20)', -1) AS result;
+ result 
+--------
+      5
+(1 row)
+
+-- Second member
+SELECT test_bms_next_member('(b 5 10 15 20)', 5) AS result;
+ result 
+--------
+     10
+(1 row)
+
+-- Member past the end
+SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result;
+ result 
+--------
+     -2
+(1 row)
+
+-- Empty set
+SELECT test_bms_next_member('(b)', -1) AS result;
+ result 
+--------
+     -2
+(1 row)
+
+-- Last member
+SELECT test_bms_prev_member('(b 5 10 15 20)', 21) AS result;
+ result 
+--------
+     20
+(1 row)
+
+-- Penultimate member
+SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result;
+ result 
+--------
+     15
+(1 row)
+
+-- Past beginning member
+SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result;
+ result 
+--------
+     -2
+(1 row)
+
+-- Empty set
+SELECT test_bms_prev_member('(b)', 100) AS result;
+ result 
+--------
+     -2
+(1 row)
+
+-- Negative prevbit should result in highest possible bit in set
+SELECT test_bms_prev_member('(b 0 63 64 127)', -1) AS result;
+ 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)
+
+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;
+ result 
+--------
+     -2
+(1 row)
+
+SELECT test_bms_prev_member('(b 5)', NULL) AS result;
+ result 
+--------
+     -2
+(1 row)
+
+SELECT test_bms_prev_member(NULL, 5) AS result;
+ result 
+--------
+     -2
+(1 row)
+
+-- bms_hash_value()
+SELECT test_bms_hash_value('(b)') = 0 AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_hash_value('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS result;
+ result 
+--------
+ t
+(1 row)
+
+-- Test module check
+SELECT test_bms_hash_value(NULL) AS result;
+ result 
+--------
+      0
+(1 row)
+
+-- bms_overlap()
+SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result;
  result 
 --------
- (b 5)
+ t
 (1 row)
 
-SELECT test_bms_add_range('(b 1 10)', 5, 7) AS result;
-     result     
-----------------
- (b 1 5 6 7 10)
+SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6)') AS result;
+ result 
+--------
+ f
 (1 row)
 
--- Word boundary of 31
-SELECT test_bms_add_range('(b)', 30, 34) AS result;
-       result       
---------------------
- (b 30 31 32 33 34)
+SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result;
+ result 
+--------
+ f
 (1 row)
 
--- Word boundary of 63
-SELECT test_bms_add_range('(b)', 62, 66) AS result;
-       result       
---------------------
- (b 62 63 64 65 66)
+-- Test module checks
+SELECT test_bms_overlap('(b 5)', NULL) AS result;
+ result 
+--------
+ f
 (1 row)
 
--- Large range
-SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result;
+SELECT test_bms_overlap(NULL, '(b 5)') AS result;
  result 
 --------
-   3898
+ f
 (1 row)
 
--- Force reallocations
-SELECT length(test_bms_add_range('(b)', 0, 200)) AS result;
+SELECT test_bms_overlap(NULL, NULL) AS result;
  result 
 --------
-    697
+ f
 (1 row)
 
-SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result;
+-- bms_is_subset()
+SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result;
  result 
 --------
-    508
+ t
 (1 row)
 
--- bms_membership()
-SELECT test_bms_membership('(b)') AS result;
+SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5)') AS result;
  result 
 --------
-      0
+ t
 (1 row)
 
-SELECT test_bms_membership('(b 42)') AS result;
+SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3)') AS result;
  result 
 --------
-      1
+ f
 (1 row)
 
-SELECT test_bms_membership('(b 1 2)') AS result;
+SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result;
  result 
 --------
-      2
+ f
 (1 row)
 
--- bms_is_empty()
-SELECT test_bms_is_empty(NULL) AS result;
+SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31),
+                          test_bms_add_range(NULL, 0, 63)) AS result;
  result 
 --------
  t
 (1 row)
 
-SELECT test_bms_is_empty('(b)') AS result;
+-- Is subset with shorter word counts?
+SELECT test_bms_is_subset('(b 5 100)', '(b 5)') AS result;
  result 
 --------
- t
+ f
 (1 row)
 
-SELECT test_bms_is_empty('(b 1)') AS result;
+SELECT test_bms_is_subset('(b 1 2 50 100)', '(b 1 2)') AS result;
  result 
 --------
  f
 (1 row)
 
--- bms_singleton_member()
-SELECT test_bms_singleton_member('(b 1 2)'); -- error
-ERROR:  bitmapset has multiple members
-SELECT test_bms_singleton_member('(b 42)') AS result;
+-- Test module checks
+SELECT test_bms_is_subset('(b 5)', NULL) AS result;
  result 
 --------
-     42
+ f
 (1 row)
 
--- bms_get_singleton_member()
--- Not a singleton, returns input default
-SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result;
+SELECT test_bms_is_subset(NULL, '(b 5)') AS result;
  result 
 --------
-   1000
+ t
 (1 row)
 
--- Singletone, returns sole member
-SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result;
+SELECT test_bms_is_subset(NULL, NULL) AS result;
  result 
 --------
-    400
+ t
 (1 row)
 
--- bms_next_member() and bms_prev_member()
--- First member
-SELECT test_bms_next_member('(b 5 10 15 20)', -1) AS result;
+-- bms_subset_compare()
+SELECT test_bms_subset_compare(NULL, NULL) AS result;
  result 
 --------
-      5
+      0
 (1 row)
 
--- Second member
-SELECT test_bms_next_member('(b 5 10 15 20)', 5) AS result;
+SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result;
  result 
 --------
-     10
+      1
 (1 row)
 
--- Member past the end
-SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result;
+SELECT test_bms_subset_compare('(b)', '(b)') AS result;
  result 
 --------
-     -2
+      0
 (1 row)
 
--- Empty set
-SELECT test_bms_next_member('(b)', -1) AS result;
+SELECT test_bms_subset_compare('(b)', '(b 1)') AS result;
  result 
 --------
-     -2
+      1
 (1 row)
 
--- Last member
-SELECT test_bms_prev_member('(b 5 10 15 20)', 21) AS result;
+SELECT test_bms_subset_compare('(b 1)', '(b)') AS result;
  result 
 --------
-     20
+      2
 (1 row)
 
--- Penultimate member
-SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result;
+SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result;
  result 
 --------
-     15
+      2
 (1 row)
 
--- Past beginning member
-SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result;
+SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result;
  result 
 --------
-     -2
+      0
 (1 row)
 
--- Empty set
-SELECT test_bms_prev_member('(b)', 100) AS result;
+SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result;
  result 
 --------
-     -2
+      1
 (1 row)
 
--- bms_hash_value()
-SELECT test_bms_hash_value('(b)') = 0 AS result;
+SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result;
  result 
 --------
- t
+      2
 (1 row)
 
-SELECT test_bms_hash_value('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare('(b 1 2)', '(b 1 3)') AS result;
  result 
 --------
- t
+      3
 (1 row)
 
-SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS result;
+SELECT test_bms_subset_compare('(b 1 2)', '(b 1 4)') AS result;
  result 
 --------
- t
+      3
 (1 row)
 
--- bms_overlap()
-SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result;
+SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 64)') AS result;
  result 
 --------
- t
+      1
 (1 row)
 
-SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6)') AS result;
+SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3)') AS result;
  result 
 --------
- f
+      2
 (1 row)
 
-SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3 65)') AS result;
  result 
 --------
- f
+      3
 (1 row)
 
--- bms_is_subset()
-SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare('(b 1 3)', '(b 2 4)') AS result;
  result 
 --------
- t
+      3
 (1 row)
 
-SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare('(b 1)', '(b 64)') AS result;
  result 
 --------
- t
+      3
 (1 row)
 
-SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3)') AS result;
+SELECT test_bms_subset_compare('(b 0)', '(b 32)') AS result;
  result 
 --------
- f
+      3
 (1 row)
 
-SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result;
+SELECT test_bms_subset_compare('(b 0)', '(b 64)') AS result;
  result 
 --------
- f
+      3
 (1 row)
 
-SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31),
-                          test_bms_add_range(NULL, 0, 63)) AS result;
+SELECT test_bms_subset_compare('(b 64)', '(b 1)') AS result;
  result 
 --------
- t
+      3
 (1 row)
 
--- bms_subset_compare()
-SELECT test_bms_subset_compare(NULL, NULL) AS result;
+SELECT test_bms_subset_compare('(b 1 2)', '(b 1 2 64)') AS result;
  result 
 --------
-      0
+      1
 (1 row)
 
-SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result;
+SELECT test_bms_subset_compare('(b 64 200)', '(b 1 201)') AS result;
  result 
 --------
-      2
+      3
 (1 row)
 
-SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result;
+SELECT test_bms_subset_compare('(b 1 64 65)', '(b 1 2 64)') AS result;
  result 
 --------
-      1
+      3
 (1 row)
 
-SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result;
+SELECT test_bms_subset_compare('(b 2 64 128)', '(b 1 65)') AS result;
  result 
 --------
-      2
+      3
 (1 row)
 
-SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result;
+-- Test module checks
+SELECT test_bms_subset_compare('(b 5)', NULL) AS result;
  result 
 --------
-      1
+      2
 (1 row)
 
-SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare(NULL, '(b 5)') AS result;
  result 
 --------
-      0
+      1
 (1 row)
 
-SELECT test_bms_subset_compare('(b 1 3 5)', '(b 2 4 6)') AS result;
+SELECT test_bms_subset_compare(NULL, NULL) AS result;
  result 
 --------
-      3
+      0
 (1 row)
 
 -- bms_copy()
@@ -719,13 +1430,14 @@ SELECT test_bms_copy('(b 1 3 5 7)') AS result;
  (b 1 3 5 7)
 (1 row)
 
--- bms_add_members()
-SELECT test_bms_add_member('(b)', 1000); -- error
- test_bms_add_member 
----------------------
- (b 1000)
+-- 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    
 -------------
@@ -769,6 +1481,13 @@ SELECT test_bitmap_hash('(b 1 3 5)') != test_bitmap_hash('(b 2 4 6)') AS result;
  t
 (1 row)
 
+-- Test module check
+SELECT test_bitmap_hash(NULL) AS result;
+ result 
+--------
+      0
+(1 row)
+
 -- bitmap_match()
 SELECT test_bitmap_match('(b)', '(b)') AS result;
  result 
@@ -828,6 +1547,25 @@ SELECT (test_bitmap_match('(b)', '(b)') = 0) =
  t
 (1 row)
 
+-- Test module checks
+SELECT test_bitmap_match('(b 5)', NULL) AS result;
+ result 
+--------
+      1
+(1 row)
+
+SELECT test_bitmap_match(NULL, '(b 5)') AS result;
+ result 
+--------
+      1
+(1 row)
+
+SELECT test_bitmap_match(NULL, NULL) AS result;
+ result 
+--------
+      0
+(1 row)
+
 -- bms_overlap_list()
 SELECT test_bms_overlap_list('(b 0)', ARRAY[0]) AS result;
  result 
@@ -866,6 +1604,30 @@ SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result;
  f
 (1 row)
 
+-- Overlap list with negative numbers
+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
+SELECT test_bms_overlap_list('(b 5)', NULL) AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_overlap_list(NULL, ARRAY[1,2,3]) AS result;
+ result 
+--------
+ f
+(1 row)
+
+SELECT test_bms_overlap_list(NULL, NULL) AS result;
+ result 
+--------
+ f
+(1 row)
+
 -- bms_nonempty_difference()
 SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result;
  result 
@@ -897,6 +1659,44 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result;
  f
 (1 row)
 
+-- Difference with different word counts
+SELECT test_bms_nonempty_difference('(b 5)', '(b 100)') AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_nonempty_difference('(b 100)', '(b 5)') AS result;
+ result 
+--------
+ t
+(1 row)
+
+SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 100)') AS result;
+ 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 
index 2b2c72c876b3ca70db2d3446e5844d5ae2a15d71..c6e6bce60a38b2f2a4e1b27237340c6797ff9b93 100644 (file)
@@ -6,6 +6,8 @@ SELECT test_bms_make_singleton(-1);
 SELECT test_bms_make_singleton(42) AS result;
 SELECT test_bms_make_singleton(0) AS result;
 SELECT test_bms_make_singleton(1000) AS result;
+-- Test module check
+SELECT test_bms_make_singleton(NULL) AS result;
 
 -- bms_add_member()
 SELECT test_bms_add_member('(b 1)', -1); -- error
@@ -16,6 +18,8 @@ SELECT test_bms_add_member('(b 5)', 10) AS result;
 SELECT test_bms_add_member('(b 10)', 5) AS result;
 -- idempotent change
 SELECT test_bms_add_member('(b 10)', 10) AS result;
+-- Test module check
+SELECT test_bms_add_member('(b)', NULL) AS result;
 
 -- bms_replace_members()
 SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result;
@@ -23,6 +27,13 @@ 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;
+-- 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
@@ -34,15 +45,43 @@ SELECT test_bms_del_member('(b 1 2 3)', 2) AS result;
 SELECT test_bms_del_member(test_bms_del_member('(b 0 31 32 63 64)', 32), 63) AS result;
 -- Word boundary
 SELECT test_bms_del_member(test_bms_add_range('(b)', 30, 34), 32) AS result;
+-- Force word count changes
+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()
+SELECT test_bms_del_members('(b)', '(b 10)') AS result;
+SELECT test_bms_del_members('(b 10)', '(b 10)') AS result;
+SELECT test_bms_del_members('(b 10)', '(b 5)') AS result;
+SELECT test_bms_del_members('(b 1 2 3)', '(b 2)') AS result;
+SELECT test_bms_del_members('(b 5 100)', '(b 100)') AS result;
+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
+SELECT test_bms_del_members('(b 5)', NULL) AS result;
+SELECT test_bms_del_members(NULL, '(b 5)') AS result;
 
 -- bms_join()
 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;
+-- 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
+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;
 
 -- bms_union()
--- Overlapping sets.
+-- Overlapping sets
 SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result;
 -- Union with NULL
 SELECT test_bms_union('(b 1 3 5)', '(b)') AS result;
@@ -53,24 +92,44 @@ 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
+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
+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;
 
 -- bms_intersect()
 -- Overlapping sets
 SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result;
 -- Disjoint sets
 SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result;
--- Intersect with empty.
+-- Intersect with empty
 SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result;
+-- Intersect with varrying 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;
+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;
 
 -- bms_int_members()
 -- Overlapping sets
 SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result;
 -- Disjoint sets
 SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result;
--- Intersect with empty.
+-- Intersect with empty
 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;
+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;
 
 -- bms_difference()
 -- Overlapping sets
@@ -86,6 +145,14 @@ SELECT test_bms_difference(
          test_bms_add_range('(b)', 0, 100),
          test_bms_add_range('(b)', 50, 150)
        ) AS result;
+-- 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;
+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;
 
 -- bms_is_member()
 SELECT test_bms_is_member('(b)', -5); -- error
@@ -93,12 +160,21 @@ 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) AS result;
+-- Test module check
+SELECT test_bms_is_member('(b 5)', NULL) AS result;
 
 -- bms_member_index()
 SELECT test_bms_member_index(NULL, 1) AS result;
 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 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;
 
 -- bms_num_members()
 SELECT test_bms_num_members('(b)') AS result;
@@ -111,6 +187,13 @@ SELECT test_bms_equal('(b)', '(b 1 3 5)') AS result;
 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 5)', '(b 100)') AS result;
+SELECT test_bms_equal('(b 5 10)', '(b 100 200 300)') AS result;
+-- Test module checks
+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;
 
 -- bms_compare()
 SELECT test_bms_compare('(b)', '(b)') AS result;
@@ -123,6 +206,10 @@ SELECT test_bms_compare(
          test_bms_add_range('(b)', 0, 63),
          test_bms_add_range('(b)', 0, 64)
        ) AS result;
+-- Test module checks
+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;
 
 -- bms_add_range()
 SELECT test_bms_add_range('(b)', -5, 10); -- error
@@ -138,26 +225,47 @@ SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result;
 -- Force reallocations
 SELECT length(test_bms_add_range('(b)', 0, 200)) AS result;
 SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result;
+-- Force word count expansion
+SELECT test_bms_add_range('(b 5)', 100, 105) AS result;
+SELECT length(test_bms_add_range('(b 1 2)', 200, 250)) AS result;
+-- Test module checks
+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;
+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
+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
+SELECT test_bms_singleton_member(NULL) AS result;
 
 -- bms_get_singleton_member()
+SELECT test_bms_get_singleton_member('(b)', 1000);
 -- Not a singleton, returns input default
 SELECT test_bms_get_singleton_member('(b 3 6)', 1000) 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;
 
 -- bms_next_member() and bms_prev_member()
 -- First member
@@ -176,16 +284,32 @@ SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result;
 SELECT test_bms_prev_member('(b 5 10 15 20)', 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;
+-- Test module checks
+SELECT test_bms_next_member('', 5) AS result;
+SELECT test_bms_next_member('(b 5)', NULL) AS result;
+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;
 
 -- 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
+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
+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;
 
 -- bms_is_subset()
 SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result;
@@ -194,22 +318,50 @@ 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(test_bms_add_range(NULL, 0, 31),
                           test_bms_add_range(NULL, 0, 63)) AS result;
+-- 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
+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;
 
 -- bms_subset_compare()
 SELECT test_bms_subset_compare(NULL, NULL) AS result;
-SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result;
 SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result;
-SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result;
-SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare('(b)', '(b)') AS result;
+SELECT test_bms_subset_compare('(b)', '(b 1)') AS result;
+SELECT test_bms_subset_compare('(b 1)', '(b)') AS result;
+SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result;
 SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result;
-SELECT test_bms_subset_compare('(b 1 3 5)', '(b 2 4 6)') AS result;
+SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result;
+SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result;
+SELECT test_bms_subset_compare('(b 1 2)', '(b 1 3)') AS result;
+SELECT test_bms_subset_compare('(b 1 2)', '(b 1 4)') AS result;
+SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 64)') AS result;
+SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3)') AS result;
+SELECT test_bms_subset_compare('(b 1 3 64)', '(b 1 3 65)') AS result;
+SELECT test_bms_subset_compare('(b 1 3)', '(b 2 4)') AS result;
+SELECT test_bms_subset_compare('(b 1)', '(b 64)') AS result;
+SELECT test_bms_subset_compare('(b 0)', '(b 32)') AS result;
+SELECT test_bms_subset_compare('(b 0)', '(b 64)') AS result;
+SELECT test_bms_subset_compare('(b 64)', '(b 1)') AS result;
+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_member('(b)', 1000); -- error
 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 100 200 300)') AS result;
@@ -219,6 +371,8 @@ SELECT test_bitmap_hash('(b)') = 0 AS result;
 SELECT test_bitmap_hash('(b 1 3 5)') = test_bitmap_hash('(b 1 3 5)') AS result;
 SELECT test_bitmap_hash('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
 SELECT test_bitmap_hash('(b 1 3 5)') != test_bitmap_hash('(b 2 4 6)') AS result;
+-- Test module check
+SELECT test_bitmap_hash(NULL) AS result;
 
 -- bitmap_match()
 SELECT test_bitmap_match('(b)', '(b)') AS result;
@@ -234,6 +388,10 @@ 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
+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;
 
 -- bms_overlap_list()
 SELECT test_bms_overlap_list('(b 0)', ARRAY[0]) AS result;
@@ -243,6 +401,13 @@ 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;
 -- Empty list
 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
+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;
 
 -- bms_nonempty_difference()
 SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result;
@@ -250,6 +415,14 @@ SELECT test_bms_nonempty_difference('(b 1 3 5)', 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;
+-- Difference with different word counts
+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;
index 95f5ee02e3f3a3e84fe2b81a6853f4332d214a61..b95c4d0dda5c717580cb5619cd0e474ef8ce5a9d 100644 (file)
@@ -112,6 +112,10 @@ CREATE FUNCTION test_bms_int_members(text, text)
 RETURNS text
 AS 'MODULE_PATHNAME' LANGUAGE C;
 
+CREATE FUNCTION test_bms_del_members(text, text)
+RETURNS text
+AS 'MODULE_PATHNAME' LANGUAGE C;
+
 CREATE FUNCTION test_bms_replace_members(text, text)
 RETURNS text
 AS 'MODULE_PATHNAME' LANGUAGE C;
index 5bc4daa23f18af90b1916b13533dcf71648ee980..2e821320836bcae3a47bd824a04f169403699a5d 100644 (file)
@@ -58,6 +58,7 @@ PG_FUNCTION_INFO_V1(test_bms_member_index);
 PG_FUNCTION_INFO_V1(test_bms_add_range);
 PG_FUNCTION_INFO_V1(test_bms_add_members);
 PG_FUNCTION_INFO_V1(test_bms_int_members);
+PG_FUNCTION_INFO_V1(test_bms_del_members);
 PG_FUNCTION_INFO_V1(test_bms_replace_members);
 PG_FUNCTION_INFO_V1(test_bms_join);
 PG_FUNCTION_INFO_V1(test_bitmap_hash);
@@ -111,9 +112,6 @@ test_bms_add_member(PG_FUNCTION_ARGS)
    if (bms)
        bms_free(bms);
 
-   if (result == NULL)
-       PG_RETURN_NULL();
-
    PG_RETURN_TEXT_P(result);
 }
 
@@ -136,9 +134,6 @@ test_bms_add_members(PG_FUNCTION_ARGS)
    if (bms2)
        bms_free(bms2);
 
-   if (bms1 == NULL)
-       PG_RETURN_NULL();
-
    result = BITMAPSET_TO_TEXT(bms1);
    bms_free(bms1);
 
@@ -161,12 +156,8 @@ test_bms_del_member(PG_FUNCTION_ARGS)
    member = PG_GETARG_INT32(1);
    bms = bms_del_member(bms, member);
 
-   if (bms == NULL || bms_is_empty(bms))
-   {
-       if (bms)
-           bms_free(bms);
+   if (bms_is_empty(bms))
        PG_RETURN_NULL();
-   }
 
    result = BITMAPSET_TO_TEXT(bms);
    bms_free(bms);
@@ -515,8 +506,8 @@ test_bms_get_singleton_member(PG_FUNCTION_ARGS)
 {
    Bitmapset  *bms = NULL;
    int32       default_member = PG_GETARG_INT32(1);
-   int         member;
    bool        success;
+   int         member = -1;
 
    if (PG_ARGISNULL(0))
        PG_RETURN_INT32(default_member);
@@ -532,8 +523,8 @@ test_bms_get_singleton_member(PG_FUNCTION_ARGS)
 
    if (success)
        PG_RETURN_INT32(member);
-   else
-       PG_RETURN_INT32(default_member);
+
+   PG_RETURN_INT32(default_member);
 }
 
 Datum
@@ -609,11 +600,6 @@ test_bms_overlap_list(PG_FUNCTION_ARGS)
 
    array = PG_GETARG_ARRAYTYPE_P(1);
 
-   if (ARR_ELEMTYPE(array) != INT4OID)
-       ereport(ERROR,
-               (errcode(ERRCODE_DATATYPE_MISMATCH),
-                errmsg("integer array expected")));
-
    deconstruct_array(array,
                      INT4OID, sizeof(int32), true, 'i',
                      &elem_datums, &elem_nulls, &elem_count);
@@ -752,6 +738,37 @@ test_bms_int_members(PG_FUNCTION_ARGS)
    PG_RETURN_TEXT_P(result);
 }
 
+Datum
+test_bms_del_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_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);
+}
+
 Datum
 test_bms_replace_members(PG_FUNCTION_ARGS)
 {