LCOV - code coverage report
Current view: top level - src/test/modules/test_bitmapset - test_bitmapset.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 480 506 94.9 %
Date: 2025-09-27 04:17:35 Functions: 65 65 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * test_bitmapset.c
       4             :  *      Test the Bitmapset data structure.
       5             :  *
       6             :  * This module tests the Bitmapset implementation in PostgreSQL, covering
       7             :  * all public API functions.
       8             :  *
       9             :  * Copyright (c) 2025, PostgreSQL Global Development Group
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *      src/test/modules/test_bitmapset/test_bitmapset.c
      13             :  *
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : 
      17             : #include "postgres.h"
      18             : 
      19             : #include <stddef.h>
      20             : #include "catalog/pg_type.h"
      21             : #include "common/pg_prng.h"
      22             : #include "utils/array.h"
      23             : #include "fmgr.h"
      24             : #include "nodes/bitmapset.h"
      25             : #include "nodes/nodes.h"
      26             : #include "nodes/pg_list.h"
      27             : #include "utils/builtins.h"
      28             : #include "utils/timestamp.h"
      29             : #include "varatt.h"
      30             : 
      31           2 : PG_MODULE_MAGIC;
      32             : 
      33             : /* Bitmapset API functions in order of appearance in bitmapset.c */
      34           4 : PG_FUNCTION_INFO_V1(test_bms_make_singleton);
      35           4 : PG_FUNCTION_INFO_V1(test_bms_add_member);
      36           4 : PG_FUNCTION_INFO_V1(test_bms_del_member);
      37           4 : PG_FUNCTION_INFO_V1(test_bms_is_member);
      38           4 : PG_FUNCTION_INFO_V1(test_bms_num_members);
      39           4 : PG_FUNCTION_INFO_V1(test_bms_copy);
      40           4 : PG_FUNCTION_INFO_V1(test_bms_equal);
      41           4 : PG_FUNCTION_INFO_V1(test_bms_compare);
      42           4 : PG_FUNCTION_INFO_V1(test_bms_is_subset);
      43           4 : PG_FUNCTION_INFO_V1(test_bms_subset_compare);
      44           4 : PG_FUNCTION_INFO_V1(test_bms_union);
      45           4 : PG_FUNCTION_INFO_V1(test_bms_intersect);
      46           4 : PG_FUNCTION_INFO_V1(test_bms_difference);
      47           4 : PG_FUNCTION_INFO_V1(test_bms_is_empty);
      48           4 : PG_FUNCTION_INFO_V1(test_bms_membership);
      49           4 : PG_FUNCTION_INFO_V1(test_bms_singleton_member);
      50           4 : PG_FUNCTION_INFO_V1(test_bms_get_singleton_member);
      51           4 : PG_FUNCTION_INFO_V1(test_bms_next_member);
      52           4 : PG_FUNCTION_INFO_V1(test_bms_prev_member);
      53           4 : PG_FUNCTION_INFO_V1(test_bms_hash_value);
      54           4 : PG_FUNCTION_INFO_V1(test_bms_overlap);
      55           4 : PG_FUNCTION_INFO_V1(test_bms_overlap_list);
      56           4 : PG_FUNCTION_INFO_V1(test_bms_nonempty_difference);
      57           4 : PG_FUNCTION_INFO_V1(test_bms_member_index);
      58           4 : PG_FUNCTION_INFO_V1(test_bms_add_range);
      59           4 : PG_FUNCTION_INFO_V1(test_bms_add_members);
      60           4 : PG_FUNCTION_INFO_V1(test_bms_int_members);
      61           4 : PG_FUNCTION_INFO_V1(test_bms_replace_members);
      62           4 : PG_FUNCTION_INFO_V1(test_bms_join);
      63           4 : PG_FUNCTION_INFO_V1(test_bitmap_hash);
      64           4 : PG_FUNCTION_INFO_V1(test_bitmap_match);
      65             : 
      66             : /* Test utility functions */
      67           4 : PG_FUNCTION_INFO_V1(test_random_operations);
      68             : 
      69             : /* Convenient macros to test results */
      70             : #define EXPECT_TRUE(expr)   \
      71             :     do { \
      72             :         if (!(expr)) \
      73             :             elog(ERROR, \
      74             :                  "%s was unexpectedly false in file \"%s\" line %u", \
      75             :                  #expr, __FILE__, __LINE__); \
      76             :     } while (0)
      77             : 
      78             : #define EXPECT_NOT_NULL(expr)   \
      79             :     do { \
      80             :         if ((expr) == NULL) \
      81             :             elog(ERROR, \
      82             :                  "%s was unexpectedly true in file \"%s\" line %u", \
      83             :                  #expr, __FILE__, __LINE__); \
      84             :     } while (0)
      85             : 
      86             : /* Encode/Decode to/from TEXT and Bitmapset */
      87             : #define BITMAPSET_TO_TEXT(bms) cstring_to_text(nodeToString(bms))
      88             : #define TEXT_TO_BITMAPSET(str) ((Bitmapset *) stringToNode(text_to_cstring(str)))
      89             : 
      90             : /*
      91             :  * Individual test functions for each bitmapset API function
      92             :  */
      93             : 
      94             : Datum
      95          14 : test_bms_add_member(PG_FUNCTION_ARGS)
      96             : {
      97             :     int         member;
      98          14 :     Bitmapset  *bms = NULL;
      99             :     text       *result;
     100             : 
     101          14 :     if (PG_ARGISNULL(1))
     102           0 :         PG_RETURN_NULL();
     103             : 
     104          14 :     if (!PG_ARGISNULL(0))
     105          14 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     106             : 
     107          14 :     member = PG_GETARG_INT32(1);
     108          14 :     bms = bms_add_member(bms, member);
     109          10 :     result = BITMAPSET_TO_TEXT(bms);
     110             : 
     111          10 :     if (bms)
     112          10 :         bms_free(bms);
     113             : 
     114          10 :     if (result == NULL)
     115           0 :         PG_RETURN_NULL();
     116             : 
     117          10 :     PG_RETURN_TEXT_P(result);
     118             : }
     119             : 
     120             : Datum
     121           6 : test_bms_add_members(PG_FUNCTION_ARGS)
     122             : {
     123           6 :     Bitmapset  *bms1 = NULL,
     124           6 :                *bms2 = NULL;
     125             :     text       *result;
     126             : 
     127           6 :     if (!PG_ARGISNULL(0))
     128           6 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     129             : 
     130           6 :     if (!PG_ARGISNULL(1))
     131           6 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     132             : 
     133             :     /* IMPORTANT: bms_add_members modifies/frees the first argument */
     134           6 :     bms1 = bms_add_members(bms1, bms2);
     135             : 
     136           6 :     if (bms2)
     137           6 :         bms_free(bms2);
     138             : 
     139           6 :     if (bms1 == NULL)
     140           0 :         PG_RETURN_NULL();
     141             : 
     142           6 :     result = BITMAPSET_TO_TEXT(bms1);
     143           6 :     bms_free(bms1);
     144             : 
     145           6 :     PG_RETURN_TEXT_P(result);
     146             : }
     147             : 
     148             : Datum
     149          16 : test_bms_del_member(PG_FUNCTION_ARGS)
     150             : {
     151          16 :     Bitmapset  *bms = NULL;
     152             :     int32       member;
     153             :     text       *result;
     154             : 
     155          16 :     if (PG_ARGISNULL(1))
     156           0 :         PG_RETURN_NULL();
     157             : 
     158          16 :     if (!PG_ARGISNULL(0))
     159          16 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     160             : 
     161          16 :     member = PG_GETARG_INT32(1);
     162          16 :     bms = bms_del_member(bms, member);
     163             : 
     164          14 :     if (bms == NULL || bms_is_empty(bms))
     165             :     {
     166           4 :         if (bms)
     167           0 :             bms_free(bms);
     168           4 :         PG_RETURN_NULL();
     169             :     }
     170             : 
     171          10 :     result = BITMAPSET_TO_TEXT(bms);
     172          10 :     bms_free(bms);
     173             : 
     174          10 :     PG_RETURN_TEXT_P(result);
     175             : }
     176             : 
     177             : Datum
     178          10 : test_bms_is_member(PG_FUNCTION_ARGS)
     179             : {
     180          10 :     Bitmapset  *bms = NULL;
     181             :     int32       member;
     182             :     bool        result;
     183             : 
     184          10 :     if (PG_ARGISNULL(1))
     185           0 :         PG_RETURN_BOOL(false);
     186             : 
     187          10 :     if (!PG_ARGISNULL(0))
     188          10 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     189             : 
     190          10 :     member = PG_GETARG_INT32(1);
     191          10 :     result = bms_is_member(member, bms);
     192             : 
     193           8 :     if (bms)
     194           6 :         bms_free(bms);
     195             : 
     196           8 :     PG_RETURN_BOOL(result);
     197             : }
     198             : 
     199             : Datum
     200           6 : test_bms_num_members(PG_FUNCTION_ARGS)
     201             : {
     202           6 :     Bitmapset  *bms = NULL;
     203           6 :     int         result = 0;
     204             : 
     205           6 :     if (!PG_ARGISNULL(0))
     206           6 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     207             : 
     208           6 :     result = bms_num_members(bms);
     209             : 
     210           6 :     if (bms)
     211           4 :         bms_free(bms);
     212             : 
     213           6 :     PG_RETURN_INT32(result);
     214             : }
     215             : 
     216             : Datum
     217           8 : test_bms_make_singleton(PG_FUNCTION_ARGS)
     218             : {
     219             :     int32       member;
     220             :     Bitmapset  *bms;
     221             :     text       *result;
     222             : 
     223           8 :     if (PG_ARGISNULL(0))
     224           0 :         PG_RETURN_NULL();
     225             : 
     226           8 :     member = PG_GETARG_INT32(0);
     227           8 :     bms = bms_make_singleton(member);
     228             : 
     229           6 :     result = BITMAPSET_TO_TEXT(bms);
     230           6 :     bms_free(bms);
     231             : 
     232           6 :     PG_RETURN_TEXT_P(result);
     233             : }
     234             : 
     235             : Datum
     236           4 : test_bms_copy(PG_FUNCTION_ARGS)
     237             : {
     238             :     text       *bms_data;
     239           4 :     Bitmapset  *bms = NULL;
     240             :     Bitmapset  *copy_bms;
     241             :     text       *result;
     242             : 
     243           4 :     if (PG_ARGISNULL(0))
     244           2 :         PG_RETURN_NULL();
     245             : 
     246           2 :     bms_data = PG_GETARG_TEXT_PP(0);
     247           2 :     bms = TEXT_TO_BITMAPSET(bms_data);
     248           2 :     copy_bms = bms_copy(bms);
     249           2 :     result = BITMAPSET_TO_TEXT(copy_bms);
     250             : 
     251           2 :     if (bms)
     252           2 :         bms_free(bms);
     253           2 :     if (copy_bms)
     254           2 :         bms_free(copy_bms);
     255             : 
     256           2 :     PG_RETURN_TEXT_P(result);
     257             : }
     258             : 
     259             : Datum
     260          16 : test_bms_equal(PG_FUNCTION_ARGS)
     261             : {
     262          16 :     Bitmapset  *bms1 = NULL,
     263          16 :                *bms2 = NULL;
     264             :     bool        result;
     265             : 
     266          16 :     if (!PG_ARGISNULL(0))
     267          16 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     268             : 
     269          16 :     if (!PG_ARGISNULL(1))
     270          16 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     271             : 
     272          16 :     result = bms_equal(bms1, bms2);
     273             : 
     274          16 :     if (bms1)
     275          10 :         bms_free(bms1);
     276          16 :     if (bms2)
     277          10 :         bms_free(bms2);
     278             : 
     279          16 :     PG_RETURN_BOOL(result);
     280             : }
     281             : 
     282             : Datum
     283           8 : test_bms_union(PG_FUNCTION_ARGS)
     284             : {
     285           8 :     Bitmapset  *bms1 = NULL,
     286           8 :                *bms2 = NULL;
     287             :     Bitmapset  *result_bms;
     288             :     text       *result;
     289             : 
     290           8 :     if (!PG_ARGISNULL(0))
     291           8 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     292             : 
     293           8 :     if (!PG_ARGISNULL(1))
     294           8 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     295             : 
     296           8 :     result_bms = bms_union(bms1, bms2);
     297             : 
     298           8 :     if (bms1)
     299           6 :         bms_free(bms1);
     300           8 :     if (bms2)
     301           4 :         bms_free(bms2);
     302             : 
     303           8 :     if (result_bms == NULL)
     304           2 :         PG_RETURN_NULL();
     305             : 
     306           6 :     result = BITMAPSET_TO_TEXT(result_bms);
     307           6 :     bms_free(result_bms);
     308             : 
     309           6 :     PG_RETURN_TEXT_P(result);
     310             : }
     311             : 
     312             : Datum
     313           6 : test_bms_membership(PG_FUNCTION_ARGS)
     314             : {
     315           6 :     Bitmapset  *bms = NULL;
     316             :     BMS_Membership result;
     317             : 
     318           6 :     if (PG_ARGISNULL(0))
     319           0 :         PG_RETURN_INT32(BMS_EMPTY_SET);
     320             : 
     321           6 :     bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     322           6 :     result = bms_membership(bms);
     323             : 
     324           6 :     if (bms)
     325           4 :         bms_free(bms);
     326             : 
     327           6 :     PG_RETURN_INT32((int32) result);
     328             : }
     329             : 
     330             : Datum
     331           8 : test_bms_next_member(PG_FUNCTION_ARGS)
     332             : {
     333           8 :     Bitmapset  *bms = NULL;
     334             :     int32       prevmember;
     335             :     int         result;
     336             : 
     337           8 :     if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
     338           0 :         PG_RETURN_INT32(-2);
     339             : 
     340           8 :     bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     341           8 :     prevmember = PG_GETARG_INT32(1);
     342           8 :     result = bms_next_member(bms, prevmember);
     343             : 
     344           8 :     if (bms)
     345           6 :         bms_free(bms);
     346             : 
     347           8 :     PG_RETURN_INT32(result);
     348             : }
     349             : 
     350             : Datum
     351           6 : test_bms_intersect(PG_FUNCTION_ARGS)
     352             : {
     353           6 :     Bitmapset  *bms1 = NULL,
     354           6 :                *bms2 = NULL;
     355             :     Bitmapset  *result_bms;
     356             :     text       *result;
     357             : 
     358           6 :     if (!PG_ARGISNULL(0))
     359           6 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     360             : 
     361           6 :     if (!PG_ARGISNULL(1))
     362           6 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     363             : 
     364           6 :     result_bms = bms_intersect(bms1, bms2);
     365             : 
     366           6 :     if (bms1)
     367           6 :         bms_free(bms1);
     368           6 :     if (bms2)
     369           4 :         bms_free(bms2);
     370             : 
     371           6 :     if (result_bms == NULL)
     372           4 :         PG_RETURN_NULL();
     373             : 
     374           2 :     result = BITMAPSET_TO_TEXT(result_bms);
     375           2 :     bms_free(result_bms);
     376             : 
     377           2 :     PG_RETURN_TEXT_P(result);
     378             : }
     379             : 
     380             : Datum
     381          10 : test_bms_difference(PG_FUNCTION_ARGS)
     382             : {
     383          10 :     Bitmapset  *bms1 = NULL,
     384          10 :                *bms2 = NULL;
     385             :     Bitmapset  *result_bms;
     386             :     text       *result;
     387             : 
     388          10 :     if (!PG_ARGISNULL(0))
     389          10 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     390             : 
     391          10 :     if (!PG_ARGISNULL(1))
     392          10 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     393             : 
     394          10 :     result_bms = bms_difference(bms1, bms2);
     395             : 
     396          10 :     if (bms1)
     397          10 :         bms_free(bms1);
     398          10 :     if (bms2)
     399          10 :         bms_free(bms2);
     400             : 
     401          10 :     if (result_bms == NULL)
     402           4 :         PG_RETURN_NULL();
     403             : 
     404           6 :     result = BITMAPSET_TO_TEXT(result_bms);
     405           6 :     bms_free(result_bms);
     406             : 
     407           6 :     PG_RETURN_TEXT_P(result);
     408             : }
     409             : 
     410             : Datum
     411          14 : test_bms_compare(PG_FUNCTION_ARGS)
     412             : {
     413          14 :     Bitmapset  *bms1 = NULL,
     414          14 :                *bms2 = NULL;
     415             :     int         result;
     416             : 
     417          14 :     if (!PG_ARGISNULL(0))
     418          14 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     419             : 
     420          14 :     if (!PG_ARGISNULL(1))
     421          14 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     422             : 
     423          14 :     result = bms_compare(bms1, bms2);
     424             : 
     425          14 :     if (bms1)
     426          10 :         bms_free(bms1);
     427          14 :     if (bms2)
     428          10 :         bms_free(bms2);
     429             : 
     430          14 :     PG_RETURN_INT32(result);
     431             : }
     432             : 
     433             : Datum
     434           6 : test_bms_is_empty(PG_FUNCTION_ARGS)
     435             : {
     436           6 :     Bitmapset  *bms = NULL;
     437             :     bool        result;
     438             : 
     439           6 :     if (!PG_ARGISNULL(0))
     440           4 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     441             : 
     442           6 :     result = bms_is_empty(bms);
     443             : 
     444           6 :     if (bms)
     445           2 :         bms_free(bms);
     446             : 
     447           6 :     PG_RETURN_BOOL(result);
     448             : }
     449             : 
     450             : Datum
     451          10 : test_bms_is_subset(PG_FUNCTION_ARGS)
     452             : {
     453          10 :     Bitmapset  *bms1 = NULL,
     454          10 :                *bms2 = NULL;
     455             :     bool        result;
     456             : 
     457          10 :     if (!PG_ARGISNULL(0))
     458          10 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     459             : 
     460          10 :     if (!PG_ARGISNULL(1))
     461          10 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     462             : 
     463          10 :     result = bms_is_subset(bms1, bms2);
     464             : 
     465          10 :     if (bms1)
     466           8 :         bms_free(bms1);
     467          10 :     if (bms2)
     468          10 :         bms_free(bms2);
     469             : 
     470          10 :     PG_RETURN_BOOL(result);
     471             : }
     472             : 
     473             : Datum
     474          14 : test_bms_subset_compare(PG_FUNCTION_ARGS)
     475             : {
     476          14 :     Bitmapset  *bms1 = NULL,
     477          14 :                *bms2 = NULL;
     478             :     BMS_Comparison result;
     479             : 
     480          14 :     if (!PG_ARGISNULL(0))
     481          10 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     482             : 
     483          14 :     if (!PG_ARGISNULL(1))
     484          10 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     485             : 
     486          14 :     result = bms_subset_compare(bms1, bms2);
     487             : 
     488          14 :     if (bms1)
     489          10 :         bms_free(bms1);
     490          14 :     if (bms2)
     491          10 :         bms_free(bms2);
     492             : 
     493          14 :     PG_RETURN_INT32((int32) result);
     494             : }
     495             : 
     496             : Datum
     497           4 : test_bms_singleton_member(PG_FUNCTION_ARGS)
     498             : {
     499           4 :     Bitmapset  *bms = NULL;
     500             :     int         result;
     501             : 
     502           4 :     if (!PG_ARGISNULL(0))
     503           4 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     504             : 
     505           4 :     result = bms_singleton_member(bms);
     506             : 
     507           2 :     if (bms)
     508           2 :         bms_free(bms);
     509             : 
     510           2 :     PG_RETURN_INT32(result);
     511             : }
     512             : 
     513             : Datum
     514           4 : test_bms_get_singleton_member(PG_FUNCTION_ARGS)
     515             : {
     516           4 :     Bitmapset  *bms = NULL;
     517           4 :     int32       default_member = PG_GETARG_INT32(1);
     518             :     int         member;
     519             :     bool        success;
     520             : 
     521           4 :     if (PG_ARGISNULL(0))
     522           0 :         PG_RETURN_INT32(default_member);
     523             : 
     524           4 :     bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     525             : 
     526             :     /*
     527             :      * bms_get_singleton_member returns bool and stores result in member
     528             :      * pointer
     529             :      */
     530           4 :     success = bms_get_singleton_member(bms, &member);
     531           4 :     bms_free(bms);
     532             : 
     533           4 :     if (success)
     534           2 :         PG_RETURN_INT32(member);
     535             :     else
     536           2 :         PG_RETURN_INT32(default_member);
     537             : }
     538             : 
     539             : Datum
     540           8 : test_bms_prev_member(PG_FUNCTION_ARGS)
     541             : {
     542             :     text       *bms_data;
     543           8 :     Bitmapset  *bms = NULL;
     544             :     int32       prevmember;
     545             :     int         result;
     546             : 
     547           8 :     if (PG_ARGISNULL(0))
     548           0 :         PG_RETURN_INT32(-2);
     549             : 
     550           8 :     bms_data = PG_GETARG_TEXT_PP(0);
     551           8 :     prevmember = PG_GETARG_INT32(1);
     552             : 
     553           8 :     if (VARSIZE_ANY_EXHDR(bms_data) == 0)
     554           0 :         PG_RETURN_INT32(-2);
     555             : 
     556           8 :     bms = TEXT_TO_BITMAPSET(bms_data);
     557           8 :     result = bms_prev_member(bms, prevmember);
     558           8 :     bms_free(bms);
     559             : 
     560           8 :     PG_RETURN_INT32(result);
     561             : }
     562             : 
     563             : Datum
     564           6 : test_bms_overlap(PG_FUNCTION_ARGS)
     565             : {
     566           6 :     Bitmapset  *bms1 = NULL,
     567           6 :                *bms2 = NULL;
     568             :     bool        result;
     569             : 
     570           6 :     if (!PG_ARGISNULL(0))
     571           6 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     572             : 
     573           6 :     if (!PG_ARGISNULL(1))
     574           6 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     575             : 
     576           6 :     result = bms_overlap(bms1, bms2);
     577             : 
     578           6 :     if (bms1)
     579           4 :         bms_free(bms1);
     580           6 :     if (bms2)
     581           6 :         bms_free(bms2);
     582             : 
     583           6 :     PG_RETURN_BOOL(result);
     584             : }
     585             : 
     586             : Datum
     587          12 : test_bms_overlap_list(PG_FUNCTION_ARGS)
     588             : {
     589          12 :     Bitmapset  *bms = NULL;
     590             :     ArrayType  *array;
     591          12 :     List       *int_list = NIL;
     592             :     bool        result;
     593             :     Datum      *elem_datums;
     594             :     bool       *elem_nulls;
     595             :     int         elem_count;
     596             :     int         i;
     597             : 
     598          12 :     if (PG_ARGISNULL(0))
     599           0 :         PG_RETURN_BOOL(false);
     600             : 
     601          12 :     bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     602             : 
     603          12 :     if (PG_ARGISNULL(1))
     604             :     {
     605           0 :         if (bms)
     606           0 :             bms_free(bms);
     607           0 :         PG_RETURN_BOOL(false);
     608             :     }
     609             : 
     610          12 :     array = PG_GETARG_ARRAYTYPE_P(1);
     611             : 
     612          12 :     if (ARR_ELEMTYPE(array) != INT4OID)
     613           0 :         ereport(ERROR,
     614             :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
     615             :                  errmsg("integer array expected")));
     616             : 
     617          12 :     deconstruct_array(array,
     618             :                       INT4OID, sizeof(int32), true, 'i',
     619             :                       &elem_datums, &elem_nulls, &elem_count);
     620             : 
     621          40 :     for (i = 0; i < elem_count; i++)
     622             :     {
     623          28 :         if (!elem_nulls[i])
     624             :         {
     625          28 :             int32       member = DatumGetInt32(elem_datums[i]);
     626             : 
     627          28 :             int_list = lappend_int(int_list, member);
     628             :         }
     629             :     }
     630             : 
     631          12 :     result = bms_overlap_list(bms, int_list);
     632             : 
     633          12 :     if (bms)
     634          12 :         bms_free(bms);
     635             : 
     636          12 :     list_free(int_list);
     637             : 
     638          12 :     pfree(elem_datums);
     639          12 :     pfree(elem_nulls);
     640             : 
     641          12 :     PG_RETURN_BOOL(result);
     642             : }
     643             : 
     644             : Datum
     645          10 : test_bms_nonempty_difference(PG_FUNCTION_ARGS)
     646             : {
     647          10 :     Bitmapset  *bms1 = NULL,
     648          10 :                *bms2 = NULL;
     649             :     bool        result;
     650             : 
     651          10 :     if (!PG_ARGISNULL(0))
     652           8 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     653             : 
     654          10 :     if (!PG_ARGISNULL(1))
     655           8 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     656             : 
     657          10 :     result = bms_nonempty_difference(bms1, bms2);
     658             : 
     659          10 :     if (bms1)
     660           8 :         bms_free(bms1);
     661          10 :     if (bms2)
     662           8 :         bms_free(bms2);
     663             : 
     664          10 :     PG_RETURN_BOOL(result);
     665             : }
     666             : 
     667             : Datum
     668           8 : test_bms_member_index(PG_FUNCTION_ARGS)
     669             : {
     670             :     text       *bms_data;
     671           8 :     Bitmapset  *bms = NULL;
     672             :     int32       member;
     673             :     int         result;
     674             : 
     675           8 :     if (PG_ARGISNULL(0))
     676           2 :         PG_RETURN_INT32(-1);
     677             : 
     678           6 :     bms_data = PG_GETARG_TEXT_PP(0);
     679           6 :     member = PG_GETARG_INT32(1);
     680             : 
     681           6 :     if (VARSIZE_ANY_EXHDR(bms_data) == 0)
     682           0 :         PG_RETURN_INT32(-1);
     683             : 
     684           6 :     bms = TEXT_TO_BITMAPSET(bms_data);
     685             : 
     686           6 :     result = bms_member_index(bms, member);
     687           6 :     bms_free(bms);
     688             : 
     689           6 :     PG_RETURN_INT32(result);
     690             : }
     691             : 
     692             : Datum
     693          36 : test_bms_add_range(PG_FUNCTION_ARGS)
     694             : {
     695          36 :     Bitmapset  *bms = NULL;
     696             :     int32       lower,
     697             :                 upper;
     698             :     text       *result;
     699             : 
     700          36 :     if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
     701           0 :         PG_RETURN_NULL();
     702             : 
     703          36 :     if (!PG_ARGISNULL(0))
     704          32 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     705             : 
     706          36 :     lower = PG_GETARG_INT32(1);
     707          36 :     upper = PG_GETARG_INT32(2);
     708             : 
     709             :     /* Check for invalid range */
     710          36 :     if (upper < lower)
     711             :     {
     712           0 :         if (bms)
     713           0 :             bms_free(bms);
     714           0 :         PG_RETURN_NULL();
     715             :     }
     716             : 
     717          36 :     bms = bms_add_range(bms, lower, upper);
     718             : 
     719          34 :     result = BITMAPSET_TO_TEXT(bms);
     720          34 :     if (bms)
     721          34 :         bms_free(bms);
     722             : 
     723          34 :     PG_RETURN_TEXT_P(result);
     724             : }
     725             : 
     726             : Datum
     727           8 : test_bms_int_members(PG_FUNCTION_ARGS)
     728             : {
     729           8 :     Bitmapset  *bms1 = NULL,
     730           8 :                *bms2 = NULL;
     731             :     text       *result;
     732             : 
     733           8 :     if (!PG_ARGISNULL(0))
     734           8 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     735             : 
     736           8 :     if (!PG_ARGISNULL(1))
     737           8 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     738             : 
     739           8 :     bms1 = bms_int_members(bms1, bms2);
     740             : 
     741           8 :     if (bms2)
     742           6 :         bms_free(bms2);
     743             : 
     744           8 :     if (bms1 == NULL)
     745           4 :         PG_RETURN_NULL();
     746             : 
     747           4 :     result = BITMAPSET_TO_TEXT(bms1);
     748             : 
     749           4 :     if (bms1)
     750           4 :         bms_free(bms1);
     751             : 
     752           4 :     PG_RETURN_TEXT_P(result);
     753             : }
     754             : 
     755             : Datum
     756          10 : test_bms_replace_members(PG_FUNCTION_ARGS)
     757             : {
     758          10 :     Bitmapset  *bms1 = NULL,
     759          10 :                *bms2 = NULL;
     760             :     Bitmapset  *result_bms;
     761             :     text       *result;
     762             : 
     763          10 :     if (!PG_ARGISNULL(0))
     764           8 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     765             : 
     766          10 :     if (!PG_ARGISNULL(1))
     767           8 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     768             : 
     769             :     /* IMPORTANT: bms_replace_members modifies/frees the first argument */
     770          10 :     result_bms = bms_replace_members(bms1, bms2);
     771             : 
     772             :     /* bms1 is now invalid, do not free it */
     773             : 
     774          10 :     if (bms2)
     775           8 :         bms_free(bms2);
     776             : 
     777          10 :     if (result_bms == NULL)
     778           2 :         PG_RETURN_NULL();
     779             : 
     780           8 :     result = BITMAPSET_TO_TEXT(result_bms);
     781           8 :     bms_free(result_bms);
     782             : 
     783           8 :     PG_RETURN_TEXT_P(result);
     784             : }
     785             : 
     786             : Datum
     787           8 : test_bms_join(PG_FUNCTION_ARGS)
     788             : {
     789           8 :     Bitmapset  *bms1 = NULL,
     790           8 :                *bms2 = NULL;
     791             :     Bitmapset  *result_bms;
     792             :     text       *result;
     793             : 
     794           8 :     if (!PG_ARGISNULL(0))
     795           6 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     796             : 
     797           8 :     if (!PG_ARGISNULL(1))
     798           6 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     799             : 
     800             :     /* IMPORTANT: bms_join may recycle either input arguments */
     801           8 :     result_bms = bms_join(bms1, bms2);
     802             : 
     803             :     /* bms1 and bms2 may have been recycled! Do not free any of them. */
     804             : 
     805           8 :     if (result_bms == NULL)
     806           0 :         PG_RETURN_NULL();
     807             : 
     808           8 :     result = BITMAPSET_TO_TEXT(result_bms);
     809           8 :     bms_free(result_bms);
     810             : 
     811           8 :     PG_RETURN_TEXT_P(result);
     812             : }
     813             : 
     814             : Datum
     815          12 : test_bms_hash_value(PG_FUNCTION_ARGS)
     816             : {
     817          12 :     Bitmapset  *bms = NULL;
     818             :     uint32      hash_result;
     819             : 
     820          12 :     if (!PG_ARGISNULL(0))
     821          12 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     822             : 
     823          12 :     hash_result = bms_hash_value(bms);
     824             : 
     825          12 :     if (bms)
     826          10 :         bms_free(bms);
     827             : 
     828          12 :     PG_RETURN_INT32(hash_result);
     829             : }
     830             : 
     831             : Datum
     832          12 : test_bitmap_hash(PG_FUNCTION_ARGS)
     833             : {
     834          12 :     Bitmapset  *bms = NULL;
     835             :     Bitmapset  *bms_ptr;
     836             :     uint32      hash_result;
     837             : 
     838          12 :     if (!PG_ARGISNULL(0))
     839          12 :         bms = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     840             : 
     841          12 :     bms_ptr = bms;
     842             : 
     843             :     /* Call bitmap_hash */
     844          12 :     hash_result = bitmap_hash(&bms_ptr, sizeof(Bitmapset *));
     845             : 
     846             :     /* Clean up */
     847          12 :     if (!PG_ARGISNULL(0) && bms_ptr)
     848          10 :         bms_free(bms_ptr);
     849             : 
     850          12 :     PG_RETURN_INT32(hash_result);
     851             : }
     852             : 
     853             : Datum
     854          18 : test_bitmap_match(PG_FUNCTION_ARGS)
     855             : {
     856          18 :     Bitmapset  *bms1 = NULL,
     857          18 :                *bms2 = NULL;
     858             :     Bitmapset  *bms_ptr1,
     859             :                *bms_ptr2;
     860             :     int         match_result;
     861             : 
     862          18 :     if (!PG_ARGISNULL(0))
     863          18 :         bms1 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(0));
     864             : 
     865          18 :     if (!PG_ARGISNULL(1))
     866          18 :         bms2 = TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(1));
     867             : 
     868             :     /* Set up pointers to the Bitmapsets */
     869          18 :     bms_ptr1 = bms1;
     870          18 :     bms_ptr2 = bms2;
     871             : 
     872             :     /* Call bitmap_match with addresses of the Bitmapset pointers */
     873          18 :     match_result = bitmap_match(&bms_ptr1, &bms_ptr2, sizeof(Bitmapset *));
     874             : 
     875             :     /* Clean up */
     876          18 :     if (bms1)
     877          12 :         bms_free(bms1);
     878          18 :     if (bms2)
     879          12 :         bms_free(bms2);
     880             : 
     881          18 :     PG_RETURN_INT32(match_result);
     882             : }
     883             : 
     884             : /*
     885             :  * Contrary to all the other functions which are one-one mappings with the
     886             :  * equivalent C functions, this stresses Bitmapsets in a random fashion for
     887             :  * various operations.
     888             :  *
     889             :  * "min_value" is the minimal value used for the members, that will stand
     890             :  * up to a range of "max_range".  "num_ops" defines the number of time each
     891             :  * operation is done.  "seed" is a random seed used to calculate the member
     892             :  * values.
     893             :  *
     894             :  * The return value is the number of times all operations have been executed.
     895             :  */
     896             : Datum
     897           2 : test_random_operations(PG_FUNCTION_ARGS)
     898             : {
     899           2 :     Bitmapset  *bms1 = NULL;
     900           2 :     Bitmapset  *bms2 = NULL;
     901           2 :     Bitmapset  *bms = NULL;
     902           2 :     Bitmapset  *result = NULL;
     903             :     pg_prng_state state;
     904           2 :     uint64      seed = GetCurrentTimestamp();
     905           2 :     int         num_ops = 5000;
     906           2 :     int         total_ops = 0;
     907           2 :     int         max_range = 2000;
     908           2 :     int         min_value = 0;
     909             :     int         member;
     910             :     int        *members;
     911           2 :     int         num_members = 0;
     912             : 
     913           2 :     if (!PG_ARGISNULL(0) && PG_GETARG_INT32(0) > 0)
     914           0 :         seed = PG_GETARG_INT32(0);
     915             : 
     916           2 :     if (!PG_ARGISNULL(1))
     917           2 :         num_ops = PG_GETARG_INT32(1);
     918             : 
     919           2 :     if (!PG_ARGISNULL(2))
     920           2 :         max_range = PG_GETARG_INT32(2);
     921             : 
     922           2 :     if (!PG_ARGISNULL(3))
     923           2 :         min_value = PG_GETARG_INT32(3);
     924             : 
     925           2 :     pg_prng_seed(&state, seed);
     926           2 :     members = palloc(sizeof(int) * num_ops);
     927             : 
     928             :     /* Phase 1: Random insertions */
     929       10002 :     for (int i = 0; i < num_ops / 2; i++)
     930             :     {
     931       10000 :         member = pg_prng_uint32(&state) % max_range + min_value;
     932             : 
     933       10000 :         if (!bms_is_member(member, bms1))
     934             :         {
     935        9710 :             members[num_members++] = member;
     936        9710 :             bms1 = bms_add_member(bms1, member);
     937             :         }
     938             :     }
     939             : 
     940             :     /* Phase 2: Random set operations */
     941        5002 :     for (int i = 0; i < num_ops / 4; i++)
     942             :     {
     943        5000 :         member = pg_prng_uint32(&state) % max_range + min_value;
     944             : 
     945        5000 :         bms2 = bms_add_member(bms2, member);
     946             :     }
     947             : 
     948             :     /* Test union */
     949           2 :     result = bms_union(bms1, bms2);
     950           2 :     EXPECT_NOT_NULL(result);
     951             : 
     952             :     /* Verify union contains all members from first set */
     953        9712 :     for (int i = 0; i < num_members; i++)
     954             :     {
     955        9710 :         if (!bms_is_member(members[i], result))
     956           0 :             elog(ERROR, "union missing member %d", members[i]);
     957             :     }
     958           2 :     bms_free(result);
     959             : 
     960             :     /* Test intersection */
     961           2 :     result = bms_intersect(bms1, bms2);
     962           2 :     if (result != NULL)
     963             :     {
     964           2 :         member = -1;
     965             : 
     966         328 :         while ((member = bms_next_member(result, member)) >= 0)
     967             :         {
     968         326 :             if (!bms_is_member(member, bms1) || !bms_is_member(member, bms2))
     969           0 :                 elog(ERROR, "intersection contains invalid member %d", member);
     970             :         }
     971           2 :         bms_free(result);
     972             :     }
     973             : 
     974             :     /* Phase 3: Test range operations */
     975           2 :     result = NULL;
     976       20002 :     for (int i = 0; i < num_ops; i++)
     977             :     {
     978       20000 :         int         lower = pg_prng_uint32(&state) % 100;
     979       20000 :         int         upper = lower + (pg_prng_uint32(&state) % 20);
     980             : 
     981       20000 :         result = bms_add_range(result, lower, upper);
     982             :     }
     983           2 :     if (result != NULL)
     984             :     {
     985           2 :         EXPECT_TRUE(bms_num_members(result) > 0);
     986           2 :         bms_free(result);
     987             :     }
     988             : 
     989           2 :     pfree(members);
     990           2 :     bms_free(bms1);
     991           2 :     bms_free(bms2);
     992             : 
     993       20002 :     for (int i = 0; i < num_ops; i++)
     994             :     {
     995       20000 :         member = pg_prng_uint32(&state) % max_range + min_value;
     996       20000 :         switch (pg_prng_uint32(&state) % 3)
     997             :         {
     998        6766 :             case 0:             /* add */
     999        6766 :                 bms = bms_add_member(bms, member);
    1000        6766 :                 break;
    1001        6704 :             case 1:             /* delete */
    1002        6704 :                 if (bms != NULL)
    1003             :                 {
    1004        6700 :                     bms = bms_del_member(bms, member);
    1005             :                 }
    1006        6704 :                 break;
    1007        6530 :             case 2:             /* test membership */
    1008        6530 :                 if (bms != NULL)
    1009             :                 {
    1010        6530 :                     bms_is_member(member, bms);
    1011             :                 }
    1012        6530 :                 break;
    1013             :         }
    1014       20000 :         total_ops++;
    1015             :     }
    1016             : 
    1017           2 :     if (bms)
    1018           2 :         bms_free(bms);
    1019             : 
    1020           2 :     PG_RETURN_INT32(total_ops);
    1021             : }

Generated by: LCOV version 1.16