LCOV - code coverage report
Current view: top level - contrib/hstore - hstore_gist.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 87.1 % 264 230
Test Date: 2026-02-17 17:20:33 Functions: 88.9 % 27 24
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        33104 : crc32_sz(const char *buf, int size)
      82              : {
      83              :     pg_crc32    crc;
      84              : 
      85        33104 :     INIT_TRADITIONAL_CRC32(crc);
      86       176456 :     COMP_TRADITIONAL_CRC32(crc, buf, size);
      87        33104 :     FIN_TRADITIONAL_CRC32(crc);
      88              : 
      89        33104 :     return crc;
      90              : }
      91              : 
      92              : 
      93            7 : PG_FUNCTION_INFO_V1(ghstore_in);
      94            7 : 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         9537 : ghstore_alloc(bool allistrue, int siglen, BITVECP sign)
     119              : {
     120         9537 :     int         flag = allistrue ? ALLISTRUE : 0;
     121         9537 :     int         size = CALCGTSIZE(flag, siglen);
     122         9537 :     GISTTYPE   *res = palloc(size);
     123              : 
     124         9537 :     SET_VARSIZE(res, size);
     125         9537 :     res->flag = flag;
     126              : 
     127         9537 :     if (!allistrue)
     128              :     {
     129         9537 :         if (sign)
     130         1318 :             memcpy(GETSIGN(res), sign, siglen);
     131              :         else
     132         8219 :             memset(GETSIGN(res), 0, siglen);
     133              :     }
     134              : 
     135         9537 :     return res;
     136              : }
     137              : 
     138            8 : PG_FUNCTION_INFO_V1(ghstore_consistent);
     139            8 : PG_FUNCTION_INFO_V1(ghstore_compress);
     140            8 : PG_FUNCTION_INFO_V1(ghstore_decompress);
     141            8 : PG_FUNCTION_INFO_V1(ghstore_penalty);
     142            8 : PG_FUNCTION_INFO_V1(ghstore_picksplit);
     143            8 : PG_FUNCTION_INFO_V1(ghstore_union);
     144            8 : PG_FUNCTION_INFO_V1(ghstore_same);
     145            8 : PG_FUNCTION_INFO_V1(ghstore_options);
     146              : 
     147              : Datum
     148         8207 : ghstore_compress(PG_FUNCTION_ARGS)
     149              : {
     150         8207 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     151         8207 :     int         siglen = GET_SIGLEN();
     152         8207 :     GISTENTRY  *retval = entry;
     153              : 
     154         8207 :     if (entry->leafkey)
     155              :     {
     156         2002 :         GISTTYPE   *res = ghstore_alloc(false, siglen, NULL);
     157         2002 :         HStore     *val = DatumGetHStoreP(entry->key);
     158         2002 :         HEntry     *hsent = ARRPTR(val);
     159         2002 :         char       *ptr = STRPTR(val);
     160         2002 :         int         count = HS_COUNT(val);
     161              :         int         i;
     162              : 
     163        11564 :         for (i = 0; i < count; ++i)
     164              :         {
     165              :             int         h;
     166              : 
     167         9562 :             h = crc32_sz((char *) HSTORE_KEY(hsent, ptr, i),
     168         9562 :                          HSTORE_KEYLEN(hsent, i));
     169         9562 :             HASH(GETSIGN(res), h, siglen);
     170         9562 :             if (!HSTORE_VALISNULL(hsent, i))
     171              :             {
     172         9560 :                 h = crc32_sz((char *) HSTORE_VAL(hsent, ptr, i),
     173         9560 :                              HSTORE_VALLEN(hsent, i));
     174         9560 :                 HASH(GETSIGN(res), h, siglen);
     175              :             }
     176              :         }
     177              : 
     178         2002 :         retval = palloc_object(GISTENTRY);
     179         2002 :         gistentryinit(*retval, PointerGetDatum(res),
     180              :                       entry->rel, entry->page,
     181              :                       entry->offset,
     182              :                       false);
     183              :     }
     184         6205 :     else if (!ISALLTRUE(DatumGetPointer(entry->key)))
     185              :     {
     186              :         int32       i;
     187              :         GISTTYPE   *res;
     188         6205 :         BITVECP     sign = GETSIGN(DatumGetPointer(entry->key));
     189              : 
     190         6230 :         LOOPBYTE(siglen)
     191              :         {
     192         6230 :             if ((sign[i] & 0xff) != 0xff)
     193         6205 :                 PG_RETURN_POINTER(retval);
     194              :         }
     195              : 
     196            0 :         res = ghstore_alloc(true, siglen, NULL);
     197              : 
     198            0 :         retval = palloc_object(GISTENTRY);
     199            0 :         gistentryinit(*retval, PointerGetDatum(res),
     200              :                       entry->rel, entry->page,
     201              :                       entry->offset,
     202              :                       false);
     203              :     }
     204              : 
     205         2002 :     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        48997 : ghstore_decompress(PG_FUNCTION_ARGS)
     214              : {
     215        48997 :     PG_RETURN_POINTER(PG_GETARG_POINTER(0));
     216              : }
     217              : 
     218              : Datum
     219         6217 : ghstore_same(PG_FUNCTION_ARGS)
     220              : {
     221         6217 :     GISTTYPE   *a = (GISTTYPE *) PG_GETARG_POINTER(0);
     222         6217 :     GISTTYPE   *b = (GISTTYPE *) PG_GETARG_POINTER(1);
     223         6217 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     224         6217 :     int         siglen = GET_SIGLEN();
     225              : 
     226              : 
     227         6217 :     if (ISALLTRUE(a) && ISALLTRUE(b))
     228            0 :         *result = true;
     229         6217 :     else if (ISALLTRUE(a))
     230            0 :         *result = false;
     231         6217 :     else if (ISALLTRUE(b))
     232            0 :         *result = false;
     233              :     else
     234              :     {
     235              :         int32       i;
     236         6217 :         BITVECP     sa = GETSIGN(a),
     237         6217 :                     sb = GETSIGN(b);
     238              : 
     239         6217 :         *result = true;
     240      4625766 :         LOOPBYTE(siglen)
     241              :         {
     242      4624436 :             if (sa[i] != sb[i])
     243              :             {
     244         4887 :                 *result = false;
     245         4887 :                 break;
     246              :             }
     247              :         }
     248              :     }
     249         6217 :     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       132601 : hemdistsign(BITVECP a, BITVECP b, int siglen)
     268              : {
     269              :     int         i,
     270       132601 :                 dist = 0;
     271              : 
     272    384971129 :     LOOPBIT(siglen)
     273              :     {
     274    384838528 :         if (GETBIT(a, i) != GETBIT(b, i))
     275      3369320 :             dist++;
     276              :     }
     277       132601 :     return dist;
     278              : }
     279              : 
     280              : static int
     281       132601 : hemdist(GISTTYPE *a, GISTTYPE *b, int siglen)
     282              : {
     283       132601 :     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       132601 :     else if (ISALLTRUE(b))
     291            0 :         return SIGLENBIT(siglen) - sizebitvec(GETSIGN(a), siglen);
     292              : 
     293       132601 :     return hemdistsign(GETSIGN(a), GETSIGN(b), siglen);
     294              : }
     295              : 
     296              : static int32
     297        12434 : unionkey(BITVECP sbase, GISTTYPE *add, int siglen)
     298              : {
     299              :     int32       i;
     300        12434 :     BITVECP     sadd = GETSIGN(add);
     301              : 
     302        12434 :     if (ISALLTRUE(add))
     303            0 :         return 1;
     304     21978098 :     LOOPBYTE(siglen)
     305     21965664 :         sbase[i] |= sadd[i];
     306        12434 :     return 0;
     307              : }
     308              : 
     309              : Datum
     310         6217 : ghstore_union(PG_FUNCTION_ARGS)
     311              : {
     312         6217 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     313         6217 :     int32       len = entryvec->n;
     314              : 
     315         6217 :     int        *size = (int *) PG_GETARG_POINTER(1);
     316         6217 :     int         siglen = GET_SIGLEN();
     317              :     int32       i;
     318         6217 :     GISTTYPE   *result = ghstore_alloc(false, siglen, NULL);
     319         6217 :     BITVECP     base = GETSIGN(result);
     320              : 
     321        18651 :     for (i = 0; i < len; i++)
     322              :     {
     323        12434 :         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         6217 :     *size = VARSIZE(result);
     332              : 
     333         6217 :     PG_RETURN_POINTER(result);
     334              : }
     335              : 
     336              : Datum
     337        16216 : ghstore_penalty(PG_FUNCTION_ARGS)
     338              : {
     339        16216 :     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
     340        16216 :     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
     341        16216 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     342        16216 :     int         siglen = GET_SIGLEN();
     343        16216 :     GISTTYPE   *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
     344        16216 :     GISTTYPE   *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
     345              : 
     346        16216 :     *penalty = hemdist(origval, newval, siglen);
     347        16216 :     PG_RETURN_POINTER(penalty);
     348              : }
     349              : 
     350              : 
     351              : typedef struct
     352              : {
     353              :     OffsetNumber pos;
     354              :     int32       cost;
     355              : } SPLITCOST;
     356              : 
     357              : static int
     358         5954 : comparecost(const void *a, const void *b)
     359              : {
     360        11908 :     return pg_cmp_s32(((const SPLITCOST *) a)->cost,
     361         5954 :                       ((const SPLITCOST *) b)->cost);
     362              : }
     363              : 
     364              : 
     365              : Datum
     366          659 : ghstore_picksplit(PG_FUNCTION_ARGS)
     367              : {
     368          659 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     369          659 :     OffsetNumber maxoff = entryvec->n - 2;
     370              : 
     371          659 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     372          659 :     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          659 :                 waste = -1;
     383              :     int32       nbytes;
     384          659 :     OffsetNumber seed_1 = 0,
     385          659 :                 seed_2 = 0;
     386              :     OffsetNumber *left,
     387              :                *right;
     388              :     BITVECP     ptr;
     389              :     int         i;
     390              :     SPLITCOST  *costvector;
     391              :     GISTTYPE   *_k,
     392              :                *_j;
     393              : 
     394          659 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     395          659 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     396          659 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     397              : 
     398         2977 :     for (k = FirstOffsetNumber; k < maxoff; k = OffsetNumberNext(k))
     399              :     {
     400         2318 :         _k = GETENTRY(entryvec, k);
     401       106795 :         for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
     402              :         {
     403       104477 :             size_waste = hemdist(_k, GETENTRY(entryvec, j), siglen);
     404       104477 :             if (size_waste > waste)
     405              :             {
     406         1119 :                 waste = size_waste;
     407         1119 :                 seed_1 = k;
     408         1119 :                 seed_2 = j;
     409              :             }
     410              :         }
     411              :     }
     412              : 
     413          659 :     left = v->spl_left;
     414          659 :     v->spl_nleft = 0;
     415          659 :     right = v->spl_right;
     416          659 :     v->spl_nright = 0;
     417              : 
     418          659 :     if (seed_1 == 0 || seed_2 == 0)
     419              :     {
     420            0 :         seed_1 = 1;
     421            0 :         seed_2 = 2;
     422              :     }
     423              : 
     424              :     /* form initial .. */
     425          659 :     datum_l = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_1)), siglen,
     426          659 :                             GETSIGN(GETENTRY(entryvec, seed_1)));
     427          659 :     datum_r = ghstore_alloc(ISALLTRUE(GETENTRY(entryvec, seed_2)), siglen,
     428          659 :                             GETSIGN(GETENTRY(entryvec, seed_2)));
     429              : 
     430          659 :     maxoff = OffsetNumberNext(maxoff);
     431              :     /* sort before ... */
     432          659 :     costvector = palloc_array(SPLITCOST, maxoff);
     433         4295 :     for (j = FirstOffsetNumber; j <= maxoff; j = OffsetNumberNext(j))
     434              :     {
     435         3636 :         costvector[j - 1].pos = j;
     436         3636 :         _j = GETENTRY(entryvec, j);
     437         3636 :         size_alpha = hemdist(datum_l, _j, siglen);
     438         3636 :         size_beta = hemdist(datum_r, _j, siglen);
     439         3636 :         costvector[j - 1].cost = abs(size_alpha - size_beta);
     440              :     }
     441          659 :     qsort(costvector, maxoff, sizeof(SPLITCOST), comparecost);
     442              : 
     443          659 :     union_l = GETSIGN(datum_l);
     444          659 :     union_r = GETSIGN(datum_r);
     445              : 
     446         4295 :     for (k = 0; k < maxoff; k++)
     447              :     {
     448         3636 :         j = costvector[k].pos;
     449         3636 :         if (j == seed_1)
     450              :         {
     451          659 :             *left++ = j;
     452          659 :             v->spl_nleft++;
     453          659 :             continue;
     454              :         }
     455         2977 :         else if (j == seed_2)
     456              :         {
     457          659 :             *right++ = j;
     458          659 :             v->spl_nright++;
     459          659 :             continue;
     460              :         }
     461         2318 :         _j = GETENTRY(entryvec, j);
     462         2318 :         size_alpha = hemdist(datum_l, _j, siglen);
     463         2318 :         size_beta = hemdist(datum_r, _j, siglen);
     464              : 
     465         2318 :         if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.0001))
     466              :         {
     467         1124 :             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         1124 :                 ptr = GETSIGN(_j);
     475      1278124 :                 LOOPBYTE(siglen)
     476      1277000 :                     union_l[i] |= ptr[i];
     477              :             }
     478         1124 :             *left++ = j;
     479         1124 :             v->spl_nleft++;
     480              :         }
     481              :         else
     482              :         {
     483         1194 :             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         1194 :                 ptr = GETSIGN(_j);
     491      1387746 :                 LOOPBYTE(siglen)
     492      1386552 :                     union_r[i] |= ptr[i];
     493              :             }
     494         1194 :             *right++ = j;
     495         1194 :             v->spl_nright++;
     496              :         }
     497              :     }
     498              : 
     499          659 :     *right = *left = FirstOffsetNumber;
     500              : 
     501          659 :     v->spl_ldatum = PointerGetDatum(datum_l);
     502          659 :     v->spl_rdatum = PointerGetDatum(datum_r);
     503              : 
     504          659 :     PG_RETURN_POINTER(v);
     505              : }
     506              : 
     507              : 
     508              : Datum
     509        10494 : ghstore_consistent(PG_FUNCTION_ARGS)
     510              : {
     511        10494 :     GISTTYPE   *entry = (GISTTYPE *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     512        10494 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     513              : #ifdef NOT_USED
     514              :     Oid         subtype = PG_GETARG_OID(3);
     515              : #endif
     516        10494 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     517        10494 :     int         siglen = GET_SIGLEN();
     518        10494 :     bool        res = true;
     519              :     BITVECP     sign;
     520              : 
     521              :     /* All cases served by this function are inexact */
     522        10494 :     *recheck = true;
     523              : 
     524        10494 :     if (ISALLTRUE(entry))
     525            0 :         PG_RETURN_BOOL(true);
     526              : 
     527        10494 :     sign = GETSIGN(entry);
     528              : 
     529        10494 :     if (strategy == HStoreContainsStrategyNumber ||
     530              :         strategy == HStoreOldContainsStrategyNumber)
     531         4737 :     {
     532         4737 :         HStore     *query = PG_GETARG_HSTORE_P(1);
     533         4737 :         HEntry     *qe = ARRPTR(query);
     534         4737 :         char       *qv = STRPTR(query);
     535         4737 :         int         count = HS_COUNT(query);
     536              :         int         i;
     537              : 
     538         9693 :         for (i = 0; res && i < count; ++i)
     539              :         {
     540         4956 :             int         crc = crc32_sz((char *) HSTORE_KEY(qe, qv, i),
     541         4956 :                                        HSTORE_KEYLEN(qe, i));
     542              : 
     543         4956 :             if (GETBIT(sign, HASHVAL(crc, siglen)))
     544              :             {
     545         1973 :                 if (!HSTORE_VALISNULL(qe, i))
     546              :                 {
     547         1188 :                     crc = crc32_sz((char *) HSTORE_VAL(qe, qv, i),
     548         1188 :                                    HSTORE_VALLEN(qe, i));
     549         1188 :                     if (!GETBIT(sign, HASHVAL(crc, siglen)))
     550          577 :                         res = false;
     551              :                 }
     552              :             }
     553              :             else
     554         2983 :                 res = false;
     555              :         }
     556              :     }
     557         5757 :     else if (strategy == HStoreExistsStrategyNumber)
     558              :     {
     559         1934 :         text       *query = PG_GETARG_TEXT_PP(1);
     560         1934 :         int         crc = crc32_sz(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query));
     561              : 
     562         1934 :         res = (GETBIT(sign, HASHVAL(crc, siglen))) ? true : false;
     563              :     }
     564         3823 :     else if (strategy == HStoreExistsAllStrategyNumber)
     565              :     {
     566         1547 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
     567              :         Datum      *key_datums;
     568              :         bool       *key_nulls;
     569              :         int         key_count;
     570              :         int         i;
     571              : 
     572         1547 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     573              : 
     574         3691 :         for (i = 0; res && i < key_count; ++i)
     575              :         {
     576              :             int         crc;
     577              : 
     578         2144 :             if (key_nulls[i])
     579            0 :                 continue;
     580         2144 :             crc = crc32_sz(VARDATA(DatumGetPointer(key_datums[i])), VARSIZE(DatumGetPointer(key_datums[i])) - VARHDRSZ);
     581         2144 :             if (!(GETBIT(sign, HASHVAL(crc, siglen))))
     582         1251 :                 res = false;
     583              :         }
     584              :     }
     585         2276 :     else if (strategy == HStoreExistsAnyStrategyNumber)
     586              :     {
     587         2276 :         ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
     588              :         Datum      *key_datums;
     589              :         bool       *key_nulls;
     590              :         int         key_count;
     591              :         int         i;
     592              : 
     593         2276 :         deconstruct_array_builtin(query, TEXTOID, &key_datums, &key_nulls, &key_count);
     594              : 
     595         2276 :         res = false;
     596              : 
     597         6036 :         for (i = 0; !res && i < key_count; ++i)
     598              :         {
     599              :             int         crc;
     600              : 
     601         3760 :             if (key_nulls[i])
     602            0 :                 continue;
     603         3760 :             crc = crc32_sz(VARDATA(DatumGetPointer(key_datums[i])), VARSIZE(DatumGetPointer(key_datums[i])) - VARHDRSZ);
     604         3760 :             if (GETBIT(sign, HASHVAL(crc, siglen)))
     605         1222 :                 res = true;
     606              :         }
     607              :     }
     608              :     else
     609            0 :         elog(ERROR, "Unsupported strategy number: %d", strategy);
     610              : 
     611        10494 :     PG_RETURN_BOOL(res);
     612              : }
     613              : 
     614              : Datum
     615           10 : ghstore_options(PG_FUNCTION_ARGS)
     616              : {
     617           10 :     local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
     618              : 
     619           10 :     init_local_reloptions(relopts, sizeof(GistHstoreOptions));
     620           10 :     add_local_int_reloption(relopts, "siglen",
     621              :                             "signature length in bytes",
     622              :                             SIGLEN_DEFAULT, 1, SIGLEN_MAX,
     623              :                             offsetof(GistHstoreOptions, siglen));
     624              : 
     625           10 :     PG_RETURN_VOID();
     626              : }
        

Generated by: LCOV version 2.0-1