LCOV - code coverage report
Current view: top level - contrib/hstore - hstore_gist.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 229 263 87.1 %
Date: 2024-03-28 20:11:39 Functions: 24 27 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * contrib/hstore/hstore_gist.c
       3             :  */
       4             : #include "postgres.h"
       5             : 
       6             : #include "access/gist.h"
       7             : #include "access/reloptions.h"
       8             : #include "access/stratnum.h"
       9             : #include "catalog/pg_type.h"
      10             : #include "common/int.h"
      11             : #include "hstore.h"
      12             : #include "utils/pg_crc.h"
      13             : 
      14             : /* gist_hstore_ops opclass options */
      15             : typedef struct
      16             : {
      17             :     int32       vl_len_;        /* varlena header (do not touch directly!) */
      18             :     int         siglen;         /* signature length in bytes */
      19             : } GistHstoreOptions;
      20             : 
      21             : /* bigint defines */
      22             : #define BITBYTE 8
      23             : #define SIGLEN_DEFAULT  (sizeof(int32) * 4)
      24             : #define SIGLEN_MAX      GISTMaxIndexKeySize
      25             : #define SIGLENBIT(siglen) ((siglen) * BITBYTE)
      26             : #define GET_SIGLEN()    (PG_HAS_OPCLASS_OPTIONS() ? \
      27             :                          ((GistHstoreOptions *) PG_GET_OPCLASS_OPTIONS())->siglen : \
      28             :                          SIGLEN_DEFAULT)
      29             : 
      30             : 
      31             : typedef char *BITVECP;
      32             : 
      33             : #define LOOPBYTE(siglen) \
      34             :             for (i = 0; i < (siglen); i++)
      35             : 
      36             : #define LOOPBIT(siglen) \
      37             :             for (i = 0; i < SIGLENBIT(siglen); i++)
      38             : 
      39             : /* beware of multiple evaluation of arguments to these macros! */
      40             : #define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITBYTE ) ) )
      41             : #define GETBITBYTE(x,i) ( (*((char*)(x)) >> (i)) & 0x01 )
      42             : #define CLRBIT(x,i)   GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) )
      43             : #define SETBIT(x,i)   GETBYTE(x,i) |=  ( 0x01 << ( (i) % BITBYTE ) )
      44             : #define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITBYTE )) & 0x01 )
      45             : #define HASHVAL(val, siglen) (((unsigned int)(val)) % SIGLENBIT(siglen))
      46             : #define HASH(sign, val, siglen) SETBIT((sign), HASHVAL(val, siglen))
      47             : 
      48             : typedef struct
      49             : {
      50             :     int32       vl_len_;        /* varlena header (do not touch directly!) */
      51             :     int32       flag;
      52             :     char        data[FLEXIBLE_ARRAY_MEMBER];
      53             : } GISTTYPE;
      54             : 
      55             : #define ALLISTRUE       0x04
      56             : 
      57             : #define ISALLTRUE(x)    ( ((GISTTYPE*)x)->flag & ALLISTRUE )
      58             : 
      59             : #define GTHDRSIZE       (VARHDRSZ + sizeof(int32))
      60             : #define CALCGTSIZE(flag, siglen) ( GTHDRSIZE+(((flag) & ALLISTRUE) ? 0 : (siglen)) )
      61             : 
      62             : #define GETSIGN(x)      ( (BITVECP)( (char*)x+GTHDRSIZE ) )
      63             : 
      64             : #define SUMBIT(val) (       \
      65             :     GETBITBYTE((val),0) + \
      66             :     GETBITBYTE((val),1) + \
      67             :     GETBITBYTE((val),2) + \
      68             :     GETBITBYTE((val),3) + \
      69             :     GETBITBYTE((val),4) + \
      70             :     GETBITBYTE((val),5) + \
      71             :     GETBITBYTE((val),6) + \
      72             :     GETBITBYTE((val),7)   \
      73             : )
      74             : 
      75             : #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
      76             : 
      77             : #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )
      78             : 
      79             : /* shorthand for calculating CRC-32 of a single chunk of data. */
      80             : static pg_crc32
      81       65820 : crc32_sz(const char *buf, int size)
      82             : {
      83             :     pg_crc32    crc;
      84             : 
      85       65820 :     INIT_TRADITIONAL_CRC32(crc);
      86      350616 :     COMP_TRADITIONAL_CRC32(crc, buf, size);
      87       65820 :     FIN_TRADITIONAL_CRC32(crc);
      88             : 
      89       65820 :     return crc;
      90             : }
      91             : 
      92             : 
      93          14 : PG_FUNCTION_INFO_V1(ghstore_in);
      94          14 : PG_FUNCTION_INFO_V1(ghstore_out);
      95             : 
      96             : 
      97             : Datum
      98           0 : ghstore_in(PG_FUNCTION_ARGS)
      99             : {
     100           0 :     ereport(ERROR,
     101             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     102             :              errmsg("cannot accept a value of type %s", "ghstore")));
     103             : 
     104             :     PG_RETURN_VOID();           /* keep compiler quiet */
     105             : }
     106             : 
     107             : Datum
     108           0 : ghstore_out(PG_FUNCTION_ARGS)
     109             : {
     110           0 :     ereport(ERROR,
     111             :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     112             :              errmsg("cannot display a value of type %s", "ghstore")));
     113             : 
     114             :     PG_RETURN_VOID();           /* keep compiler quiet */
     115             : }
     116             : 
     117             : static GISTTYPE *
     118       18932 : ghstore_alloc(bool allistrue, int siglen, BITVECP sign)
     119             : {
     120       18932 :     int         flag = allistrue ? ALLISTRUE : 0;
     121       18932 :     int         size = CALCGTSIZE(flag, siglen);
     122       18932 :     GISTTYPE   *res = palloc(size);
     123             : 
     124       18932 :     SET_VARSIZE(res, size);
     125       18932 :     res->flag = flag;
     126             : 
     127       18932 :     if (!allistrue)
     128             :     {
     129       18932 :         if (sign)
     130        2652 :             memcpy(GETSIGN(res), sign, siglen);
     131             :         else
     132       16280 :             memset(GETSIGN(res), 0, siglen);
     133             :     }
     134             : 
     135       18932 :     return res;
     136             : }
     137             : 
     138          16 : PG_FUNCTION_INFO_V1(ghstore_consistent);
     139          16 : PG_FUNCTION_INFO_V1(ghstore_compress);
     140          16 : PG_FUNCTION_INFO_V1(ghstore_decompress);
     141          16 : PG_FUNCTION_INFO_V1(ghstore_penalty);
     142          16 : PG_FUNCTION_INFO_V1(ghstore_picksplit);
     143          16 : PG_FUNCTION_INFO_V1(ghstore_union);
     144          16 : PG_FUNCTION_INFO_V1(ghstore_same);
     145          16 : PG_FUNCTION_INFO_V1(ghstore_options);
     146             : 
     147             : Datum
     148       16270 : ghstore_compress(PG_FUNCTION_ARGS)
     149             : {
     150       16270 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     151       16270 :     int         siglen = GET_SIGLEN();
     152       16270 :     GISTENTRY  *retval = entry;
     153             : 
     154       16270 :     if (entry->leafkey)
     155             :     {
     156        4004 :         GISTTYPE   *res = ghstore_alloc(false, siglen, NULL);
     157        4004 :         HStore     *val = DatumGetHStoreP(entry->key);
     158        4004 :         HEntry     *hsent = ARRPTR(val);
     159        4004 :         char       *ptr = STRPTR(val);
     160        4004 :         int         count = HS_COUNT(val);
     161             :         int         i;
     162             : 
     163       23128 :         for (i = 0; i < count; ++i)
     164             :         {
     165             :             int         h;
     166             : 
     167       19124 :             h = crc32_sz((char *) HSTORE_KEY(hsent, ptr, i),
     168       19124 :                          HSTORE_KEYLEN(hsent, i));
     169       19124 :             HASH(GETSIGN(res), h, siglen);
     170       19124 :             if (!HSTORE_VALISNULL(hsent, i))
     171             :             {
     172       19120 :                 h = crc32_sz((char *) HSTORE_VAL(hsent, ptr, i),
     173       19120 :                              HSTORE_VALLEN(hsent, i));
     174       19120 :                 HASH(GETSIGN(res), h, siglen);
     175             :             }
     176             :         }
     177             : 
     178        4004 :         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
     179        4004 :         gistentryinit(*retval, PointerGetDatum(res),
     180             :                       entry->rel, entry->page,
     181             :                       entry->offset,
     182             :                       false);
     183             :     }
     184       12266 :     else if (!ISALLTRUE(DatumGetPointer(entry->key)))
     185             :     {
     186             :         int32       i;
     187             :         GISTTYPE   *res;
     188       12266 :         BITVECP     sign = GETSIGN(DatumGetPointer(entry->key));
     189             : 
     190       12276 :         LOOPBYTE(siglen)
     191             :         {
     192       12276 :             if ((sign[i] & 0xff) != 0xff)
     193       12266 :                 PG_RETURN_POINTER(retval);
     194             :         }
     195             : 
     196           0 :         res = ghstore_alloc(true, siglen, NULL);
     197             : 
     198           0 :         retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
     199           0 :         gistentryinit(*retval, PointerGetDatum(res),
     200             :                       entry->rel, entry->page,
     201             :                       entry->offset,
     202             :                       false);
     203             :     }
     204             : 
     205        4004 :     PG_RETURN_POINTER(retval);
     206             : }
     207             : 
     208             : /*
     209             :  * Since type ghstore isn't toastable (and doesn't need to be),
     210             :  * this function can be a no-op.
     211             :  */
     212             : Datum
     213       96796 : ghstore_decompress(PG_FUNCTION_ARGS)
     214             : {
     215       96796 :     PG_RETURN_POINTER(PG_GETARG_POINTER(0));
     216             : }
     217             : 
     218             : Datum
     219       12276 : ghstore_same(PG_FUNCTION_ARGS)
     220             : {
     221       12276 :     GISTTYPE   *a = (GISTTYPE *) PG_GETARG_POINTER(0);
     222       12276 :     GISTTYPE   *b = (GISTTYPE *) PG_GETARG_POINTER(1);
     223       12276 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     224       12276 :     int         siglen = GET_SIGLEN();
     225             : 
     226             : 
     227       12276 :     if (ISALLTRUE(a) && ISALLTRUE(b))
     228           0 :         *result = true;
     229       12276 :     else if (ISALLTRUE(a))
     230           0 :         *result = false;
     231       12276 :     else if (ISALLTRUE(b))
     232           0 :         *result = false;
     233             :     else
     234             :     {
     235             :         int32       i;
     236       12276 :         BITVECP     sa = GETSIGN(a),
     237       12276 :                     sb = GETSIGN(b);
     238             : 
     239       12276 :         *result = true;
     240     9002414 :         LOOPBYTE(siglen)
     241             :         {
     242     8999752 :             if (sa[i] != sb[i])
     243             :             {
     244        9614 :                 *result = false;
     245        9614 :                 break;
     246             :             }
     247             :         }
     248             :     }
     249       12276 :     PG_RETURN_POINTER(result);
     250             : }
     251             : 
     252             : static int32
     253           0 : sizebitvec(BITVECP sign, int siglen)
     254             : {
     255           0 :     int32       size = 0,
     256             :                 i;
     257             : 
     258           0 :     LOOPBYTE(siglen)
     259             :     {
     260           0 :         size += SUMBIT(sign);
     261           0 :         sign = (BITVECP) (((char *) sign) + 1);
     262             :     }
     263           0 :     return size;
     264             : }
     265             : 
     266             : static int
     267      264760 : hemdistsign(BITVECP a, BITVECP b, int siglen)
     268             : {
     269             :     int         i,
     270      264760 :                 dist = 0;
     271             : 
     272   766833080 :     LOOPBIT(siglen)
     273             :     {
     274   766568320 :         if (GETBIT(a, i) != GETBIT(b, i))
     275     6753280 :             dist++;
     276             :     }
     277      264760 :     return dist;
     278             : }
     279             : 
     280             : static int
     281      264760 : hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
     282             : {
     283      264760 :     if (ISALLTRUE(a))
     284             :     {
     285           0 :         if (ISALLTRUE(b))
     286           0 :             return 0;
     287             :         else
     288           0 :             return SIGLENBIT(siglen) - sizebitvec(GETSIGN(b), siglen);
     289             :     }
     290      264760 :     else if (ISALLTRUE(b))
     291           0 :         return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
     292             : 
     293      264760 :     return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
     294             : }
     295             : 
     296             : static int32
     297       24552 : unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
     298             : {
     299             :     int32       i;
     300       24552 :     BITVECP     sadd = GETSIGN(add);
     301             : 
     302       24552 :     if (ISALLTRUE(add))
     303           0 :         return 1;
     304    43316296 :     LOOPBYTE(siglen)
     305    43291744 :         sbase[i] |= sadd[i];
     306       24552 :     return 0;
     307             : }
     308             : 
     309             : Datum
     310       12276 : ghstore_union(PG_FUNCTION_ARGS)
     311             : {
     312       12276 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     313       12276 :     int32       len = entryvec->n;
     314             : 
     315       12276 :     int        *size = (int *) PG_GETARG_POINTER(1);
     316       12276 :     int         siglen = GET_SIGLEN();
     317             :     int32       i;
     318       12276 :     GISTTYPE   *result = ghstore_alloc(false, siglen, NULL);
     319       12276 :     BITVECP     base = GETSIGN(result);
     320             : 
     321       36828 :     for (i = 0; i < len; i++)
     322             :     {
     323       24552 :         if (unionkey(base, GETENTRY(entryvec, i), siglen))
     324             :         {
     325           0 :             result->flag |= ALLISTRUE;
     326           0 :             SET_VARSIZE(result, CALCGTSIZE(ALLISTRUE, siglen));
     327           0 :             break;
     328             :         }
     329             :     }
     330             : 
     331       12276 :     *size = VARSIZE(result);
     332             : 
     333       12276 :     PG_RETURN_POINTER(result);
     334             : }
     335             : 
     336             : Datum
     337       31870 : ghstore_penalty(PG_FUNCTION_ARGS)
     338             : {
     339       31870 :     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
     340       31870 :     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
     341       31870 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     342       31870 :     int         siglen = GET_SIGLEN();
     343       31870 :     GISTTYPE   *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
     344       31870 :     GISTTYPE   *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
     345             : 
     346       31870 :     *penalty = hemdist(origval, newval, siglen);
     347       31870 :     PG_RETURN_POINTER(penalty);
     348             : }
     349             : 
     350             : 
     351             : typedef struct
     352             : {
     353             :     OffsetNumber pos;
     354             :     int32       cost;
     355             : } SPLITCOST;
     356             : 
     357             : static int
     358       12000 : comparecost(const void *a, const void *b)
     359             : {
     360       12000 :     return pg_cmp_s32(((const SPLITCOST *) a)->cost,
     361             :                       ((const SPLITCOST *) b)->cost);
     362             : }
     363             : 
     364             : 
     365             : Datum
     366        1326 : ghstore_picksplit(PG_FUNCTION_ARGS)
     367             : {
     368        1326 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     369        1326 :     OffsetNumber maxoff = entryvec->n - 2;
     370             : 
     371        1326 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     372        1326 :     int         siglen = GET_SIGLEN();
     373             :     OffsetNumber k,
     374             :                 j;
     375             :     GISTTYPE   *datum_l,
     376             :                *datum_r;
     377             :     BITVECP     union_l,
     378             :                 union_r;
     379             :     int32       size_alpha,
     380             :                 size_beta;
     381             :     int32       size_waste,
     382        1326 :                 waste = -1;
     383             :     int32       nbytes;
     384        1326 :     OffsetNumber seed_1 = 0,
     385        1326 :                 seed_2 = 0;
     386             :     OffsetNumber *left,
     387             :                *right;
     388             :     BITVECP     ptr;
     389             :     int         i;
     390             :     SPLITCOST  *costvector;
     391             :     GISTTYPE   *_k,
     392             :                *_j;
     393             : 
     394        1326 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     395        1326 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     396        1326 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     397             : 
     398        5978 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
     399             :     {
     400        4652 :         _k = GETENTRY(entryvec, k);
     401      213630 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
     402             :         {
     403      208978 :             size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
     404      208978 :             if (size_waste > waste)
     405             :             {
     406        2178 :                 waste = size_waste;
     407        2178 :                 seed_1 = k;
     408        2178 :                 seed_2 = j;
     409             :             }
     410             :         }
     411             :     }
     412             : 
     413        1326 :     left = v->spl_left;
     414        1326 :     v->spl_nleft = 0;
     415        1326 :     right = v->spl_right;
     416        1326 :     v->spl_nright = 0;
     417             : 
     418        1326 :     if (seed_1 == 0 || seed_2 == 0)
     419             :     {
     420           0 :         seed_1 = 1;
     421           0 :         seed_2 = 2;
     422             :     }
     423             : 
     424             :     /* form initial .. */
     425        1326 :     datum_l = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
     426        1326 :                             GETSIGN(GETENTRY(entryvec, seed_1)));
     427        1326 :     datum_r = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
     428        1326 :                             GETSIGN(GETENTRY(entryvec, seed_2)));
     429             : 
     430        1326 :     maxoff = OffsetNumberNext(maxoff);
     431             :     /* sort before ... */
     432        1326 :     costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
     433        8630 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     434             :     {
     435        7304 :         costvector[j - 1].pos = j;
     436        7304 :         _j = GETENTRY(entryvec, j);
     437        7304 :         size_alpha = hemdist(datum_l, _j, siglen);
     438        7304 :         size_beta = hemdist(datum_r, _j, siglen);
     439        7304 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
     440             :     }
     441        1326 :     qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
     442             : 
     443        1326 :     union_l = GETSIGN(datum_l);
     444        1326 :     union_r = GETSIGN(datum_r);
     445             : 
     446        8630 :     for (k = 0; k < maxoff; k++)
     447             :     {
     448        7304 :         j = costvector[k].pos;
     449        7304 :         if (j == seed_1)
     450             :         {
     451        1326 :             *left++ = j;
     452        1326 :             v->spl_nleft++;
     453        1326 :             continue;
     454             :         }
     455        5978 :         else if (j == seed_2)
     456             :         {
     457        1326 :             *right++ = j;
     458        1326 :             v->spl_nright++;
     459        1326 :             continue;
     460             :         }
     461        4652 :         _j = GETENTRY(entryvec, j);
     462        4652 :         size_alpha = hemdist(datum_l, _j, siglen);
     463        4652 :         size_beta = hemdist(datum_r, _j, siglen);
     464             : 
     465        4652 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.0001))
     466             :         {
     467        2306 :             if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
     468             :             {
     469           0 :                 if (!ISALLTRUE(datum_l))
     470           0 :                     memset(union_l, 0xff, siglen);
     471             :             }
     472             :             else
     473             :             {
     474        2306 :                 ptr = GETSIGN(_j);
     475     2557234 :                 LOOPBYTE(siglen)
     476     2554928 :                     union_l[i] |= ptr[i];
     477             :             }
     478        2306 :             *left++ = j;
     479        2306 :             v->spl_nleft++;
     480             :         }
     481             :         else
     482             :         {
     483        2346 :             if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
     484             :             {
     485           0 :                 if (!ISALLTRUE(datum_r))
     486           0 :                     memset(union_r, 0xff, siglen);
     487             :             }
     488             :             else
     489             :             {
     490        2346 :                 ptr = GETSIGN(_j);
     491     2806906 :                 LOOPBYTE(siglen)
     492     2804560 :                     union_r[i] |= ptr[i];
     493             :             }
     494        2346 :             *right++ = j;
     495        2346 :             v->spl_nright++;
     496             :         }
     497             :     }
     498             : 
     499        1326 :     *right = *left = FirstOffsetNumber;
     500             : 
     501        1326 :     v->spl_ldatum = PointerGetDatum(datum_l);
     502        1326 :     v->spl_rdatum = PointerGetDatum(datum_r);
     503             : 
     504        1326 :     PG_RETURN_POINTER(v);
     505             : }
     506             : 
     507             : 
     508             : Datum
     509       20794 : ghstore_consistent(PG_FUNCTION_ARGS)
     510             : {
     511       20794 :     GISTTYPE   *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     512       20794 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     513             : 
     514             :     /* Oid      subtype = PG_GETARG_OID(3); */
     515       20794 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     516       20794 :     int         siglen = GET_SIGLEN();
     517       20794 :     bool        res = true;
     518             :     BITVECP     sign;
     519             : 
     520             :     /* All cases served by this function are inexact */
     521       20794 :     *recheck = true;
     522             : 
     523       20794 :     if (ISALLTRUE(entry))
     524           0 :         PG_RETURN_BOOL(true);
     525             : 
     526       20794 :     sign = GETSIGN(entry);
     527             : 
     528       20794 :     if (strategy == HStoreContainsStrategyNumber ||
     529             :         strategy == HStoreOldContainsStrategyNumber)
     530        9398 :     {
     531        9398 :         HStore     *query = PG_GETARG_HSTORE_P(1);
     532        9398 :         HEntry     *qe = ARRPTR(query);
     533        9398 :         char       *qv = STRPTR(query);
     534        9398 :         int         count = HS_COUNT(query);
     535             :         int         i;
     536             : 
     537       19198 :         for (i = 0; res && i < count; ++i)
     538             :         {
     539        9800 :             int         crc = crc32_sz((char *) HSTORE_KEY(qe, qv, i),
     540        9800 :                                        HSTORE_KEYLEN(qe, i));
     541             : 
     542        9800 :             if (GETBIT(sign, HASHVAL(crc, siglen)))
     543             :             {
     544        3882 :                 if (!HSTORE_VALISNULL(qe, i))
     545             :                 {
     546        2284 :                     crc = crc32_sz((char *) HSTORE_VAL(qe, qv, i),
     547        2284 :                                    HSTORE_VALLEN(qe, i));
     548        2284 :                     if (!GETBIT(sign, HASHVAL(crc, siglen)))
     549        1138 :                         res = false;
     550             :                 }
     551             :             }
     552             :             else
     553        5918 :                 res = false;
     554             :         }
     555             :     }
     556       11396 :     else if (strategy == HStoreExistsStrategyNumber)
     557             :     {
     558        3804 :         text       *query = PG_GETARG_TEXT_PP(1);
     559        3804 :         int         crc = crc32_sz(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
     560             : 
     561        3804 :         res = (GETBIT(sign, HASHVAL(crc, siglen))) ? true : false;
     562             :     }
     563        7592 :     else if (strategy == HStoreExistsAllStrategyNumber)
     564             :     {
     565        3154 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
     566             :         Datum      *key_datums;
     567             :         bool       *key_nulls;
     568             :         int         key_count;
     569             :         int         i;
     570             : 
     571        3154 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     572             : 
     573        7524 :         for (i = 0; res && i < key_count; ++i)
     574             :         {
     575             :             int         crc;
     576             : 
     577        4370 :             if (key_nulls[i])
     578           0 :                 continue;
     579        4370 :             crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
     580        4370 :             if (!(GETBIT(sign, HASHVAL(crc, siglen))))
     581        2534 :                 res = false;
     582             :         }
     583             :     }
     584        4438 :     else if (strategy == HStoreExistsAnyStrategyNumber)
     585             :     {
     586        4438 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
     587             :         Datum      *key_datums;
     588             :         bool       *key_nulls;
     589             :         int         key_count;
     590             :         int         i;
     591             : 
     592        4438 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     593             : 
     594        4438 :         res = false;
     595             : 
     596       11756 :         for (i = 0; !res && i < key_count; ++i)
     597             :         {
     598             :             int         crc;
     599             : 
     600        7318 :             if (key_nulls[i])
     601           0 :                 continue;
     602        7318 :             crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
     603        7318 :             if (GETBIT(sign, HASHVAL(crc, siglen)))
     604        2400 :                 res = true;
     605             :         }
     606             :     }
     607             :     else
     608           0 :         elog(ERROR, "Unsupported strategy number: %d", strategy);
     609             : 
     610       20794 :     PG_RETURN_BOOL(res);
     611             : }
     612             : 
     613             : Datum
     614          20 : ghstore_options(PG_FUNCTION_ARGS)
     615             : {
     616          20 :     local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
     617             : 
     618          20 :     init_local_reloptions(relopts, sizeof(GistHstoreOptions));
     619          20 :     add_local_int_reloption(relopts, "siglen",
     620             :                             "signature length in bytes",
     621             :                             SIGLEN_DEFAULT, 1, SIGLEN_MAX,
     622             :                             offsetof(GistHstoreOptions, siglen));
     623             : 
     624          20 :     PG_RETURN_VOID();
     625             : }

Generated by: LCOV version 1.14