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

Generated by: LCOV version 1.13