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-05-09 16:10:48 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       66104 : crc32_sz(const char *buf, int size)
      82             : {
      83             :     pg_crc32    crc;
      84             : 
      85       66104 :     INIT_TRADITIONAL_CRC32(crc);
      86      352586 :     COMP_TRADITIONAL_CRC32(crc, buf, size);
      87       66104 :     FIN_TRADITIONAL_CRC32(crc);
      88             : 
      89       66104 :     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       18926 : ghstore_alloc(bool allistrue, int siglen, BITVECP sign)
     119             : {
     120       18926 :     int         flag = allistrue ? ALLISTRUE : 0;
     121       18926 :     int         size = CALCGTSIZE(flag, siglen);
     122       18926 :     GISTTYPE   *res = palloc(size);
     123             : 
     124       18926 :     SET_VARSIZE(res, size);
     125       18926 :     res->flag = flag;
     126             : 
     127       18926 :     if (!allistrue)
     128             :     {
     129       18926 :         if (sign)
     130        2664 :             memcpy(GETSIGN(res), sign, siglen);
     131             :         else
     132       16262 :             memset(GETSIGN(res), 0, siglen);
     133             :     }
     134             : 
     135       18926 :     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       16302 : ghstore_compress(PG_FUNCTION_ARGS)
     149             : {
     150       16302 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     151       16302 :     int         siglen = GET_SIGLEN();
     152       16302 :     GISTENTRY  *retval = entry;
     153             : 
     154       16302 :     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       12298 :     else if (!ISALLTRUE(DatumGetPointer(entry->key)))
     185             :     {
     186             :         int32       i;
     187             :         GISTTYPE   *res;
     188       12298 :         BITVECP     sign = GETSIGN(DatumGetPointer(entry->key));
     189             : 
     190       12298 :         LOOPBYTE(siglen)
     191             :         {
     192       12298 :             if ((sign[i] & 0xff) != 0xff)
     193       12298 :                 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       97074 : ghstore_decompress(PG_FUNCTION_ARGS)
     214             : {
     215       97074 :     PG_RETURN_POINTER(PG_GETARG_POINTER(0));
     216             : }
     217             : 
     218             : Datum
     219       12258 : ghstore_same(PG_FUNCTION_ARGS)
     220             : {
     221       12258 :     GISTTYPE   *a = (GISTTYPE *) PG_GETARG_POINTER(0);
     222       12258 :     GISTTYPE   *b = (GISTTYPE *) PG_GETARG_POINTER(1);
     223       12258 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     224       12258 :     int         siglen = GET_SIGLEN();
     225             : 
     226             : 
     227       12258 :     if (ISALLTRUE(a) && ISALLTRUE(b))
     228           0 :         *result = true;
     229       12258 :     else if (ISALLTRUE(a))
     230           0 :         *result = false;
     231       12258 :     else if (ISALLTRUE(b))
     232           0 :         *result = false;
     233             :     else
     234             :     {
     235             :         int32       i;
     236       12258 :         BITVECP     sa = GETSIGN(a),
     237       12258 :                     sb = GETSIGN(b);
     238             : 
     239       12258 :         *result = true;
     240     9013226 :         LOOPBYTE(siglen)
     241             :         {
     242     9010602 :             if (sa[i] != sb[i])
     243             :             {
     244        9634 :                 *result = false;
     245        9634 :                 break;
     246             :             }
     247             :         }
     248             :     }
     249       12258 :     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      264980 : hemdistsign(BITVECP a, BITVECP b, int siglen)
     268             : {
     269             :     int         i,
     270      264980 :                 dist = 0;
     271             : 
     272   768499988 :     LOOPBIT(siglen)
     273             :     {
     274   768235008 :         if (GETBIT(a, i) != GETBIT(b, i))
     275     6725266 :             dist++;
     276             :     }
     277      264980 :     return dist;
     278             : }
     279             : 
     280             : static int
     281      264980 : hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
     282             : {
     283      264980 :     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      264980 :     else if (ISALLTRUE(b))
     291           0 :         return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
     292             : 
     293      264980 :     return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
     294             : }
     295             : 
     296             : static int32
     297       24516 : unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
     298             : {
     299             :     int32       i;
     300       24516 :     BITVECP     sadd = GETSIGN(add);
     301             : 
     302       24516 :     if (ISALLTRUE(add))
     303           0 :         return 1;
     304    43243396 :     LOOPBYTE(siglen)
     305    43218880 :         sbase[i] |= sadd[i];
     306       24516 :     return 0;
     307             : }
     308             : 
     309             : Datum
     310       12258 : ghstore_union(PG_FUNCTION_ARGS)
     311             : {
     312       12258 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     313       12258 :     int32       len = entryvec->n;
     314             : 
     315       12258 :     int        *size = (int *) PG_GETARG_POINTER(1);
     316       12258 :     int         siglen = GET_SIGLEN();
     317             :     int32       i;
     318       12258 :     GISTTYPE   *result = ghstore_alloc(false, siglen, NULL);
     319       12258 :     BITVECP     base = GETSIGN(result);
     320             : 
     321       36774 :     for (i = 0; i < len; i++)
     322             :     {
     323       24516 :         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       12258 :     *size = VARSIZE(result);
     332             : 
     333       12258 :     PG_RETURN_POINTER(result);
     334             : }
     335             : 
     336             : Datum
     337       32000 : ghstore_penalty(PG_FUNCTION_ARGS)
     338             : {
     339       32000 :     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
     340       32000 :     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
     341       32000 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     342       32000 :     int         siglen = GET_SIGLEN();
     343       32000 :     GISTTYPE   *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
     344       32000 :     GISTTYPE   *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
     345             : 
     346       32000 :     *penalty = hemdist(origval, newval, siglen);
     347       32000 :     PG_RETURN_POINTER(penalty);
     348             : }
     349             : 
     350             : 
     351             : typedef struct
     352             : {
     353             :     OffsetNumber pos;
     354             :     int32       cost;
     355             : } SPLITCOST;
     356             : 
     357             : static int
     358       12232 : comparecost(const void *a, const void *b)
     359             : {
     360       12232 :     return pg_cmp_s32(((const SPLITCOST *) a)->cost,
     361             :                       ((const SPLITCOST *) b)->cost);
     362             : }
     363             : 
     364             : 
     365             : Datum
     366        1332 : ghstore_picksplit(PG_FUNCTION_ARGS)
     367             : {
     368        1332 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     369        1332 :     OffsetNumber maxoff = entryvec->n - 2;
     370             : 
     371        1332 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     372        1332 :     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        1332 :                 waste = -1;
     383             :     int32       nbytes;
     384        1332 :     OffsetNumber seed_1 = 0,
     385        1332 :                 seed_2 = 0;
     386             :     OffsetNumber *left,
     387             :                *right;
     388             :     BITVECP     ptr;
     389             :     int         i;
     390             :     SPLITCOST  *costvector;
     391             :     GISTTYPE   *_k,
     392             :                *_j;
     393             : 
     394        1332 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     395        1332 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     396        1332 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     397             : 
     398        5996 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
     399             :     {
     400        4664 :         _k = GETENTRY(entryvec, k);
     401      213660 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
     402             :         {
     403      208996 :             size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
     404      208996 :             if (size_waste > waste)
     405             :             {
     406        2228 :                 waste = size_waste;
     407        2228 :                 seed_1 = k;
     408        2228 :                 seed_2 = j;
     409             :             }
     410             :         }
     411             :     }
     412             : 
     413        1332 :     left = v->spl_left;
     414        1332 :     v->spl_nleft = 0;
     415        1332 :     right = v->spl_right;
     416        1332 :     v->spl_nright = 0;
     417             : 
     418        1332 :     if (seed_1 == 0 || seed_2 == 0)
     419             :     {
     420           0 :         seed_1 = 1;
     421           0 :         seed_2 = 2;
     422             :     }
     423             : 
     424             :     /* form initial .. */
     425        1332 :     datum_l = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
     426        1332 :                             GETSIGN(GETENTRY(entryvec, seed_1)));
     427        1332 :     datum_r = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
     428        1332 :                             GETSIGN(GETENTRY(entryvec, seed_2)));
     429             : 
     430        1332 :     maxoff = OffsetNumberNext(maxoff);
     431             :     /* sort before ... */
     432        1332 :     costvector = (SPLITCOST *) palloc(sizeof(SPLITCOST) * maxoff);
     433        8660 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     434             :     {
     435        7328 :         costvector[j - 1].pos = j;
     436        7328 :         _j = GETENTRY(entryvec, j);
     437        7328 :         size_alpha = hemdist(datum_l, _j, siglen);
     438        7328 :         size_beta = hemdist(datum_r, _j, siglen);
     439        7328 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
     440             :     }
     441        1332 :     qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
     442             : 
     443        1332 :     union_l = GETSIGN(datum_l);
     444        1332 :     union_r = GETSIGN(datum_r);
     445             : 
     446        8660 :     for (k = 0; k < maxoff; k++)
     447             :     {
     448        7328 :         j = costvector[k].pos;
     449        7328 :         if (j == seed_1)
     450             :         {
     451        1332 :             *left++ = j;
     452        1332 :             v->spl_nleft++;
     453        1332 :             continue;
     454             :         }
     455        5996 :         else if (j == seed_2)
     456             :         {
     457        1332 :             *right++ = j;
     458        1332 :             v->spl_nright++;
     459        1332 :             continue;
     460             :         }
     461        4664 :         _j = GETENTRY(entryvec, j);
     462        4664 :         size_alpha = hemdist(datum_l, _j, siglen);
     463        4664 :         size_beta = hemdist(datum_r, _j, siglen);
     464             : 
     465        4664 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.0001))
     466             :         {
     467        2298 :             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        2298 :                 ptr = GETSIGN(_j);
     475     2637418 :                 LOOPBYTE(siglen)
     476     2635120 :                     union_l[i] |= ptr[i];
     477             :             }
     478        2298 :             *left++ = j;
     479        2298 :             v->spl_nleft++;
     480             :         }
     481             :         else
     482             :         {
     483        2366 :             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        2366 :                 ptr = GETSIGN(_j);
     491     2751022 :                 LOOPBYTE(siglen)
     492     2748656 :                     union_r[i] |= ptr[i];
     493             :             }
     494        2366 :             *right++ = j;
     495        2366 :             v->spl_nright++;
     496             :         }
     497             :     }
     498             : 
     499        1332 :     *right = *left = FirstOffsetNumber;
     500             : 
     501        1332 :     v->spl_ldatum = PointerGetDatum(datum_l);
     502        1332 :     v->spl_rdatum = PointerGetDatum(datum_r);
     503             : 
     504        1332 :     PG_RETURN_POINTER(v);
     505             : }
     506             : 
     507             : 
     508             : Datum
     509       20972 : ghstore_consistent(PG_FUNCTION_ARGS)
     510             : {
     511       20972 :     GISTTYPE   *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     512       20972 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     513             : 
     514             :     /* Oid      subtype = PG_GETARG_OID(3); */
     515       20972 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     516       20972 :     int         siglen = GET_SIGLEN();
     517       20972 :     bool        res = true;
     518             :     BITVECP     sign;
     519             : 
     520             :     /* All cases served by this function are inexact */
     521       20972 :     *recheck = true;
     522             : 
     523       20972 :     if (ISALLTRUE(entry))
     524           0 :         PG_RETURN_BOOL(true);
     525             : 
     526       20972 :     sign = GETSIGN(entry);
     527             : 
     528       20972 :     if (strategy == HStoreContainsStrategyNumber ||
     529             :         strategy == HStoreOldContainsStrategyNumber)
     530        9408 :     {
     531        9408 :         HStore     *query = PG_GETARG_HSTORE_P(1);
     532        9408 :         HEntry     *qe = ARRPTR(query);
     533        9408 :         char       *qv = STRPTR(query);
     534        9408 :         int         count = HS_COUNT(query);
     535             :         int         i;
     536             : 
     537       19232 :         for (i = 0; res && i < count; ++i)
     538             :         {
     539        9824 :             int         crc = crc32_sz((char *) HSTORE_KEY(qe, qv, i),
     540        9824 :                                        HSTORE_KEYLEN(qe, i));
     541             : 
     542        9824 :             if (GETBIT(sign, HASHVAL(crc, siglen)))
     543             :             {
     544        3882 :                 if (!HSTORE_VALISNULL(qe, i))
     545             :                 {
     546        2312 :                     crc = crc32_sz((char *) HSTORE_VAL(qe, qv, i),
     547        2312 :                                    HSTORE_VALLEN(qe, i));
     548        2312 :                     if (!GETBIT(sign, HASHVAL(crc, siglen)))
     549        1130 :                         res = false;
     550             :                 }
     551             :             }
     552             :             else
     553        5942 :                 res = false;
     554             :         }
     555             :     }
     556       11564 :     else if (strategy == HStoreExistsStrategyNumber)
     557             :     {
     558        3852 :         text       *query = PG_GETARG_TEXT_PP(1);
     559        3852 :         int         crc = crc32_sz(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
     560             : 
     561        3852 :         res = (GETBIT(sign, HASHVAL(crc, siglen))) ? true : false;
     562             :     }
     563        7712 :     else if (strategy == HStoreExistsAllStrategyNumber)
     564             :     {
     565        3250 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
     566             :         Datum      *key_datums;
     567             :         bool       *key_nulls;
     568             :         int         key_count;
     569             :         int         i;
     570             : 
     571        3250 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     572             : 
     573        7774 :         for (i = 0; res && i < key_count; ++i)
     574             :         {
     575             :             int         crc;
     576             : 
     577        4524 :             if (key_nulls[i])
     578           0 :                 continue;
     579        4524 :             crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
     580        4524 :             if (!(GETBIT(sign, HASHVAL(crc, siglen))))
     581        2588 :                 res = false;
     582             :         }
     583             :     }
     584        4462 :     else if (strategy == HStoreExistsAnyStrategyNumber)
     585             :     {
     586        4462 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
     587             :         Datum      *key_datums;
     588             :         bool       *key_nulls;
     589             :         int         key_count;
     590             :         int         i;
     591             : 
     592        4462 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     593             : 
     594        4462 :         res = false;
     595             : 
     596       11810 :         for (i = 0; !res && i < key_count; ++i)
     597             :         {
     598             :             int         crc;
     599             : 
     600        7348 :             if (key_nulls[i])
     601           0 :                 continue;
     602        7348 :             crc = crc32_sz(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ);
     603        7348 :             if (GETBIT(sign, HASHVAL(crc, siglen)))
     604        2406 :                 res = true;
     605             :         }
     606             :     }
     607             :     else
     608           0 :         elog(ERROR, "Unsupported strategy number: %d", strategy);
     609             : 
     610       20972 :     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