LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_utils_var.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 268 278 96.4 %
Date: 2024-12-12 16:15:21 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * contrib/btree_gist/btree_utils_var.c
       3             :  */
       4             : #include "postgres.h"
       5             : 
       6             : #include <math.h>
       7             : #include <limits.h>
       8             : #include <float.h>
       9             : 
      10             : #include "btree_gist.h"
      11             : #include "btree_utils_var.h"
      12             : #include "mb/pg_wchar.h"
      13             : #include "utils/rel.h"
      14             : 
      15             : /* used for key sorting */
      16             : typedef struct
      17             : {
      18             :     int         i;
      19             :     GBT_VARKEY *t;
      20             : } Vsrt;
      21             : 
      22             : typedef struct
      23             : {
      24             :     const gbtree_vinfo *tinfo;
      25             :     Oid         collation;
      26             :     FmgrInfo   *flinfo;
      27             : } gbt_vsrt_arg;
      28             : 
      29             : 
      30          18 : PG_FUNCTION_INFO_V1(gbt_var_decompress);
      31          18 : PG_FUNCTION_INFO_V1(gbt_var_fetch);
      32             : 
      33             : 
      34             : Datum
      35      172018 : gbt_var_decompress(PG_FUNCTION_ARGS)
      36             : {
      37      172018 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
      38      172018 :     GBT_VARKEY *key = (GBT_VARKEY *) PG_DETOAST_DATUM(entry->key);
      39             : 
      40      172018 :     if (key != (GBT_VARKEY *) DatumGetPointer(entry->key))
      41             :     {
      42      171156 :         GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
      43             : 
      44      171156 :         gistentryinit(*retval, PointerGetDatum(key),
      45             :                       entry->rel, entry->page,
      46             :                       entry->offset, false);
      47             : 
      48      171156 :         PG_RETURN_POINTER(retval);
      49             :     }
      50             : 
      51         862 :     PG_RETURN_POINTER(entry);
      52             : }
      53             : 
      54             : /* Returns a better readable representation of variable key ( sets pointer ) */
      55             : GBT_VARKEY_R
      56      666602 : gbt_var_key_readable(const GBT_VARKEY *k)
      57             : {
      58             :     GBT_VARKEY_R r;
      59             : 
      60      666602 :     r.lower = (bytea *) &(((char *) k)[VARHDRSZ]);
      61      666602 :     if (VARSIZE(k) > (VARHDRSZ + (VARSIZE(r.lower))))
      62      324408 :         r.upper = (bytea *) &(((char *) k)[VARHDRSZ + INTALIGN(VARSIZE(r.lower))]);
      63             :     else
      64      342194 :         r.upper = r.lower;
      65      666602 :     return r;
      66             : }
      67             : 
      68             : 
      69             : /*
      70             :  * Create a leaf-entry to store in the index, from a single Datum.
      71             :  */
      72             : static GBT_VARKEY *
      73       16524 : gbt_var_key_from_datum(const struct varlena *u)
      74             : {
      75       16524 :     int32       lowersize = VARSIZE(u);
      76             :     GBT_VARKEY *r;
      77             : 
      78       16524 :     r = (GBT_VARKEY *) palloc(lowersize + VARHDRSZ);
      79       16524 :     memcpy(VARDATA(r), u, lowersize);
      80       16524 :     SET_VARSIZE(r, lowersize + VARHDRSZ);
      81             : 
      82       16524 :     return r;
      83             : }
      84             : 
      85             : /*
      86             :  * Create an entry to store in the index, from lower and upper bound.
      87             :  */
      88             : GBT_VARKEY *
      89       87442 : gbt_var_key_copy(const GBT_VARKEY_R *u)
      90             : {
      91       87442 :     int32       lowersize = VARSIZE(u->lower);
      92       87442 :     int32       uppersize = VARSIZE(u->upper);
      93             :     GBT_VARKEY *r;
      94             : 
      95       87442 :     r = (GBT_VARKEY *) palloc0(INTALIGN(lowersize) + uppersize + VARHDRSZ);
      96       87442 :     memcpy(VARDATA(r), u->lower, lowersize);
      97       87442 :     memcpy(VARDATA(r) + INTALIGN(lowersize), u->upper, uppersize);
      98       87442 :     SET_VARSIZE(r, INTALIGN(lowersize) + uppersize + VARHDRSZ);
      99             : 
     100       87442 :     return r;
     101             : }
     102             : 
     103             : 
     104             : static GBT_VARKEY *
     105      122422 : gbt_var_leaf2node(GBT_VARKEY *leaf, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
     106             : {
     107      122422 :     GBT_VARKEY *out = leaf;
     108             : 
     109      122422 :     if (tinfo->f_l2n)
     110       10220 :         out = tinfo->f_l2n(leaf, flinfo);
     111             : 
     112      122422 :     return out;
     113             : }
     114             : 
     115             : 
     116             : /*
     117             :  * returns the common prefix length of a node key
     118             : */
     119             : static int32
     120       41532 : gbt_var_node_cp_len(const GBT_VARKEY *node, const gbtree_vinfo *tinfo)
     121             : {
     122       41532 :     GBT_VARKEY_R r = gbt_var_key_readable(node);
     123       41532 :     int32       i = 0;
     124       41532 :     int32       l = 0;
     125       41532 :     int32       t1len = VARSIZE(r.lower) - VARHDRSZ;
     126       41532 :     int32       t2len = VARSIZE(r.upper) - VARHDRSZ;
     127       41532 :     int32       ml = Min(t1len, t2len);
     128       41532 :     char       *p1 = VARDATA(r.lower);
     129       41532 :     char       *p2 = VARDATA(r.upper);
     130             : 
     131       41532 :     if (ml == 0)
     132       13136 :         return 0;
     133             : 
     134       28396 :     while (i < ml)
     135             :     {
     136       28396 :         if (tinfo->eml > 1 && l == 0)
     137             :         {
     138       18216 :             if ((l = pg_mblen(p1)) != pg_mblen(p2))
     139             :             {
     140           0 :                 return i;
     141             :             }
     142             :         }
     143       28396 :         if (*p1 != *p2)
     144             :         {
     145       28396 :             if (tinfo->eml > 1)
     146             :             {
     147       18216 :                 return (i - l + 1);
     148             :             }
     149             :             else
     150             :             {
     151       10180 :                 return i;
     152             :             }
     153             :         }
     154             : 
     155           0 :         p1++;
     156           0 :         p2++;
     157           0 :         l--;
     158           0 :         i++;
     159             :     }
     160           0 :     return ml;                  /* lower == upper */
     161             : }
     162             : 
     163             : 
     164             : /*
     165             :  * returns true, if query matches prefix ( common prefix )
     166             :  */
     167             : static bool
     168       19336 : gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinfo)
     169             : {
     170       19336 :     bool        out = false;
     171       19336 :     int32       qlen = VARSIZE(query) - VARHDRSZ;
     172       19336 :     int32       nlen = VARSIZE(pf) - VARHDRSZ;
     173             : 
     174       19336 :     if (nlen <= qlen)
     175             :     {
     176        9056 :         char       *q = VARDATA(query);
     177        9056 :         char       *n = VARDATA(pf);
     178             : 
     179        9056 :         out = (memcmp(q, n, nlen) == 0);
     180             :     }
     181             : 
     182       19336 :     return out;
     183             : }
     184             : 
     185             : 
     186             : /*
     187             :  * returns true, if query matches node using common prefix
     188             :  */
     189             : static bool
     190         318 : gbt_var_node_pf_match(const GBT_VARKEY_R *node, const bytea *query, const gbtree_vinfo *tinfo)
     191             : {
     192         474 :     return (tinfo->trnc &&
     193         156 :             (gbt_bytea_pf_match(node->lower, query, tinfo) ||
     194          68 :              gbt_bytea_pf_match(node->upper, query, tinfo)));
     195             : }
     196             : 
     197             : 
     198             : /*
     199             : *  truncates / compresses the node key
     200             : *  cpf_length .. common prefix length
     201             : */
     202             : static GBT_VARKEY *
     203        3192 : gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vinfo *tinfo)
     204             : {
     205        3192 :     GBT_VARKEY *out = NULL;
     206        3192 :     GBT_VARKEY_R r = gbt_var_key_readable(node);
     207        3192 :     int32       len1 = VARSIZE(r.lower) - VARHDRSZ;
     208        3192 :     int32       len2 = VARSIZE(r.upper) - VARHDRSZ;
     209             :     int32       si;
     210             :     char       *out2;
     211             : 
     212        3192 :     len1 = Min(len1, (cpf_length + 1));
     213        3192 :     len2 = Min(len2, (cpf_length + 1));
     214             : 
     215        3192 :     si = 2 * VARHDRSZ + INTALIGN(len1 + VARHDRSZ) + len2;
     216        3192 :     out = (GBT_VARKEY *) palloc0(si);
     217        3192 :     SET_VARSIZE(out, si);
     218             : 
     219        3192 :     memcpy(VARDATA(out), r.lower, len1 + VARHDRSZ);
     220        3192 :     SET_VARSIZE(VARDATA(out), len1 + VARHDRSZ);
     221             : 
     222        3192 :     out2 = VARDATA(out) + INTALIGN(len1 + VARHDRSZ);
     223        3192 :     memcpy(out2, r.upper, len2 + VARHDRSZ);
     224        3192 :     SET_VARSIZE(out2, len2 + VARHDRSZ);
     225             : 
     226        3192 :     return out;
     227             : }
     228             : 
     229             : 
     230             : 
     231             : void
     232       94520 : gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
     233             :                   const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
     234             : {
     235       94520 :     GBT_VARKEY_R eo = gbt_var_key_readable(e);
     236             :     GBT_VARKEY_R nr;
     237             : 
     238       94520 :     if (eo.lower == eo.upper)   /* leaf */
     239             :     {
     240             :         GBT_VARKEY *tmp;
     241             : 
     242       72364 :         tmp = gbt_var_leaf2node(e, tinfo, flinfo);
     243       72364 :         if (tmp != e)
     244        4112 :             eo = gbt_var_key_readable(tmp);
     245             :     }
     246             : 
     247       94520 :     if (DatumGetPointer(*u))
     248             :     {
     249       75130 :         GBT_VARKEY_R ro = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(*u));
     250       75130 :         bool        update = false;
     251             : 
     252       75130 :         nr.lower = ro.lower;
     253       75130 :         nr.upper = ro.upper;
     254             : 
     255       75130 :         if (tinfo->f_cmp(ro.lower, eo.lower, collation, flinfo) > 0)
     256             :         {
     257       17102 :             nr.lower = eo.lower;
     258       17102 :             update = true;
     259             :         }
     260             : 
     261       75130 :         if (tinfo->f_cmp(ro.upper, eo.upper, collation, flinfo) < 0)
     262             :         {
     263       15414 :             nr.upper = eo.upper;
     264       15414 :             update = true;
     265             :         }
     266             : 
     267       75130 :         if (update)
     268       32516 :             *u = PointerGetDatum(gbt_var_key_copy(&nr));
     269             :     }
     270             :     else
     271             :     {
     272       19390 :         nr.lower = eo.lower;
     273       19390 :         nr.upper = eo.upper;
     274       19390 :         *u = PointerGetDatum(gbt_var_key_copy(&nr));
     275             :     }
     276       94520 : }
     277             : 
     278             : 
     279             : GISTENTRY *
     280       16822 : gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
     281             : {
     282             :     GISTENTRY  *retval;
     283             : 
     284       16822 :     if (entry->leafkey)
     285             :     {
     286       16524 :         struct varlena *leaf = PG_DETOAST_DATUM(entry->key);
     287             :         GBT_VARKEY *r;
     288             : 
     289       16524 :         r = gbt_var_key_from_datum(leaf);
     290             : 
     291       16524 :         retval = palloc(sizeof(GISTENTRY));
     292       16524 :         gistentryinit(*retval, PointerGetDatum(r),
     293             :                       entry->rel, entry->page,
     294             :                       entry->offset, true);
     295             :     }
     296             :     else
     297         298 :         retval = entry;
     298             : 
     299       16822 :     return retval;
     300             : }
     301             : 
     302             : 
     303             : Datum
     304          12 : gbt_var_fetch(PG_FUNCTION_ARGS)
     305             : {
     306          12 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     307          12 :     GBT_VARKEY *key = (GBT_VARKEY *) PG_DETOAST_DATUM(entry->key);
     308          12 :     GBT_VARKEY_R r = gbt_var_key_readable(key);
     309             :     GISTENTRY  *retval;
     310             : 
     311          12 :     retval = palloc(sizeof(GISTENTRY));
     312          12 :     gistentryinit(*retval, PointerGetDatum(r.lower),
     313             :                   entry->rel, entry->page,
     314             :                   entry->offset, true);
     315             : 
     316          12 :     PG_RETURN_POINTER(retval);
     317             : }
     318             : 
     319             : 
     320             : GBT_VARKEY *
     321       13622 : gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
     322             :               const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
     323             : {
     324       13622 :     int         i = 0,
     325       13622 :                 numranges = entryvec->n;
     326             :     GBT_VARKEY *cur;
     327             :     Datum       out;
     328             :     GBT_VARKEY_R rk;
     329             : 
     330       13622 :     *size = sizeof(GBT_VARKEY);
     331             : 
     332       13622 :     cur = (GBT_VARKEY *) DatumGetPointer(entryvec->vector[0].key);
     333       13622 :     rk = gbt_var_key_readable(cur);
     334       13622 :     out = PointerGetDatum(gbt_var_key_copy(&rk));
     335             : 
     336       36752 :     for (i = 1; i < numranges; i++)
     337             :     {
     338       23130 :         cur = (GBT_VARKEY *) DatumGetPointer(entryvec->vector[i].key);
     339       23130 :         gbt_var_bin_union(&out, cur, collation, tinfo, flinfo);
     340             :     }
     341             : 
     342             : 
     343             :     /* Truncate (=compress) key */
     344       13622 :     if (tinfo->trnc)
     345             :     {
     346             :         int32       plen;
     347        3148 :         GBT_VARKEY *trc = NULL;
     348             : 
     349        3148 :         plen = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(out), tinfo);
     350        3148 :         trc = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(out), plen + 1, tinfo);
     351             : 
     352        3148 :         out = PointerGetDatum(trc);
     353             :     }
     354             : 
     355       13622 :     return ((GBT_VARKEY *) DatumGetPointer(out));
     356             : }
     357             : 
     358             : 
     359             : bool
     360       13520 : gbt_var_same(Datum d1, Datum d2, Oid collation,
     361             :              const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
     362             : {
     363       13520 :     GBT_VARKEY *t1 = (GBT_VARKEY *) DatumGetPointer(d1);
     364       13520 :     GBT_VARKEY *t2 = (GBT_VARKEY *) DatumGetPointer(d2);
     365             :     GBT_VARKEY_R r1,
     366             :                 r2;
     367             : 
     368       13520 :     r1 = gbt_var_key_readable(t1);
     369       13520 :     r2 = gbt_var_key_readable(t2);
     370             : 
     371       27002 :     return (tinfo->f_cmp(r1.lower, r2.lower, collation, flinfo) == 0 &&
     372       13482 :             tinfo->f_cmp(r1.upper, r2.upper, collation, flinfo) == 0);
     373             : }
     374             : 
     375             : 
     376             : float *
     377       28702 : gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
     378             :                 Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
     379             : {
     380       28702 :     GBT_VARKEY *orge = (GBT_VARKEY *) DatumGetPointer(o->key);
     381       28702 :     GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
     382             :     GBT_VARKEY_R ok,
     383             :                 nk;
     384             : 
     385       28702 :     *res = 0.0;
     386             : 
     387       28702 :     nk = gbt_var_key_readable(newe);
     388       28702 :     if (nk.lower == nk.upper)   /* leaf */
     389             :     {
     390             :         GBT_VARKEY *tmp;
     391             : 
     392       28702 :         tmp = gbt_var_leaf2node(newe, tinfo, flinfo);
     393       28702 :         if (tmp != newe)
     394        3134 :             nk = gbt_var_key_readable(tmp);
     395             :     }
     396       28702 :     ok = gbt_var_key_readable(orge);
     397             : 
     398       28702 :     if ((VARSIZE(ok.lower) - VARHDRSZ) == 0 && (VARSIZE(ok.upper) - VARHDRSZ) == 0)
     399        1570 :         *res = 0.0;
     400       54264 :     else if (!((tinfo->f_cmp(nk.lower, ok.lower, collation, flinfo) >= 0 ||
     401       15728 :                 gbt_bytea_pf_match(ok.lower, nk.lower, tinfo)) &&
     402       14856 :                (tinfo->f_cmp(nk.upper, ok.upper, collation, flinfo) <= 0 ||
     403        3452 :                 gbt_bytea_pf_match(ok.upper, nk.upper, tinfo))))
     404             :     {
     405       19170 :         Datum       d = PointerGetDatum(0);
     406             :         double      dres;
     407             :         int32       ol,
     408             :                     ul;
     409             : 
     410       19170 :         gbt_var_bin_union(&d, orge, collation, tinfo, flinfo);
     411       19170 :         ol = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
     412       19170 :         gbt_var_bin_union(&d, newe, collation, tinfo, flinfo);
     413       19170 :         ul = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
     414             : 
     415       19170 :         if (ul < ol)
     416             :         {
     417           0 :             dres = (ol - ul);   /* reduction of common prefix len */
     418             :         }
     419             :         else
     420             :         {
     421       19170 :             GBT_VARKEY_R uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(d));
     422             :             unsigned char tmp[4];
     423             : 
     424       19170 :             tmp[0] = (unsigned char) (((VARSIZE(ok.lower) - VARHDRSZ) <= ul) ? 0 : (VARDATA(ok.lower)[ul]));
     425       19170 :             tmp[1] = (unsigned char) (((VARSIZE(uk.lower) - VARHDRSZ) <= ul) ? 0 : (VARDATA(uk.lower)[ul]));
     426       19170 :             tmp[2] = (unsigned char) (((VARSIZE(ok.upper) - VARHDRSZ) <= ul) ? 0 : (VARDATA(ok.upper)[ul]));
     427       19170 :             tmp[3] = (unsigned char) (((VARSIZE(uk.upper) - VARHDRSZ) <= ul) ? 0 : (VARDATA(uk.upper)[ul]));
     428       19170 :             dres = abs(tmp[0] - tmp[1]) + abs(tmp[3] - tmp[2]);
     429       19170 :             dres /= 256.0;
     430             :         }
     431             : 
     432       19170 :         *res += FLT_MIN;
     433       19170 :         *res += (float) (dres / ((double) (ol + 1)));
     434       19170 :         *res *= (FLT_MAX / (o->rel->rd_att->natts + 1));
     435             :     }
     436             : 
     437       28702 :     return res;
     438             : }
     439             : 
     440             : 
     441             : static int
     442      102072 : gbt_vsrt_cmp(const void *a, const void *b, void *arg)
     443             : {
     444      102072 :     GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t);
     445      102072 :     GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t);
     446      102072 :     const gbt_vsrt_arg *varg = (const gbt_vsrt_arg *) arg;
     447             :     int         res;
     448             : 
     449      102072 :     res = varg->tinfo->f_cmp(ar.lower, br.lower, varg->collation, varg->flinfo);
     450      102072 :     if (res == 0)
     451       10492 :         return varg->tinfo->f_cmp(ar.upper, br.upper, varg->collation, varg->flinfo);
     452             : 
     453       91580 :     return res;
     454             : }
     455             : 
     456             : GIST_SPLITVEC *
     457         110 : gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
     458             :                   Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
     459             : {
     460             :     OffsetNumber i,
     461         110 :                 maxoff = entryvec->n - 1;
     462             :     Vsrt       *arr;
     463         110 :     int         svcntr = 0,
     464             :                 nbytes;
     465             :     char       *cur;
     466         110 :     GBT_VARKEY **sv = NULL;
     467             :     gbt_vsrt_arg varg;
     468             : 
     469         110 :     arr = (Vsrt *) palloc((maxoff + 1) * sizeof(Vsrt));
     470         110 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     471         110 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     472         110 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     473         110 :     v->spl_ldatum = PointerGetDatum(0);
     474         110 :     v->spl_rdatum = PointerGetDatum(0);
     475         110 :     v->spl_nleft = 0;
     476         110 :     v->spl_nright = 0;
     477             : 
     478         110 :     sv = palloc(sizeof(bytea *) * (maxoff + 1));
     479             : 
     480             :     /* Sort entries */
     481             : 
     482       21466 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     483             :     {
     484             :         GBT_VARKEY_R ro;
     485             : 
     486       21356 :         cur = (char *) DatumGetPointer(entryvec->vector[i].key);
     487       21356 :         ro = gbt_var_key_readable((GBT_VARKEY *) cur);
     488       21356 :         if (ro.lower == ro.upper)   /* leaf */
     489             :         {
     490       21356 :             sv[svcntr] = gbt_var_leaf2node((GBT_VARKEY *) cur, tinfo, flinfo);
     491       21356 :             arr[i].t = sv[svcntr];
     492       21356 :             if (sv[svcntr] != (GBT_VARKEY *) cur)
     493        2974 :                 svcntr++;
     494             :         }
     495             :         else
     496           0 :             arr[i].t = (GBT_VARKEY *) cur;
     497       21356 :         arr[i].i = i;
     498             :     }
     499             : 
     500             :     /* sort */
     501         110 :     varg.tinfo = tinfo;
     502         110 :     varg.collation = collation;
     503         110 :     varg.flinfo = flinfo;
     504         110 :     qsort_arg(&arr[FirstOffsetNumber],
     505             :               maxoff - FirstOffsetNumber + 1,
     506             :               sizeof(Vsrt),
     507             :               gbt_vsrt_cmp,
     508             :               &varg);
     509             : 
     510             :     /* We do simply create two parts */
     511             : 
     512       21466 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     513             :     {
     514       21356 :         if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
     515             :         {
     516       10660 :             gbt_var_bin_union(&v->spl_ldatum, arr[i].t, collation, tinfo, flinfo);
     517       10660 :             v->spl_left[v->spl_nleft] = arr[i].i;
     518       10660 :             v->spl_nleft++;
     519             :         }
     520             :         else
     521             :         {
     522       10696 :             gbt_var_bin_union(&v->spl_rdatum, arr[i].t, collation, tinfo, flinfo);
     523       10696 :             v->spl_right[v->spl_nright] = arr[i].i;
     524       10696 :             v->spl_nright++;
     525             :         }
     526             :     }
     527             : 
     528             :     /* Truncate (=compress) key */
     529         110 :     if (tinfo->trnc)
     530             :     {
     531          22 :         int32       ll = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(v->spl_ldatum), tinfo);
     532          22 :         int32       lr = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(v->spl_rdatum), tinfo);
     533             :         GBT_VARKEY *dl;
     534             :         GBT_VARKEY *dr;
     535             : 
     536          22 :         ll = Max(ll, lr);
     537          22 :         ll++;
     538             : 
     539          22 :         dl = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(v->spl_ldatum), ll, tinfo);
     540          22 :         dr = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(v->spl_rdatum), ll, tinfo);
     541          22 :         v->spl_ldatum = PointerGetDatum(dl);
     542          22 :         v->spl_rdatum = PointerGetDatum(dr);
     543             :     }
     544             : 
     545         110 :     return v;
     546             : }
     547             : 
     548             : 
     549             : /*
     550             :  * The GiST consistent method
     551             :  */
     552             : bool
     553       56932 : gbt_var_consistent(GBT_VARKEY_R *key,
     554             :                    const void *query,
     555             :                    StrategyNumber strategy,
     556             :                    Oid collation,
     557             :                    bool is_leaf,
     558             :                    const gbtree_vinfo *tinfo,
     559             :                    FmgrInfo *flinfo)
     560             : {
     561       56932 :     bool        retval = false;
     562             : 
     563       56932 :     switch (strategy)
     564             :     {
     565       13636 :         case BTLessEqualStrategyNumber:
     566       13636 :             if (is_leaf)
     567       13496 :                 retval = tinfo->f_ge(query, key->lower, collation, flinfo);
     568             :             else
     569         280 :                 retval = tinfo->f_cmp(query, key->lower, collation, flinfo) >= 0
     570         140 :                     || gbt_var_node_pf_match(key, query, tinfo);
     571       13636 :             break;
     572       12704 :         case BTLessStrategyNumber:
     573       12704 :             if (is_leaf)
     574       12590 :                 retval = tinfo->f_gt(query, key->lower, collation, flinfo);
     575             :             else
     576         228 :                 retval = tinfo->f_cmp(query, key->lower, collation, flinfo) >= 0
     577         114 :                     || gbt_var_node_pf_match(key, query, tinfo);
     578       12704 :             break;
     579        7168 :         case BTEqualStrategyNumber:
     580        7168 :             if (is_leaf)
     581        7030 :                 retval = tinfo->f_eq(query, key->lower, collation, flinfo);
     582             :             else
     583         138 :                 retval =
     584         232 :                     (tinfo->f_cmp(key->lower, query, collation, flinfo) <= 0 &&
     585         276 :                      tinfo->f_cmp(query, key->upper, collation, flinfo) <= 0) ||
     586         104 :                     gbt_var_node_pf_match(key, query, tinfo);
     587        7168 :             break;
     588       11458 :         case BTGreaterStrategyNumber:
     589       11458 :             if (is_leaf)
     590       11332 :                 retval = tinfo->f_lt(query, key->upper, collation, flinfo);
     591             :             else
     592         252 :                 retval = tinfo->f_cmp(query, key->upper, collation, flinfo) <= 0
     593         126 :                     || gbt_var_node_pf_match(key, query, tinfo);
     594       11458 :             break;
     595       11944 :         case BTGreaterEqualStrategyNumber:
     596       11944 :             if (is_leaf)
     597       11784 :                 retval = tinfo->f_le(query, key->upper, collation, flinfo);
     598             :             else
     599         320 :                 retval = tinfo->f_cmp(query, key->upper, collation, flinfo) <= 0
     600         160 :                     || gbt_var_node_pf_match(key, query, tinfo);
     601       11944 :             break;
     602          22 :         case BtreeGistNotEqualStrategyNumber:
     603          34 :             retval = !(tinfo->f_eq(query, key->lower, collation, flinfo) &&
     604          12 :                        tinfo->f_eq(query, key->upper, collation, flinfo));
     605          22 :             break;
     606           0 :         default:
     607           0 :             retval = false;
     608             :     }
     609             : 
     610       56932 :     return retval;
     611             : }

Generated by: LCOV version 1.14