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

Generated by: LCOV version 1.13