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

Generated by: LCOV version 2.3.2-1