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

          Line data    Source code
       1             : /*
       2             :  * contrib/btree_gist/btree_utils_num.c
       3             :  */
       4             : #include "postgres.h"
       5             : 
       6             : #include "btree_gist.h"
       7             : #include "btree_utils_num.h"
       8             : #include "utils/cash.h"
       9             : #include "utils/date.h"
      10             : #include "utils/timestamp.h"
      11             : 
      12             : 
      13             : GISTENTRY *
      14       20894 : gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
      15             : {
      16             :     GISTENTRY  *retval;
      17             : 
      18       20894 :     if (entry->leafkey)
      19             :     {
      20             :         union
      21             :         {
      22             :             bool        bo;
      23             :             int16       i2;
      24             :             int32       i4;
      25             :             int64       i8;
      26             :             float4      f4;
      27             :             float8      f8;
      28             :             DateADT     dt;
      29             :             TimeADT     tm;
      30             :             Timestamp   ts;
      31             :             Cash        ch;
      32             :         }           v;
      33             : 
      34       19374 :         GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
      35       19374 :         void       *leaf = NULL;
      36             : 
      37       19374 :         switch (tinfo->t)
      38             :         {
      39           4 :             case gbt_t_bool:
      40           4 :                 v.bo = DatumGetBool(entry->key);
      41           4 :                 leaf = &v.bo;
      42           4 :                 break;
      43        1092 :             case gbt_t_int2:
      44        1092 :                 v.i2 = DatumGetInt16(entry->key);
      45        1092 :                 leaf = &v.i2;
      46        1092 :                 break;
      47        1136 :             case gbt_t_int4:
      48        1136 :                 v.i4 = DatumGetInt32(entry->key);
      49        1136 :                 leaf = &v.i4;
      50        1136 :                 break;
      51        1094 :             case gbt_t_int8:
      52        1094 :                 v.i8 = DatumGetInt64(entry->key);
      53        1094 :                 leaf = &v.i8;
      54        1094 :                 break;
      55        3064 :             case gbt_t_oid:
      56             :             case gbt_t_enum:
      57        3064 :                 v.i4 = DatumGetObjectId(entry->key);
      58        3064 :                 leaf = &v.i4;
      59        3064 :                 break;
      60        1094 :             case gbt_t_float4:
      61        1094 :                 v.f4 = DatumGetFloat4(entry->key);
      62        1094 :                 leaf = &v.f4;
      63        1094 :                 break;
      64        1088 :             case gbt_t_float8:
      65        1088 :                 v.f8 = DatumGetFloat8(entry->key);
      66        1088 :                 leaf = &v.f8;
      67        1088 :                 break;
      68        1088 :             case gbt_t_date:
      69        1088 :                 v.dt = DatumGetDateADT(entry->key);
      70        1088 :                 leaf = &v.dt;
      71        1088 :                 break;
      72        1088 :             case gbt_t_time:
      73        1088 :                 v.tm = DatumGetTimeADT(entry->key);
      74        1088 :                 leaf = &v.tm;
      75        1088 :                 break;
      76        5140 :             case gbt_t_ts:
      77        5140 :                 v.ts = DatumGetTimestamp(entry->key);
      78        5140 :                 leaf = &v.ts;
      79        5140 :                 break;
      80        1086 :             case gbt_t_cash:
      81        1086 :                 v.ch = DatumGetCash(entry->key);
      82        1086 :                 leaf = &v.ch;
      83        1086 :                 break;
      84        2400 :             default:
      85        2400 :                 leaf = DatumGetPointer(entry->key);
      86             :         }
      87             : 
      88             :         Assert(tinfo->indexsize >= 2 * tinfo->size);
      89             : 
      90       19374 :         memcpy(&r[0], leaf, tinfo->size);
      91       19374 :         memcpy(&r[tinfo->size], leaf, tinfo->size);
      92       19374 :         retval = palloc(sizeof(GISTENTRY));
      93       19374 :         gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
      94             :                       entry->offset, false);
      95             :     }
      96             :     else
      97        1520 :         retval = entry;
      98             : 
      99       20894 :     return retval;
     100             : }
     101             : 
     102             : /*
     103             :  * Convert a compressed leaf item back to the original type, for index-only
     104             :  * scans.
     105             :  */
     106             : GISTENTRY *
     107        4426 : gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
     108             : {
     109             :     GISTENTRY  *retval;
     110             :     Datum       datum;
     111             : 
     112             :     Assert(tinfo->indexsize >= 2 * tinfo->size);
     113             : 
     114             :     /*
     115             :      * Get the original Datum from the stored datum. On leaf entries, the
     116             :      * lower and upper bound are the same. We just grab the lower bound and
     117             :      * return it.
     118             :      */
     119        4426 :     switch (tinfo->t)
     120             :     {
     121          14 :         case gbt_t_bool:
     122          14 :             datum = BoolGetDatum(*(bool *) entry->key);
     123          14 :             break;
     124         574 :         case gbt_t_int2:
     125         574 :             datum = Int16GetDatum(*(int16 *) entry->key);
     126         574 :             break;
     127         574 :         case gbt_t_int4:
     128         574 :             datum = Int32GetDatum(*(int32 *) entry->key);
     129         574 :             break;
     130         278 :         case gbt_t_int8:
     131         278 :             datum = Int64GetDatum(*(int64 *) entry->key);
     132         278 :             break;
     133           0 :         case gbt_t_oid:
     134             :         case gbt_t_enum:
     135           0 :             datum = ObjectIdGetDatum(*(Oid *) entry->key);
     136           0 :             break;
     137         530 :         case gbt_t_float4:
     138         530 :             datum = Float4GetDatum(*(float4 *) entry->key);
     139         530 :             break;
     140         270 :         case gbt_t_float8:
     141         270 :             datum = Float8GetDatum(*(float8 *) entry->key);
     142         270 :             break;
     143         562 :         case gbt_t_date:
     144         562 :             datum = DateADTGetDatum(*(DateADT *) entry->key);
     145         562 :             break;
     146         284 :         case gbt_t_time:
     147         284 :             datum = TimeADTGetDatum(*(TimeADT *) entry->key);
     148         284 :             break;
     149         734 :         case gbt_t_ts:
     150         734 :             datum = TimestampGetDatum(*(Timestamp *) entry->key);
     151         734 :             break;
     152         286 :         case gbt_t_cash:
     153         286 :             datum = CashGetDatum(*(Cash *) entry->key);
     154         286 :             break;
     155         320 :         default:
     156         320 :             datum = entry->key;
     157             :     }
     158             : 
     159        4426 :     retval = palloc(sizeof(GISTENTRY));
     160        4426 :     gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
     161             :                   false);
     162        4426 :     return retval;
     163             : }
     164             : 
     165             : 
     166             : 
     167             : /*
     168             : ** The GiST union method for numerical values
     169             : */
     170             : 
     171             : void *
     172       16824 : gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     173             : {
     174             :     int         i,
     175             :                 numranges;
     176             :     GBT_NUMKEY *cur;
     177             :     GBT_NUMKEY_R o,
     178             :                 c;
     179             : 
     180       16824 :     numranges = entryvec->n;
     181       16824 :     cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
     182             : 
     183             : 
     184       16824 :     o.lower = &((GBT_NUMKEY *) out)[0];
     185       16824 :     o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
     186             : 
     187       16824 :     memcpy(out, cur, 2 * tinfo->size);
     188             : 
     189       51380 :     for (i = 1; i < numranges; i++)
     190             :     {
     191       34556 :         cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
     192       34556 :         c.lower = &cur[0];
     193       34556 :         c.upper = &cur[tinfo->size];
     194             :         /* if out->lower > cur->lower, adopt cur as lower */
     195       34556 :         if (tinfo->f_gt(o.lower, c.lower, flinfo))
     196         266 :             memcpy(unconstify(GBT_NUMKEY *, o.lower), c.lower, tinfo->size);
     197             :         /* if out->upper < cur->upper, adopt cur as upper */
     198       34556 :         if (tinfo->f_lt(o.upper, c.upper, flinfo))
     199        2704 :             memcpy(unconstify(GBT_NUMKEY *, o.upper), c.upper, tinfo->size);
     200             :     }
     201             : 
     202       16824 :     return out;
     203             : }
     204             : 
     205             : 
     206             : 
     207             : /*
     208             : ** The GiST same method for numerical values
     209             : */
     210             : 
     211             : bool
     212       16738 : gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     213             : {
     214             :     GBT_NUMKEY_R b1,
     215             :                 b2;
     216             : 
     217       16738 :     b1.lower = &(a[0]);
     218       16738 :     b1.upper = &(a[tinfo->size]);
     219       16738 :     b2.lower = &(b[0]);
     220       16738 :     b2.upper = &(b[tinfo->size]);
     221             : 
     222       33416 :     return (tinfo->f_eq(b1.lower, b2.lower, flinfo) &&
     223       16678 :             tinfo->f_eq(b1.upper, b2.upper, flinfo));
     224             : }
     225             : 
     226             : 
     227             : void
     228       32098 : gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     229             : {
     230             :     GBT_NUMKEY_R rd;
     231             : 
     232       32098 :     rd.lower = &e[0];
     233       32098 :     rd.upper = &e[tinfo->size];
     234             : 
     235       32098 :     if (!DatumGetPointer(*u))
     236             :     {
     237         264 :         *u = PointerGetDatum(palloc0(tinfo->indexsize));
     238         264 :         memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), rd.lower, tinfo->size);
     239         264 :         memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), rd.upper, tinfo->size);
     240             :     }
     241             :     else
     242             :     {
     243             :         GBT_NUMKEY_R ur;
     244             : 
     245       31834 :         ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
     246       31834 :         ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
     247       31834 :         if (tinfo->f_gt(ur.lower, rd.lower, flinfo))
     248           0 :             memcpy(unconstify(GBT_NUMKEY *, ur.lower), rd.lower, tinfo->size);
     249       31834 :         if (tinfo->f_lt(ur.upper, rd.upper, flinfo))
     250       22132 :             memcpy(unconstify(GBT_NUMKEY *, ur.upper), rd.upper, tinfo->size);
     251             :     }
     252       32098 : }
     253             : 
     254             : 
     255             : 
     256             : /*
     257             :  * The GiST consistent method
     258             :  *
     259             :  * Note: we currently assume that no datatypes that use this routine are
     260             :  * collation-aware; so we don't bother passing collation through.
     261             :  */
     262             : bool
     263       82740 : gbt_num_consistent(const GBT_NUMKEY_R *key,
     264             :                    const void *query,
     265             :                    const StrategyNumber *strategy,
     266             :                    bool is_leaf,
     267             :                    const gbtree_ninfo *tinfo,
     268             :                    FmgrInfo *flinfo)
     269             : {
     270             :     bool        retval;
     271             : 
     272       82740 :     switch (*strategy)
     273             :     {
     274       15638 :         case BTLessEqualStrategyNumber:
     275       15638 :             retval = tinfo->f_ge(query, key->lower, flinfo);
     276       15638 :             break;
     277       16256 :         case BTLessStrategyNumber:
     278       16256 :             if (is_leaf)
     279       16090 :                 retval = tinfo->f_gt(query, key->lower, flinfo);
     280             :             else
     281         166 :                 retval = tinfo->f_ge(query, key->lower, flinfo);
     282       16256 :             break;
     283        9930 :         case BTEqualStrategyNumber:
     284        9930 :             if (is_leaf)
     285        9764 :                 retval = tinfo->f_eq(query, key->lower, flinfo);
     286             :             else
     287         256 :                 retval = (tinfo->f_le(key->lower, query, flinfo) &&
     288          90 :                           tinfo->f_le(query, key->upper, flinfo));
     289        9930 :             break;
     290       20252 :         case BTGreaterStrategyNumber:
     291       20252 :             if (is_leaf)
     292       20102 :                 retval = tinfo->f_lt(query, key->upper, flinfo);
     293             :             else
     294         150 :                 retval = tinfo->f_le(query, key->upper, flinfo);
     295       20252 :             break;
     296       20252 :         case BTGreaterEqualStrategyNumber:
     297       20252 :             retval = tinfo->f_le(query, key->upper, flinfo);
     298       20252 :             break;
     299         412 :         case BtreeGistNotEqualStrategyNumber:
     300         818 :             retval = (!(tinfo->f_eq(query, key->lower, flinfo) &&
     301         406 :                         tinfo->f_eq(query, key->upper, flinfo)));
     302         412 :             break;
     303           0 :         default:
     304           0 :             retval = false;
     305             :     }
     306             : 
     307       82740 :     return retval;
     308             : }
     309             : 
     310             : 
     311             : /*
     312             : ** The GiST distance method (for KNN-Gist)
     313             : */
     314             : 
     315             : float8
     316        4742 : gbt_num_distance(const GBT_NUMKEY_R *key,
     317             :                  const void *query,
     318             :                  bool is_leaf,
     319             :                  const gbtree_ninfo *tinfo,
     320             :                  FmgrInfo *flinfo)
     321             : {
     322             :     float8      retval;
     323             : 
     324        4742 :     if (tinfo->f_dist == NULL)
     325           0 :         elog(ERROR, "KNN search is not supported for btree_gist type %d",
     326             :              (int) tinfo->t);
     327        4742 :     if (tinfo->f_le(query, key->lower, flinfo))
     328        2510 :         retval = tinfo->f_dist(query, key->lower, flinfo);
     329        2232 :     else if (tinfo->f_ge(query, key->upper, flinfo))
     330        2208 :         retval = tinfo->f_dist(query, key->upper, flinfo);
     331             :     else
     332          24 :         retval = 0.0;
     333             : 
     334        4742 :     return retval;
     335             : }
     336             : 
     337             : 
     338             : GIST_SPLITVEC *
     339         132 : gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
     340             :                   const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     341             : {
     342             :     OffsetNumber i,
     343         132 :                 maxoff = entryvec->n - 1;
     344             :     Nsrt       *arr;
     345             :     int         nbytes;
     346             : 
     347         132 :     arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
     348         132 :     nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     349         132 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     350         132 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     351         132 :     v->spl_ldatum = PointerGetDatum(0);
     352         132 :     v->spl_rdatum = PointerGetDatum(0);
     353         132 :     v->spl_nleft = 0;
     354         132 :     v->spl_nright = 0;
     355             : 
     356             :     /* Sort entries */
     357             : 
     358       32230 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     359             :     {
     360       32098 :         arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
     361       32098 :         arr[i].i = i;
     362             :     }
     363         132 :     qsort_arg(&arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), (qsort_arg_comparator) tinfo->f_cmp, flinfo);
     364             : 
     365             :     /* We do simply create two parts */
     366             : 
     367       32230 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     368             :     {
     369       32098 :         if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
     370             :         {
     371       16034 :             gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
     372       16034 :             v->spl_left[v->spl_nleft] = arr[i].i;
     373       16034 :             v->spl_nleft++;
     374             :         }
     375             :         else
     376             :         {
     377       16064 :             gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
     378       16064 :             v->spl_right[v->spl_nright] = arr[i].i;
     379       16064 :             v->spl_nright++;
     380             :         }
     381             :     }
     382             : 
     383         132 :     return v;
     384             : }

Generated by: LCOV version 1.14