LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_utils_num.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 199 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 8 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            0 : gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
      15              : {
      16            0 :         GISTENTRY  *retval;
      17              : 
      18            0 :         if (entry->leafkey)
      19              :         {
      20            0 :                 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            0 :                 GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(tinfo->indexsize);
      35            0 :                 void       *leaf = NULL;
      36              : 
      37            0 :                 switch (tinfo->t)
      38              :                 {
      39              :                         case gbt_t_bool:
      40            0 :                                 v.bo = DatumGetBool(entry->key);
      41            0 :                                 leaf = &v.bo;
      42            0 :                                 break;
      43              :                         case gbt_t_int2:
      44            0 :                                 v.i2 = DatumGetInt16(entry->key);
      45            0 :                                 leaf = &v.i2;
      46            0 :                                 break;
      47              :                         case gbt_t_int4:
      48            0 :                                 v.i4 = DatumGetInt32(entry->key);
      49            0 :                                 leaf = &v.i4;
      50            0 :                                 break;
      51              :                         case gbt_t_int8:
      52            0 :                                 v.i8 = DatumGetInt64(entry->key);
      53            0 :                                 leaf = &v.i8;
      54            0 :                                 break;
      55              :                         case gbt_t_oid:
      56              :                         case gbt_t_enum:
      57            0 :                                 v.i4 = DatumGetObjectId(entry->key);
      58            0 :                                 leaf = &v.i4;
      59            0 :                                 break;
      60              :                         case gbt_t_float4:
      61            0 :                                 v.f4 = DatumGetFloat4(entry->key);
      62            0 :                                 leaf = &v.f4;
      63            0 :                                 break;
      64              :                         case gbt_t_float8:
      65            0 :                                 v.f8 = DatumGetFloat8(entry->key);
      66            0 :                                 leaf = &v.f8;
      67            0 :                                 break;
      68              :                         case gbt_t_date:
      69            0 :                                 v.dt = DatumGetDateADT(entry->key);
      70            0 :                                 leaf = &v.dt;
      71            0 :                                 break;
      72              :                         case gbt_t_time:
      73            0 :                                 v.tm = DatumGetTimeADT(entry->key);
      74            0 :                                 leaf = &v.tm;
      75            0 :                                 break;
      76              :                         case gbt_t_ts:
      77            0 :                                 v.ts = DatumGetTimestamp(entry->key);
      78            0 :                                 leaf = &v.ts;
      79            0 :                                 break;
      80              :                         case gbt_t_cash:
      81            0 :                                 v.ch = DatumGetCash(entry->key);
      82            0 :                                 leaf = &v.ch;
      83            0 :                                 break;
      84              :                         default:
      85            0 :                                 leaf = DatumGetPointer(entry->key);
      86            0 :                 }
      87              : 
      88            0 :                 Assert(tinfo->indexsize >= 2 * tinfo->size);
      89              : 
      90            0 :                 memcpy(&r[0], leaf, tinfo->size);
      91            0 :                 memcpy(&r[tinfo->size], leaf, tinfo->size);
      92            0 :                 retval = palloc_object(GISTENTRY);
      93            0 :                 gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
      94              :                                           entry->offset, false);
      95            0 :         }
      96              :         else
      97            0 :                 retval = entry;
      98              : 
      99            0 :         return retval;
     100            0 : }
     101              : 
     102              : /*
     103              :  * Convert a compressed leaf item back to the original type, for index-only
     104              :  * scans.
     105              :  */
     106              : GISTENTRY *
     107            0 : gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
     108              : {
     109            0 :         GISTENTRY  *retval;
     110            0 :         Datum           datum;
     111              : 
     112            0 :         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            0 :         switch (tinfo->t)
     120              :         {
     121              :                 case gbt_t_bool:
     122            0 :                         datum = BoolGetDatum(*(bool *) DatumGetPointer(entry->key));
     123            0 :                         break;
     124              :                 case gbt_t_int2:
     125            0 :                         datum = Int16GetDatum(*(int16 *) DatumGetPointer(entry->key));
     126            0 :                         break;
     127              :                 case gbt_t_int4:
     128            0 :                         datum = Int32GetDatum(*(int32 *) DatumGetPointer(entry->key));
     129            0 :                         break;
     130              :                 case gbt_t_int8:
     131            0 :                         datum = Int64GetDatum(*(int64 *) DatumGetPointer(entry->key));
     132            0 :                         break;
     133              :                 case gbt_t_oid:
     134              :                 case gbt_t_enum:
     135            0 :                         datum = ObjectIdGetDatum(*(Oid *) DatumGetPointer(entry->key));
     136            0 :                         break;
     137              :                 case gbt_t_float4:
     138            0 :                         datum = Float4GetDatum(*(float4 *) DatumGetPointer(entry->key));
     139            0 :                         break;
     140              :                 case gbt_t_float8:
     141            0 :                         datum = Float8GetDatum(*(float8 *) DatumGetPointer(entry->key));
     142            0 :                         break;
     143              :                 case gbt_t_date:
     144            0 :                         datum = DateADTGetDatum(*(DateADT *) DatumGetPointer(entry->key));
     145            0 :                         break;
     146              :                 case gbt_t_time:
     147            0 :                         datum = TimeADTGetDatum(*(TimeADT *) DatumGetPointer(entry->key));
     148            0 :                         break;
     149              :                 case gbt_t_ts:
     150            0 :                         datum = TimestampGetDatum(*(Timestamp *) DatumGetPointer(entry->key));
     151            0 :                         break;
     152              :                 case gbt_t_cash:
     153            0 :                         datum = CashGetDatum(*(Cash *) DatumGetPointer(entry->key));
     154            0 :                         break;
     155              :                 default:
     156            0 :                         datum = entry->key;
     157            0 :         }
     158              : 
     159            0 :         retval = palloc_object(GISTENTRY);
     160            0 :         gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset,
     161              :                                   false);
     162            0 :         return retval;
     163            0 : }
     164              : 
     165              : 
     166              : 
     167              : /*
     168              : ** The GiST union method for numerical values
     169              : */
     170              : 
     171              : void *
     172            0 : gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     173              : {
     174            0 :         int                     i,
     175              :                                 numranges;
     176            0 :         GBT_NUMKEY *cur;
     177            0 :         GBT_NUMKEY_R o,
     178              :                                 c;
     179              : 
     180            0 :         numranges = entryvec->n;
     181            0 :         cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
     182              : 
     183              : 
     184            0 :         o.lower = &out[0];
     185            0 :         o.upper = &out[tinfo->size];
     186              : 
     187            0 :         memcpy(out, cur, 2 * tinfo->size);
     188              : 
     189            0 :         for (i = 1; i < numranges; i++)
     190              :         {
     191            0 :                 cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
     192            0 :                 c.lower = &cur[0];
     193            0 :                 c.upper = &cur[tinfo->size];
     194              :                 /* if out->lower > cur->lower, adopt cur as lower */
     195            0 :                 if (tinfo->f_gt(o.lower, c.lower, flinfo))
     196            0 :                         memcpy(unconstify(GBT_NUMKEY *, o.lower), c.lower, tinfo->size);
     197              :                 /* if out->upper < cur->upper, adopt cur as upper */
     198            0 :                 if (tinfo->f_lt(o.upper, c.upper, flinfo))
     199            0 :                         memcpy(unconstify(GBT_NUMKEY *, o.upper), c.upper, tinfo->size);
     200            0 :         }
     201              : 
     202            0 :         return out;
     203            0 : }
     204              : 
     205              : 
     206              : 
     207              : /*
     208              : ** The GiST same method for numerical values
     209              : */
     210              : 
     211              : bool
     212            0 : gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     213              : {
     214            0 :         GBT_NUMKEY_R b1,
     215              :                                 b2;
     216              : 
     217            0 :         b1.lower = &(a[0]);
     218            0 :         b1.upper = &(a[tinfo->size]);
     219            0 :         b2.lower = &(b[0]);
     220            0 :         b2.upper = &(b[tinfo->size]);
     221              : 
     222            0 :         return (tinfo->f_eq(b1.lower, b2.lower, flinfo) &&
     223            0 :                         tinfo->f_eq(b1.upper, b2.upper, flinfo));
     224            0 : }
     225              : 
     226              : 
     227              : void
     228            0 : gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     229              : {
     230            0 :         GBT_NUMKEY_R rd;
     231              : 
     232            0 :         rd.lower = &e[0];
     233            0 :         rd.upper = &e[tinfo->size];
     234              : 
     235            0 :         if (!DatumGetPointer(*u))
     236              :         {
     237            0 :                 *u = PointerGetDatum(palloc0(tinfo->indexsize));
     238            0 :                 memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), rd.lower, tinfo->size);
     239            0 :                 memcpy(&(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), rd.upper, tinfo->size);
     240            0 :         }
     241              :         else
     242              :         {
     243            0 :                 GBT_NUMKEY_R ur;
     244              : 
     245            0 :                 ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
     246            0 :                 ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
     247            0 :                 if (tinfo->f_gt(ur.lower, rd.lower, flinfo))
     248            0 :                         memcpy(unconstify(GBT_NUMKEY *, ur.lower), rd.lower, tinfo->size);
     249            0 :                 if (tinfo->f_lt(ur.upper, rd.upper, flinfo))
     250            0 :                         memcpy(unconstify(GBT_NUMKEY *, ur.upper), rd.upper, tinfo->size);
     251            0 :         }
     252            0 : }
     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            0 : 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            0 :         bool            retval;
     271              : 
     272            0 :         switch (*strategy)
     273              :         {
     274              :                 case BTLessEqualStrategyNumber:
     275            0 :                         retval = tinfo->f_ge(query, key->lower, flinfo);
     276            0 :                         break;
     277              :                 case BTLessStrategyNumber:
     278            0 :                         if (is_leaf)
     279            0 :                                 retval = tinfo->f_gt(query, key->lower, flinfo);
     280              :                         else
     281            0 :                                 retval = tinfo->f_ge(query, key->lower, flinfo);
     282            0 :                         break;
     283              :                 case BTEqualStrategyNumber:
     284            0 :                         if (is_leaf)
     285            0 :                                 retval = tinfo->f_eq(query, key->lower, flinfo);
     286              :                         else
     287            0 :                                 retval = (tinfo->f_le(key->lower, query, flinfo) &&
     288            0 :                                                   tinfo->f_le(query, key->upper, flinfo));
     289            0 :                         break;
     290              :                 case BTGreaterStrategyNumber:
     291            0 :                         if (is_leaf)
     292            0 :                                 retval = tinfo->f_lt(query, key->upper, flinfo);
     293              :                         else
     294            0 :                                 retval = tinfo->f_le(query, key->upper, flinfo);
     295            0 :                         break;
     296              :                 case BTGreaterEqualStrategyNumber:
     297            0 :                         retval = tinfo->f_le(query, key->upper, flinfo);
     298            0 :                         break;
     299              :                 case BtreeGistNotEqualStrategyNumber:
     300            0 :                         retval = (!(tinfo->f_eq(query, key->lower, flinfo) &&
     301            0 :                                                 tinfo->f_eq(query, key->upper, flinfo)));
     302            0 :                         break;
     303              :                 default:
     304            0 :                         retval = false;
     305            0 :         }
     306              : 
     307            0 :         return retval;
     308            0 : }
     309              : 
     310              : 
     311              : /*
     312              : ** The GiST distance method (for KNN-Gist)
     313              : */
     314              : 
     315              : float8
     316            0 : 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            0 :         float8          retval;
     323              : 
     324            0 :         if (tinfo->f_dist == NULL)
     325            0 :                 elog(ERROR, "KNN search is not supported for btree_gist type %d",
     326              :                          (int) tinfo->t);
     327            0 :         if (tinfo->f_le(query, key->lower, flinfo))
     328            0 :                 retval = tinfo->f_dist(query, key->lower, flinfo);
     329            0 :         else if (tinfo->f_ge(query, key->upper, flinfo))
     330            0 :                 retval = tinfo->f_dist(query, key->upper, flinfo);
     331              :         else
     332            0 :                 retval = 0.0;
     333              : 
     334            0 :         return retval;
     335            0 : }
     336              : 
     337              : 
     338              : GIST_SPLITVEC *
     339            0 : gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
     340              :                                   const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
     341              : {
     342            0 :         OffsetNumber i,
     343            0 :                                 maxoff = entryvec->n - 1;
     344            0 :         Nsrt       *arr;
     345            0 :         int                     nbytes;
     346              : 
     347            0 :         arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
     348            0 :         nbytes = (maxoff + 2) * sizeof(OffsetNumber);
     349            0 :         v->spl_left = (OffsetNumber *) palloc(nbytes);
     350            0 :         v->spl_right = (OffsetNumber *) palloc(nbytes);
     351            0 :         v->spl_ldatum = PointerGetDatum(0);
     352            0 :         v->spl_rdatum = PointerGetDatum(0);
     353            0 :         v->spl_nleft = 0;
     354            0 :         v->spl_nright = 0;
     355              : 
     356              :         /* Sort entries */
     357              : 
     358            0 :         for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     359              :         {
     360            0 :                 arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
     361            0 :                 arr[i].i = i;
     362            0 :         }
     363            0 :         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            0 :         for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     368              :         {
     369            0 :                 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
     370              :                 {
     371            0 :                         gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
     372            0 :                         v->spl_left[v->spl_nleft] = arr[i].i;
     373            0 :                         v->spl_nleft++;
     374            0 :                 }
     375              :                 else
     376              :                 {
     377            0 :                         gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
     378            0 :                         v->spl_right[v->spl_nright] = arr[i].i;
     379            0 :                         v->spl_nright++;
     380              :                 }
     381            0 :         }
     382              : 
     383            0 :         return v;
     384            0 : }
        

Generated by: LCOV version 2.3.2-1