LCOV - differential code coverage report
Current view: top level - contrib/btree_gist - btree_utils_var.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: 77aeca80249c9e640c811e80633a2e334a9320de vs 38afc3dcb25c45b744d4025029ce0a6c90b7059f Lines: 84.4 % 262 221 1 40 19 202 8 37
Current Date: 2026-07-25 19:08:27 +0900 Functions: 95.0 % 20 19 1 8 11 1
Baseline: lcov-20260725-baseline Branches: 70.6 % 119 84 3 32 17 67
Baseline Date: 2026-07-25 19:09:19 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 95.5 % 22 21 1 19 2
(30,360] days: 100.0 % 7 7 7
(360..) days: 82.8 % 233 193 40 193
Function coverage date bins:
(7,30] days: 100.0 % 1 1 1
(30,360] days: 100.0 % 1 1 1
(360..) days: 94.4 % 18 17 1 7 10
Branch coverage date bins:
(7,30] days: 84.6 % 26 22 3 1 17 5
(360..) days: 66.7 % 93 62 31 62

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * contrib/btree_gist/btree_utils_var.c
                                  3                 :                :  *
                                  4                 :                :  * Common routines for btree_gist code working with varlena indexed data types.
                                  5                 :                :  */
                                  6                 :                : #include "postgres.h"
                                  7                 :                : 
                                  8                 :                : #include <limits.h>
                                  9                 :                : #include <float.h>
                                 10                 :                : 
                                 11                 :                : #include "btree_gist.h"
                                 12                 :                : #include "btree_utils_var.h"
                                 13                 :                : #include "utils/rel.h"
                                 14                 :                : #include "varatt.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                 :                : 
 7816 teodor@sigaev.ru           31                 :CBC          11 : PG_FUNCTION_INFO_V1(gbt_var_decompress);
 4138 heikki.linnakangas@i       32                 :             11 : PG_FUNCTION_INFO_V1(gbt_var_fetch);
                                 33                 :                : 
                                 34                 :                : 
                                 35                 :                : Datum
 7816 teodor@sigaev.ru           36                 :          63243 : gbt_var_decompress(PG_FUNCTION_ARGS)
                                 37                 :                : {
 7735 neilc@samurai.com          38                 :          63243 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 3232 tgl@sss.pgh.pa.us          39                 :          63243 :     GBT_VARKEY *key = (GBT_VARKEY *) PG_DETOAST_DATUM(entry->key);
                                 40                 :                : 
                                 41                 :                :     /* We only need a new GISTENTRY if detoasting did something */
 7735 neilc@samurai.com          42         [ +  + ]:          63243 :     if (key != (GBT_VARKEY *) DatumGetPointer(entry->key))
                                 43                 :                :     {
  232 michael@paquier.xyz        44                 :          63213 :         GISTENTRY  *retval = palloc_object(GISTENTRY);
                                 45                 :                : 
 7735 neilc@samurai.com          46                 :          63213 :         gistentryinit(*retval, PointerGetDatum(key),
                                 47                 :                :                       entry->rel, entry->page,
                                 48                 :                :                       entry->offset, false);
                                 49                 :                : 
                                 50                 :          63213 :         PG_RETURN_POINTER(retval);
                                 51                 :                :     }
                                 52                 :                : 
                                 53                 :             30 :     PG_RETURN_POINTER(entry);
                                 54                 :                : }
                                 55                 :                : 
                                 56                 :                : /*
                                 57                 :                :  * Extract a "readable" representation of a GBT_VARKEY, containing direct
                                 58                 :                :  * pointers to the contained lower and upper datums.
                                 59                 :                :  */
                                 60                 :                : GBT_VARKEY_R
 6253 bruce@momjian.us           61                 :         309893 : gbt_var_key_readable(const GBT_VARKEY *k)
                                 62                 :                : {
                                 63                 :                :     GBT_VARKEY_R r;
                                 64                 :                : 
 8000                            65                 :         309893 :     r.lower = (bytea *) &(((char *) k)[VARHDRSZ]);
                                 66         [ +  + ]:         309893 :     if (VARSIZE(k) > (VARHDRSZ + (VARSIZE(r.lower))))
                                 67                 :          55900 :         r.upper = (bytea *) &(((char *) k)[VARHDRSZ + INTALIGN(VARSIZE(r.lower))]);
                                 68                 :                :     else
                                 69                 :         253993 :         r.upper = r.lower;
                                 70                 :         309893 :     return r;
                                 71                 :                : }
                                 72                 :                : 
                                 73                 :                : 
                                 74                 :                : /*
                                 75                 :                :  * Create a leaf-entry to store in the index, from a single Datum.
                                 76                 :                :  */
                                 77                 :                : static GBT_VARKEY *
  164 michael@paquier.xyz        78                 :           8265 : gbt_var_key_from_datum(const varlena *u)
                                 79                 :                : {
 4139 heikki.linnakangas@i       80                 :           8265 :     int32       lowersize = VARSIZE(u);
                                 81                 :                :     GBT_VARKEY *r;
                                 82                 :                : 
                                 83                 :           8265 :     r = (GBT_VARKEY *) palloc(lowersize + VARHDRSZ);
                                 84                 :           8265 :     memcpy(VARDATA(r), u, lowersize);
                                 85                 :           8265 :     SET_VARSIZE(r, lowersize + VARHDRSZ);
                                 86                 :                : 
                                 87                 :           8265 :     return r;
                                 88                 :                : }
                                 89                 :                : 
                                 90                 :                : /*
                                 91                 :                :  * Create a key entry to store in the index, from lower and upper bound.
                                 92                 :                :  *
                                 93                 :                :  * This code assumes that none of the types we work with require more
                                 94                 :                :  * than INTALIGN alignment.
                                 95                 :                :  */
                                 96                 :                : GBT_VARKEY *
                                 97                 :          22313 : gbt_var_key_copy(const GBT_VARKEY_R *u)
                                 98                 :                : {
 4453 tgl@sss.pgh.pa.us          99                 :          22313 :     int32       lowersize = VARSIZE(u->lower);
                                100                 :          22313 :     int32       uppersize = VARSIZE(u->upper);
                                101                 :                :     GBT_VARKEY *r;
                                102                 :                : 
 4139 heikki.linnakangas@i      103                 :          22313 :     r = (GBT_VARKEY *) palloc0(INTALIGN(lowersize) + uppersize + VARHDRSZ);
                                104                 :          22313 :     memcpy(VARDATA(r), u->lower, lowersize);
                                105                 :          22313 :     memcpy(VARDATA(r) + INTALIGN(lowersize), u->upper, uppersize);
                                106                 :          22313 :     SET_VARSIZE(r, INTALIGN(lowersize) + uppersize + VARHDRSZ);
                                107                 :                : 
 8000 bruce@momjian.us          108                 :          22313 :     return r;
                                109                 :                : }
                                110                 :                : 
                                111                 :                : /*
                                112                 :                :  * Convert a GBT_VARKEY in leaf form to a GBT_VARKEY in internal form.
                                113                 :                :  * No-op if the data type doesn't require a transformation.
                                114                 :                :  */
                                115                 :                : static GBT_VARKEY *
 3413 andrew@dunslane.net       116                 :          46980 : gbt_var_leaf2node(GBT_VARKEY *leaf, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
                                117                 :                : {
 8000 bruce@momjian.us          118         [ +  + ]:          46980 :     if (tinfo->f_l2n)
   22 tgl@sss.pgh.pa.us         119                 :GNC        3598 :         return tinfo->f_l2n(leaf, flinfo);
                                120                 :                :     else
                                121                 :          43382 :         return leaf;
                                122                 :                : }
                                123                 :                : 
                                124                 :                : 
                                125                 :                : /*
                                126                 :                :  * returns the common prefix length of a node key
                                127                 :                :  *
                                128                 :                :  * This is not used for any cases where the underlying type is character data
                                129                 :                :  * (except in gbt_var_penalty, where it doesn't matter since we're just making
                                130                 :                :  * an estimated correction not constructing a truncated string).  If it were,
                                131                 :                :  * we'd need to be careful not to truncate in the middle of a multibyte
                                132                 :                :  * character.
                                133                 :                :  */
                                134                 :                : static int32
 6253 bruce@momjian.us          135                 :CBC          25 : gbt_var_node_cp_len(const GBT_VARKEY *node, const gbtree_vinfo *tinfo)
                                136                 :                : {
 7588                           137                 :             25 :     GBT_VARKEY_R r = gbt_var_key_readable(node);
                                138                 :             25 :     int32       i = 0;
                                139                 :             25 :     int32       t1len = VARSIZE(r.lower) - VARHDRSZ;
                                140                 :             25 :     int32       t2len = VARSIZE(r.upper) - VARHDRSZ;
                                141                 :             25 :     int32       ml = Min(t1len, t2len);
                                142                 :             25 :     char       *p1 = VARDATA(r.lower);
                                143                 :             25 :     char       *p2 = VARDATA(r.upper);
                                144                 :                : 
                                145         [ +  + ]:             25 :     if (ml == 0)
                                146                 :              4 :         return 0;
                                147                 :                : 
                                148         [ +  - ]:             21 :     while (i < ml)
                                149                 :                :     {
                                150         [ +  - ]:             21 :         if (*p1 != *p2)
   22 tgl@sss.pgh.pa.us         151                 :GNC          21 :             return i;
 7588 bruce@momjian.us          152                 :UBC           0 :         p1++;
                                153                 :              0 :         p2++;
                                154                 :              0 :         i++;
                                155                 :                :     }
 3232 tgl@sss.pgh.pa.us         156                 :              0 :     return ml;                  /* lower == upper */
                                157                 :                : }
                                158                 :                : 
                                159                 :                : 
                                160                 :                : /*
                                161                 :                :  * returns true if query matches prefix up to the length of the prefix
                                162                 :                :  *
                                163                 :                :  * We need this to avoid edge-case problems when the "prefix" is a truncated
                                164                 :                :  * datum; see discussion in btree_utils_var.h.
                                165                 :                :  */
                                166                 :                : static bool
 6253 bruce@momjian.us          167                 :CBC          26 : gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo *tinfo)
                                168                 :                : {
 3265 peter_e@gmx.net           169                 :             26 :     bool        out = false;
 7588 bruce@momjian.us          170                 :             26 :     int32       qlen = VARSIZE(query) - VARHDRSZ;
                                171                 :             26 :     int32       nlen = VARSIZE(pf) - VARHDRSZ;
                                172                 :                : 
 8000                           173         [ +  - ]:             26 :     if (nlen <= qlen)
                                174                 :                :     {
 7588                           175                 :             26 :         char       *q = VARDATA(query);
                                176                 :             26 :         char       *n = VARDATA(pf);
                                177                 :                : 
 5573 tgl@sss.pgh.pa.us         178                 :             26 :         out = (memcmp(q, n, nlen) == 0);
                                179                 :                :     }
                                180                 :                : 
 8000 bruce@momjian.us          181                 :             26 :     return out;
                                182                 :                : }
                                183                 :                : 
                                184                 :                : 
                                185                 :                : /*
                                186                 :                :  * returns true if query matches node according to common-prefix rule
                                187                 :                :  *
                                188                 :                :  * If the data type is truncatable, then a shortened upper bound must be
                                189                 :                :  * considered to include all values that match it up to its own length,
                                190                 :                :  * even though longer values would normally be considered larger.
                                191                 :                :  * We don't need to check the lower bound though: shortening it just
                                192                 :                :  * makes it even smaller.
                                193                 :                :  */
                                194                 :                : static bool
 6253                           195                 :             86 : gbt_var_node_pf_match(const GBT_VARKEY_R *node, const bytea *query, const gbtree_vinfo *tinfo)
                                196                 :                : {
 2368 alvherre@alvh.no-ip.      197   [ +  +  +  + ]:            112 :     return (tinfo->trnc &&
   22 tgl@sss.pgh.pa.us         198                 :GNC          26 :             gbt_bytea_pf_match(node->upper, query, tinfo));
                                199                 :                : }
                                200                 :                : 
                                201                 :                : 
                                202                 :                : /*
                                203                 :                :  * truncates / compresses the node key
                                204                 :                :  *
                                205                 :                :  * cpf_length is the common prefix length of the lower and upper values.
                                206                 :                :  * We truncate to that plus one byte, so that the node represents a range
                                207                 :                :  * of leaf values but doesn't have undue specificity.
                                208                 :                :  */
                                209                 :                : static GBT_VARKEY *
 6253 bruce@momjian.us          210                 :CBC          25 : gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vinfo *tinfo)
                                211                 :                : {
                                212                 :                :     GBT_VARKEY *out;
 8000                           213                 :             25 :     GBT_VARKEY_R r = gbt_var_key_readable(node);
 7588                           214                 :             25 :     int32       len1 = VARSIZE(r.lower) - VARHDRSZ;
                                215                 :             25 :     int32       len2 = VARSIZE(r.upper) - VARHDRSZ;
                                216                 :                :     int32       si;
                                217                 :                :     char       *out2;
                                218                 :                : 
                                219                 :             25 :     len1 = Min(len1, (cpf_length + 1));
                                220                 :             25 :     len2 = Min(len2, (cpf_length + 1));
                                221                 :                : 
 7088 tgl@sss.pgh.pa.us         222                 :             25 :     si = 2 * VARHDRSZ + INTALIGN(len1 + VARHDRSZ) + len2;
 4453                           223                 :             25 :     out = (GBT_VARKEY *) palloc0(si);
 7088                           224                 :             25 :     SET_VARSIZE(out, si);
                                225                 :                : 
                                226                 :             25 :     memcpy(VARDATA(out), r.lower, len1 + VARHDRSZ);
                                227                 :             25 :     SET_VARSIZE(VARDATA(out), len1 + VARHDRSZ);
                                228                 :                : 
                                229                 :             25 :     out2 = VARDATA(out) + INTALIGN(len1 + VARHDRSZ);
                                230                 :             25 :     memcpy(out2, r.upper, len2 + VARHDRSZ);
                                231                 :             25 :     SET_VARSIZE(out2, len2 + VARHDRSZ);
                                232                 :                : 
 8000 bruce@momjian.us          233                 :             25 :     return out;
                                234                 :                : }
                                235                 :                : 
                                236                 :                : 
                                237                 :                : 
                                238                 :                : void
 5573 tgl@sss.pgh.pa.us         239                 :          31362 : gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
                                240                 :                :                   const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
                                241                 :                : {
 8000 bruce@momjian.us          242                 :          31362 :     GBT_VARKEY_R eo = gbt_var_key_readable(e);
                                243                 :                :     GBT_VARKEY_R nr;
                                244                 :                : 
   22 tgl@sss.pgh.pa.us         245         [ +  + ]:GNC       31362 :     if (eo.lower == eo.upper)   /* if leaf, convert to internal form */
                                246                 :                :     {
                                247                 :                :         GBT_VARKEY *tmp;
                                248                 :                : 
 3413 andrew@dunslane.net       249                 :CBC       28956 :         tmp = gbt_var_leaf2node(e, tinfo, flinfo);
 8000 bruce@momjian.us          250         [ +  + ]:          28956 :         if (tmp != e)
                                251                 :           1198 :             eo = gbt_var_key_readable(tmp);
                                252                 :                :     }
                                253                 :                : 
                                254         [ +  + ]:          31362 :     if (DatumGetPointer(*u))
                                255                 :                :     {
                                256                 :          31260 :         GBT_VARKEY_R ro = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(*u));
 4916 tgl@sss.pgh.pa.us         257                 :          31260 :         bool        update = false;
                                258                 :                : 
                                259                 :          31260 :         nr.lower = ro.lower;
                                260                 :          31260 :         nr.upper = ro.upper;
                                261                 :                : 
 3243 peter_e@gmx.net           262         [ +  + ]:          31260 :         if (tinfo->f_cmp(ro.lower, eo.lower, collation, flinfo) > 0)
                                263                 :                :         {
 8000 bruce@momjian.us          264                 :             16 :             nr.lower = eo.lower;
 4916 tgl@sss.pgh.pa.us         265                 :             16 :             update = true;
                                266                 :                :         }
                                267                 :                : 
 3243 peter_e@gmx.net           268         [ +  + ]:          31260 :         if (tinfo->f_cmp(ro.upper, eo.upper, collation, flinfo) < 0)
                                269                 :                :         {
 8000 bruce@momjian.us          270                 :          13258 :             nr.upper = eo.upper;
 4916 tgl@sss.pgh.pa.us         271                 :          13258 :             update = true;
                                272                 :                :         }
                                273                 :                : 
                                274         [ +  + ]:          31260 :         if (update)
 4139 heikki.linnakangas@i      275                 :          13274 :             *u = PointerGetDatum(gbt_var_key_copy(&nr));
                                276                 :                :     }
                                277                 :                :     else
                                278                 :                :     {
 8000 bruce@momjian.us          279                 :            102 :         nr.lower = eo.lower;
                                280                 :            102 :         nr.upper = eo.upper;
 4139 heikki.linnakangas@i      281                 :            102 :         *u = PointerGetDatum(gbt_var_key_copy(&nr));
                                282                 :                :     }
 8093 teodor@sigaev.ru          283                 :          31362 : }
                                284                 :                : 
                                285                 :                : 
                                286                 :                : GISTENTRY *
 6253 bruce@momjian.us          287                 :           8346 : gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo)
                                288                 :                : {
                                289                 :                :     GISTENTRY  *retval;
                                290                 :                : 
 8000                           291         [ +  + ]:           8346 :     if (entry->leafkey)
                                292                 :                :     {
  164 michael@paquier.xyz       293                 :           8265 :         varlena    *leaf = PG_DETOAST_DATUM(entry->key);
                                294                 :                :         GBT_VARKEY *r;
                                295                 :                : 
 4139 heikki.linnakangas@i      296                 :           8265 :         r = gbt_var_key_from_datum(leaf);
                                297                 :                : 
  232 michael@paquier.xyz       298                 :           8265 :         retval = palloc_object(GISTENTRY);
 8000 bruce@momjian.us          299                 :           8265 :         gistentryinit(*retval, PointerGetDatum(r),
                                300                 :                :                       entry->rel, entry->page,
                                301                 :                :                       entry->offset, true);
                                302                 :                :     }
                                303                 :                :     else
                                304                 :             81 :         retval = entry;
                                305                 :                : 
 3264 peter_e@gmx.net           306                 :           8346 :     return retval;
                                307                 :                : }
                                308                 :                : 
                                309                 :                : 
                                310                 :                : Datum
 4138 heikki.linnakangas@i      311                 :          14982 : gbt_var_fetch(PG_FUNCTION_ARGS)
                                312                 :                : {
                                313                 :          14982 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 3232 tgl@sss.pgh.pa.us         314                 :          14982 :     GBT_VARKEY *key = (GBT_VARKEY *) PG_DETOAST_DATUM(entry->key);
 4138 heikki.linnakangas@i      315                 :          14982 :     GBT_VARKEY_R r = gbt_var_key_readable(key);
                                316                 :                :     GISTENTRY  *retval;
                                317                 :                : 
  232 michael@paquier.xyz       318                 :          14982 :     retval = palloc_object(GISTENTRY);
 4138 heikki.linnakangas@i      319                 :          14982 :     gistentryinit(*retval, PointerGetDatum(r.lower),
                                320                 :                :                   entry->rel, entry->page,
                                321                 :                :                   entry->offset, true);
                                322                 :                : 
                                323                 :          14982 :     PG_RETURN_POINTER(retval);
                                324                 :                : }
                                325                 :                : 
                                326                 :                : 
                                327                 :                : GBT_VARKEY *
 5573 tgl@sss.pgh.pa.us         328                 :           1865 : gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
                                329                 :                :               const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
                                330                 :                : {
 8000 bruce@momjian.us          331                 :           1865 :     int         i = 0,
                                332                 :           1865 :                 numranges = entryvec->n;
                                333                 :                :     GBT_VARKEY *cur;
                                334                 :                :     Datum       out;
                                335                 :                :     GBT_VARKEY_R rk;
                                336                 :                : 
                                337                 :           1865 :     *size = sizeof(GBT_VARKEY);
                                338                 :                : 
 7816 teodor@sigaev.ru          339                 :           1865 :     cur = (GBT_VARKEY *) DatumGetPointer(entryvec->vector[0].key);
 8000 bruce@momjian.us          340                 :           1865 :     rk = gbt_var_key_readable(cur);
 4139 heikki.linnakangas@i      341                 :           1865 :     out = PointerGetDatum(gbt_var_key_copy(&rk));
                                342                 :                : 
 8000 bruce@momjian.us          343         [ +  + ]:          11729 :     for (i = 1; i < numranges; i++)
                                344                 :                :     {
 7816 teodor@sigaev.ru          345                 :           9864 :         cur = (GBT_VARKEY *) DatumGetPointer(entryvec->vector[i].key);
 3413 andrew@dunslane.net       346                 :           9864 :         gbt_var_bin_union(&out, cur, collation, tinfo, flinfo);
                                347                 :                :     }
                                348                 :                : 
                                349                 :                : 
                                350                 :                :     /* Truncate (=compress) key */
 8000 bruce@momjian.us          351         [ +  + ]:           1865 :     if (tinfo->trnc)
                                352                 :                :     {
                                353                 :                :         int32       plen;
                                354                 :                :         GBT_VARKEY *trc;
                                355                 :                : 
                                356                 :              3 :         plen = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(out), tinfo);
                                357                 :              3 :         trc = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(out), plen + 1, tinfo);
                                358                 :                : 
                                359                 :              3 :         out = PointerGetDatum(trc);
                                360                 :                :     }
                                361                 :                : 
                                362                 :           1865 :     return ((GBT_VARKEY *) DatumGetPointer(out));
                                363                 :                : }
                                364                 :                : 
                                365                 :                : 
                                366                 :                : bool
 5573 tgl@sss.pgh.pa.us         367                 :           1814 : gbt_var_same(Datum d1, Datum d2, Oid collation,
                                368                 :                :              const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
                                369                 :                : {
 7816 teodor@sigaev.ru          370                 :           1814 :     GBT_VARKEY *t1 = (GBT_VARKEY *) DatumGetPointer(d1);
                                371                 :           1814 :     GBT_VARKEY *t2 = (GBT_VARKEY *) DatumGetPointer(d2);
                                372                 :                :     GBT_VARKEY_R r1,
                                373                 :                :                 r2;
                                374                 :                : 
 8000 bruce@momjian.us          375                 :           1814 :     r1 = gbt_var_key_readable(t1);
                                376                 :           1814 :     r2 = gbt_var_key_readable(t2);
                                377                 :                : 
 3243 peter_e@gmx.net           378   [ +  -  +  - ]:           3628 :     return (tinfo->f_cmp(r1.lower, r2.lower, collation, flinfo) == 0 &&
                                379                 :           1814 :             tinfo->f_cmp(r1.upper, r2.upper, collation, flinfo) == 0);
                                380                 :                : }
                                381                 :                : 
                                382                 :                : 
                                383                 :                : float *
 5573 tgl@sss.pgh.pa.us         384                 :UBC           0 : gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
                                385                 :                :                 Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
                                386                 :                : {
 7816 teodor@sigaev.ru          387                 :              0 :     GBT_VARKEY *orge = (GBT_VARKEY *) DatumGetPointer(o->key);
                                388                 :              0 :     GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
                                389                 :                :     GBT_VARKEY_R ok,
                                390                 :                :                 nk;
                                391                 :                : 
 8000 bruce@momjian.us          392                 :              0 :     *res = 0.0;
                                393                 :                : 
                                394                 :              0 :     nk = gbt_var_key_readable(newe);
   22 tgl@sss.pgh.pa.us         395         [ #  # ]:UNC           0 :     if (nk.lower == nk.upper)   /* if leaf, convert to internal form */
                                396                 :                :     {
                                397                 :                :         GBT_VARKEY *tmp;
                                398                 :                : 
 3413 andrew@dunslane.net       399                 :UBC           0 :         tmp = gbt_var_leaf2node(newe, tinfo, flinfo);
 8000 bruce@momjian.us          400         [ #  # ]:              0 :         if (tmp != newe)
                                401                 :              0 :             nk = gbt_var_key_readable(tmp);
                                402                 :                :     }
                                403                 :              0 :     ok = gbt_var_key_readable(orge);
                                404                 :                : 
 7694 teodor@sigaev.ru          405   [ #  #  #  # ]:              0 :     if ((VARSIZE(ok.lower) - VARHDRSZ) == 0 && (VARSIZE(ok.upper) - VARHDRSZ) == 0)
 8000 bruce@momjian.us          406                 :              0 :         *res = 0.0;
 3243 peter_e@gmx.net           407   [ #  #  #  #  :              0 :     else if (!((tinfo->f_cmp(nk.lower, ok.lower, collation, flinfo) >= 0 ||
                                              #  # ]
 5573 tgl@sss.pgh.pa.us         408                 :              0 :                 gbt_bytea_pf_match(ok.lower, nk.lower, tinfo)) &&
 3243 peter_e@gmx.net           409         [ #  # ]:              0 :                (tinfo->f_cmp(nk.upper, ok.upper, collation, flinfo) <= 0 ||
 3321 tgl@sss.pgh.pa.us         410                 :              0 :                 gbt_bytea_pf_match(ok.upper, nk.upper, tinfo))))
                                411                 :                :     {
 8000 bruce@momjian.us          412                 :              0 :         Datum       d = PointerGetDatum(0);
                                413                 :                :         double      dres;
                                414                 :                :         int32       ol,
                                415                 :                :                     ul;
                                416                 :                : 
 3413 andrew@dunslane.net       417                 :              0 :         gbt_var_bin_union(&d, orge, collation, tinfo, flinfo);
 8000 bruce@momjian.us          418                 :              0 :         ol = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
 3413 andrew@dunslane.net       419                 :              0 :         gbt_var_bin_union(&d, newe, collation, tinfo, flinfo);
 8000 bruce@momjian.us          420                 :              0 :         ul = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
                                421                 :                : 
                                422         [ #  # ]:              0 :         if (ul < ol)
                                423                 :                :         {
 4916 tgl@sss.pgh.pa.us         424                 :              0 :             dres = (ol - ul);   /* reduction of common prefix len */
                                425                 :                :         }
                                426                 :                :         else
                                427                 :                :         {
 8000 bruce@momjian.us          428                 :              0 :             GBT_VARKEY_R uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(d));
                                429                 :                :             unsigned char tmp[4];
                                430                 :                : 
 4916 tgl@sss.pgh.pa.us         431         [ #  # ]:              0 :             tmp[0] = (unsigned char) (((VARSIZE(ok.lower) - VARHDRSZ) <= ul) ? 0 : (VARDATA(ok.lower)[ul]));
                                432         [ #  # ]:              0 :             tmp[1] = (unsigned char) (((VARSIZE(uk.lower) - VARHDRSZ) <= ul) ? 0 : (VARDATA(uk.lower)[ul]));
                                433         [ #  # ]:              0 :             tmp[2] = (unsigned char) (((VARSIZE(ok.upper) - VARHDRSZ) <= ul) ? 0 : (VARDATA(ok.upper)[ul]));
                                434         [ #  # ]:              0 :             tmp[3] = (unsigned char) (((VARSIZE(uk.upper) - VARHDRSZ) <= ul) ? 0 : (VARDATA(uk.upper)[ul]));
 1387 peter@eisentraut.org      435                 :              0 :             dres = abs(tmp[0] - tmp[1]) + abs(tmp[3] - tmp[2]);
 8000 bruce@momjian.us          436                 :              0 :             dres /= 256.0;
                                437                 :                :         }
                                438                 :                : 
                                439                 :              0 :         *res += FLT_MIN;
                                440                 :              0 :         *res += (float) (dres / ((double) (ol + 1)));
                                441                 :              0 :         *res *= (FLT_MAX / (o->rel->rd_att->natts + 1));
                                442                 :                :     }
                                443                 :                : 
                                444                 :              0 :     return res;
                                445                 :                : }
                                446                 :                : 
                                447                 :                : 
                                448                 :                : static int
 7233 tgl@sss.pgh.pa.us         449                 :CBC       17987 : gbt_vsrt_cmp(const void *a, const void *b, void *arg)
                                450                 :                : {
 8000 bruce@momjian.us          451                 :          17987 :     GBT_VARKEY_R ar = gbt_var_key_readable(((const Vsrt *) a)->t);
                                452                 :          17987 :     GBT_VARKEY_R br = gbt_var_key_readable(((const Vsrt *) b)->t);
 5573 tgl@sss.pgh.pa.us         453                 :          17987 :     const gbt_vsrt_arg *varg = (const gbt_vsrt_arg *) arg;
                                454                 :                :     int         res;
                                455                 :                : 
 3243 peter_e@gmx.net           456                 :          17987 :     res = varg->tinfo->f_cmp(ar.lower, br.lower, varg->collation, varg->flinfo);
 6079 teodor@sigaev.ru          457         [ +  + ]:          17987 :     if (res == 0)
 3243 peter_e@gmx.net           458                 :           7632 :         return varg->tinfo->f_cmp(ar.upper, br.upper, varg->collation, varg->flinfo);
                                459                 :                : 
 6079 teodor@sigaev.ru          460                 :          10355 :     return res;
                                461                 :                : }
                                462                 :                : 
                                463                 :                : GIST_SPLITVEC *
 5573 tgl@sss.pgh.pa.us         464                 :             51 : gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
                                465                 :                :                   Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
                                466                 :                : {
                                467                 :                :     OffsetNumber i,
 8000 bruce@momjian.us          468                 :             51 :                 maxoff = entryvec->n - 1;
                                469                 :                :     Vsrt       *arr;
 7816 teodor@sigaev.ru          470                 :             51 :     int         svcntr = 0,
                                471                 :                :                 nbytes;
                                472                 :                :     char       *cur;
 8000 bruce@momjian.us          473                 :             51 :     GBT_VARKEY **sv = NULL;
                                474                 :                :     gbt_vsrt_arg varg;
                                475                 :                : 
  219 michael@paquier.xyz       476                 :             51 :     arr = palloc_array(Vsrt, maxoff + 1);
 8000 bruce@momjian.us          477                 :             51 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
                                478                 :             51 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
                                479                 :             51 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
                                480                 :             51 :     v->spl_ldatum = PointerGetDatum(0);
                                481                 :             51 :     v->spl_rdatum = PointerGetDatum(0);
                                482                 :             51 :     v->spl_nleft = 0;
                                483                 :             51 :     v->spl_nright = 0;
                                484                 :                : 
  219 michael@paquier.xyz       485                 :             51 :     sv = palloc_array(GBT_VARKEY *, maxoff + 1);
                                486                 :                : 
                                487                 :                :     /* Sort entries */
                                488                 :                : 
 8000 bruce@momjian.us          489         [ +  + ]:          18075 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
                                490                 :                :     {
                                491                 :                :         GBT_VARKEY_R ro;
                                492                 :                : 
 7816 teodor@sigaev.ru          493                 :          18024 :         cur = (char *) DatumGetPointer(entryvec->vector[i].key);
 8000 bruce@momjian.us          494                 :          18024 :         ro = gbt_var_key_readable((GBT_VARKEY *) cur);
 3321 tgl@sss.pgh.pa.us         495         [ +  - ]:          18024 :         if (ro.lower == ro.upper)   /* leaf */
                                496                 :                :         {
 3413 andrew@dunslane.net       497                 :          18024 :             sv[svcntr] = gbt_var_leaf2node((GBT_VARKEY *) cur, tinfo, flinfo);
 8000 bruce@momjian.us          498                 :          18024 :             arr[i].t = sv[svcntr];
                                499         [ +  + ]:          18024 :             if (sv[svcntr] != (GBT_VARKEY *) cur)
                                500                 :           2400 :                 svcntr++;
                                501                 :                :         }
                                502                 :                :         else
 8000 bruce@momjian.us          503                 :UBC           0 :             arr[i].t = (GBT_VARKEY *) cur;
 8000 bruce@momjian.us          504                 :CBC       18024 :         arr[i].i = i;
                                505                 :                :     }
                                506                 :                : 
                                507                 :                :     /* sort */
 5573 tgl@sss.pgh.pa.us         508                 :             51 :     varg.tinfo = tinfo;
                                509                 :             51 :     varg.collation = collation;
 3413 andrew@dunslane.net       510                 :             51 :     varg.flinfo = flinfo;
 1264 peter@eisentraut.org      511                 :             51 :     qsort_arg(&arr[FirstOffsetNumber],
                                512                 :                :               maxoff - FirstOffsetNumber + 1,
                                513                 :                :               sizeof(Vsrt),
                                514                 :                :               gbt_vsrt_cmp,
                                515                 :                :               &varg);
                                516                 :                : 
                                517                 :                :     /* We do simply create two parts */
                                518                 :                : 
 8000 bruce@momjian.us          519         [ +  + ]:          18075 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
                                520                 :                :     {
                                521         [ +  + ]:          18024 :         if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
                                522                 :                :         {
 3413 andrew@dunslane.net       523                 :           9008 :             gbt_var_bin_union(&v->spl_ldatum, arr[i].t, collation, tinfo, flinfo);
 8000 bruce@momjian.us          524                 :           9008 :             v->spl_left[v->spl_nleft] = arr[i].i;
                                525                 :           9008 :             v->spl_nleft++;
                                526                 :                :         }
                                527                 :                :         else
                                528                 :                :         {
 3413 andrew@dunslane.net       529                 :           9016 :             gbt_var_bin_union(&v->spl_rdatum, arr[i].t, collation, tinfo, flinfo);
 8000 bruce@momjian.us          530                 :           9016 :             v->spl_right[v->spl_nright] = arr[i].i;
                                531                 :           9016 :             v->spl_nright++;
                                532                 :                :         }
                                533                 :                :     }
                                534                 :                : 
                                535                 :                :     /* Truncate (=compress) key */
                                536         [ +  + ]:             51 :     if (tinfo->trnc)
                                537                 :                :     {
                                538                 :             11 :         int32       ll = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(v->spl_ldatum), tinfo);
                                539                 :             11 :         int32       lr = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(v->spl_rdatum), tinfo);
                                540                 :                :         GBT_VARKEY *dl;
                                541                 :                :         GBT_VARKEY *dr;
                                542                 :                : 
                                543                 :             11 :         ll = Max(ll, lr);
                                544                 :             11 :         ll++;
                                545                 :                : 
                                546                 :             11 :         dl = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(v->spl_ldatum), ll, tinfo);
                                547                 :             11 :         dr = gbt_var_node_truncate((GBT_VARKEY *) DatumGetPointer(v->spl_rdatum), ll, tinfo);
                                548                 :             11 :         v->spl_ldatum = PointerGetDatum(dl);
                                549                 :             11 :         v->spl_rdatum = PointerGetDatum(dr);
                                550                 :                :     }
                                551                 :                : 
                                552                 :             51 :     return v;
                                553                 :                : }
                                554                 :                : 
                                555                 :                : 
                                556                 :                : /*
                                557                 :                :  * The GiST consistent method
                                558                 :                :  */
                                559                 :                : bool
   22 tgl@sss.pgh.pa.us         560                 :GNC       23680 : gbt_var_consistent(const GBT_VARKEY_R *key,
                                561                 :                :                    const void *query,
                                562                 :                :                    StrategyNumber strategy,
                                563                 :                :                    Oid collation,
                                564                 :                :                    bool is_leaf,
                                565                 :                :                    const gbtree_vinfo *tinfo,
                                566                 :                :                    FmgrInfo *flinfo)
                                567                 :                : {
                                568                 :                :     bool        retval;
                                569                 :                : 
                                570                 :                :     /*
                                571                 :                :      * On leaf pages we directly apply the check "key->lower OP query"; we
                                572                 :                :      * need not consider key->upper since it will be equal to key->lower.
                                573                 :                :      *
                                574                 :                :      * On internal pages we mostly need to check "is lower bound below query?"
                                575                 :                :      * and/or "is upper bound above query?", where we must allow equality in
                                576                 :                :      * both cases.  When checking against the upper bound we have to allow a
                                577                 :                :      * gbt_var_node_pf_match too.
                                578                 :                :      *
                                579                 :                :      * Remember that f_cmp is for internal pages, f_eq etc for leaf pages.
                                580                 :                :      */
                                581                 :                : #define lower_is_below_query() \
                                582                 :                :     (tinfo->f_cmp(key->lower, query, collation, flinfo) <= 0)
                                583                 :                : #define upper_is_above_query() \
                                584                 :                :     (tinfo->f_cmp(key->upper, query, collation, flinfo) >= 0 || \
                                585                 :                :      gbt_var_node_pf_match(key, query, tinfo))
                                586                 :                : 
 5573 tgl@sss.pgh.pa.us         587   [ +  +  +  +  :CBC       23680 :     switch (strategy)
                                           +  +  - ]
                                588                 :                :     {
 8000 bruce@momjian.us          589                 :           5708 :         case BTLessEqualStrategyNumber:
                                590         [ +  + ]:           5708 :             if (is_leaf)
   22 tgl@sss.pgh.pa.us         591                 :GNC        5639 :                 retval = tinfo->f_le(key->lower, query, collation, flinfo);
                                592                 :                :             else
                                593                 :             69 :                 retval = lower_is_below_query();
 8000 bruce@momjian.us          594                 :CBC        5708 :             break;
                                595                 :           5615 :         case BTLessStrategyNumber:
                                596         [ +  + ]:           5615 :             if (is_leaf)
   22 tgl@sss.pgh.pa.us         597                 :GNC        5560 :                 retval = tinfo->f_lt(key->lower, query, collation, flinfo);
                                598                 :                :             else
                                599                 :             55 :                 retval = lower_is_below_query();
 8000 bruce@momjian.us          600                 :CBC        5615 :             break;
                                601                 :           2197 :         case BTEqualStrategyNumber:
                                602         [ +  + ]:           2197 :             if (is_leaf)
   22 tgl@sss.pgh.pa.us         603                 :GNC        2130 :                 retval = tinfo->f_eq(key->lower, query, collation, flinfo);
                                604                 :                :             else
                                605   [ +  +  +  +  :             67 :                 retval = lower_is_below_query() && upper_is_above_query();
                                              +  + ]
 8000 bruce@momjian.us          606                 :CBC        2197 :             break;
                                607                 :           4978 :         case BTGreaterStrategyNumber:
                                608         [ +  + ]:           4978 :             if (is_leaf)
   22 tgl@sss.pgh.pa.us         609                 :GNC        4917 :                 retval = tinfo->f_gt(key->lower, query, collation, flinfo);
                                610                 :                :             else
                                611   [ +  +  +  + ]:             61 :                 retval = upper_is_above_query();
 8000 bruce@momjian.us          612                 :CBC        4978 :             break;
                                613                 :           5171 :         case BTGreaterEqualStrategyNumber:
                                614         [ +  + ]:           5171 :             if (is_leaf)
   22 tgl@sss.pgh.pa.us         615                 :GNC        5095 :                 retval = tinfo->f_ge(key->lower, query, collation, flinfo);
                                616                 :                :             else
                                617   [ +  +  +  + ]:             76 :                 retval = upper_is_above_query();
 8000 bruce@momjian.us          618                 :CBC        5171 :             break;
 5836 rhaas@postgresql.org      619                 :             11 :         case BtreeGistNotEqualStrategyNumber:
   22 tgl@sss.pgh.pa.us         620         [ +  + ]:             11 :             if (is_leaf)
   22 tgl@sss.pgh.pa.us         621                 :GNC           9 :                 retval = !(tinfo->f_eq(key->lower, query, collation, flinfo));
                                622                 :                :             else
                                623                 :                :             {
                                624                 :                :                 /*
                                625                 :                :                  * If the upper/lower bounds are equal and not truncated, then
                                626                 :                :                  * all entries below this node must have exactly that value.
                                627                 :                :                  * So we can avoid descending if the query equals both bounds.
                                628                 :                :                  * In all other cases, we must descend.
                                629                 :                :                  */
   22 tgl@sss.pgh.pa.us         630   [ +  -  +  + ]:CBC           5 :                 retval = tinfo->trnc ||
   22 tgl@sss.pgh.pa.us         631         [ +  - ]:GNC           3 :                     !(tinfo->f_cmp(key->lower, query, collation, flinfo) == 0 &&
                                632                 :              1 :                       tinfo->f_cmp(key->upper, query, collation, flinfo) == 0);
                                633                 :                :             }
 5836 rhaas@postgresql.org      634                 :CBC          11 :             break;
 8000 bruce@momjian.us          635                 :UBC           0 :         default:
 3265 peter_e@gmx.net           636                 :              0 :             retval = false;
                                637                 :                :     }
                                638                 :                : 
                                639                 :                : #undef lower_is_below_query
                                640                 :                : #undef upper_is_above_query
                                641                 :                : 
 5573 tgl@sss.pgh.pa.us         642                 :CBC       23680 :     return retval;
                                643                 :                : }
        

Generated by: LCOV version 2.0-1