LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_ts.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 198 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 37 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * contrib/btree_gist/btree_ts.c
       3              :  */
       4              : #include "postgres.h"
       5              : 
       6              : #include <limits.h>
       7              : 
       8              : #include "btree_gist.h"
       9              : #include "btree_utils_num.h"
      10              : #include "utils/fmgrprotos.h"
      11              : #include "utils/timestamp.h"
      12              : #include "utils/float.h"
      13              : #include "utils/rel.h"
      14              : #include "utils/sortsupport.h"
      15              : 
      16              : typedef struct
      17              : {
      18              :         Timestamp       lower;
      19              :         Timestamp       upper;
      20              : } tsKEY;
      21              : 
      22              : /* GiST support functions */
      23            0 : PG_FUNCTION_INFO_V1(gbt_ts_compress);
      24            0 : PG_FUNCTION_INFO_V1(gbt_tstz_compress);
      25            0 : PG_FUNCTION_INFO_V1(gbt_ts_fetch);
      26            0 : PG_FUNCTION_INFO_V1(gbt_ts_union);
      27            0 : PG_FUNCTION_INFO_V1(gbt_ts_picksplit);
      28            0 : PG_FUNCTION_INFO_V1(gbt_ts_consistent);
      29            0 : PG_FUNCTION_INFO_V1(gbt_ts_distance);
      30            0 : PG_FUNCTION_INFO_V1(gbt_tstz_consistent);
      31            0 : PG_FUNCTION_INFO_V1(gbt_tstz_distance);
      32            0 : PG_FUNCTION_INFO_V1(gbt_ts_penalty);
      33            0 : PG_FUNCTION_INFO_V1(gbt_ts_same);
      34            0 : PG_FUNCTION_INFO_V1(gbt_ts_sortsupport);
      35              : 
      36              : 
      37              : /* define for comparison */
      38              : 
      39              : static bool
      40            0 : gbt_tsgt(const void *a, const void *b, FmgrInfo *flinfo)
      41              : {
      42            0 :         const Timestamp *aa = (const Timestamp *) a;
      43            0 :         const Timestamp *bb = (const Timestamp *) b;
      44              : 
      45            0 :         return DatumGetBool(DirectFunctionCall2(timestamp_gt,
      46              :                                                                                         TimestampGetDatum(*aa),
      47              :                                                                                         TimestampGetDatum(*bb)));
      48            0 : }
      49              : 
      50              : static bool
      51            0 : gbt_tsge(const void *a, const void *b, FmgrInfo *flinfo)
      52              : {
      53            0 :         const Timestamp *aa = (const Timestamp *) a;
      54            0 :         const Timestamp *bb = (const Timestamp *) b;
      55              : 
      56            0 :         return DatumGetBool(DirectFunctionCall2(timestamp_ge,
      57              :                                                                                         TimestampGetDatum(*aa),
      58              :                                                                                         TimestampGetDatum(*bb)));
      59            0 : }
      60              : 
      61              : static bool
      62            0 : gbt_tseq(const void *a, const void *b, FmgrInfo *flinfo)
      63              : {
      64            0 :         const Timestamp *aa = (const Timestamp *) a;
      65            0 :         const Timestamp *bb = (const Timestamp *) b;
      66              : 
      67            0 :         return DatumGetBool(DirectFunctionCall2(timestamp_eq,
      68              :                                                                                         TimestampGetDatum(*aa),
      69              :                                                                                         TimestampGetDatum(*bb)));
      70            0 : }
      71              : 
      72              : static bool
      73            0 : gbt_tsle(const void *a, const void *b, FmgrInfo *flinfo)
      74              : {
      75            0 :         const Timestamp *aa = (const Timestamp *) a;
      76            0 :         const Timestamp *bb = (const Timestamp *) b;
      77              : 
      78            0 :         return DatumGetBool(DirectFunctionCall2(timestamp_le,
      79              :                                                                                         TimestampGetDatum(*aa),
      80              :                                                                                         TimestampGetDatum(*bb)));
      81            0 : }
      82              : 
      83              : static bool
      84            0 : gbt_tslt(const void *a, const void *b, FmgrInfo *flinfo)
      85              : {
      86            0 :         const Timestamp *aa = (const Timestamp *) a;
      87            0 :         const Timestamp *bb = (const Timestamp *) b;
      88              : 
      89            0 :         return DatumGetBool(DirectFunctionCall2(timestamp_lt,
      90              :                                                                                         TimestampGetDatum(*aa),
      91              :                                                                                         TimestampGetDatum(*bb)));
      92            0 : }
      93              : 
      94              : static int
      95            0 : gbt_tskey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
      96              : {
      97            0 :         tsKEY      *ia = (tsKEY *) (((const Nsrt *) a)->t);
      98            0 :         tsKEY      *ib = (tsKEY *) (((const Nsrt *) b)->t);
      99            0 :         int                     res;
     100              : 
     101            0 :         res = DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatum(ia->lower), TimestampGetDatum(ib->lower)));
     102            0 :         if (res == 0)
     103            0 :                 return DatumGetInt32(DirectFunctionCall2(timestamp_cmp, TimestampGetDatum(ia->upper), TimestampGetDatum(ib->upper)));
     104              : 
     105            0 :         return res;
     106            0 : }
     107              : 
     108              : static float8
     109            0 : gbt_ts_dist(const void *a, const void *b, FmgrInfo *flinfo)
     110              : {
     111            0 :         const Timestamp *aa = (const Timestamp *) a;
     112            0 :         const Timestamp *bb = (const Timestamp *) b;
     113            0 :         Interval   *i;
     114              : 
     115            0 :         if (TIMESTAMP_NOT_FINITE(*aa) || TIMESTAMP_NOT_FINITE(*bb))
     116            0 :                 return get_float8_infinity();
     117              : 
     118            0 :         i = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
     119              :                                                                                           TimestampGetDatum(*aa),
     120              :                                                                                           TimestampGetDatum(*bb)));
     121            0 :         return fabs(INTERVAL_TO_SEC(i));
     122            0 : }
     123              : 
     124              : static const gbtree_ninfo tinfo =
     125              : {
     126              :         gbt_t_ts,
     127              :         sizeof(Timestamp),
     128              :         16,                                                     /* sizeof(gbtreekey16) */
     129              :         gbt_tsgt,
     130              :         gbt_tsge,
     131              :         gbt_tseq,
     132              :         gbt_tsle,
     133              :         gbt_tslt,
     134              :         gbt_tskey_cmp,
     135              :         gbt_ts_dist
     136              : };
     137              : 
     138              : 
     139            0 : PG_FUNCTION_INFO_V1(ts_dist);
     140              : Datum
     141            0 : ts_dist(PG_FUNCTION_ARGS)
     142              : {
     143            0 :         Timestamp       a = PG_GETARG_TIMESTAMP(0);
     144            0 :         Timestamp       b = PG_GETARG_TIMESTAMP(1);
     145            0 :         Interval   *r;
     146              : 
     147            0 :         if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
     148              :         {
     149            0 :                 Interval   *p = palloc_object(Interval);
     150              : 
     151            0 :                 p->day = INT_MAX;
     152            0 :                 p->month = INT_MAX;
     153            0 :                 p->time = PG_INT64_MAX;
     154            0 :                 PG_RETURN_INTERVAL_P(p);
     155            0 :         }
     156              :         else
     157            0 :                 r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
     158              :                                                                                                   PG_GETARG_DATUM(0),
     159              :                                                                                                   PG_GETARG_DATUM(1)));
     160            0 :         PG_RETURN_INTERVAL_P(abs_interval(r));
     161            0 : }
     162              : 
     163            0 : PG_FUNCTION_INFO_V1(tstz_dist);
     164              : Datum
     165            0 : tstz_dist(PG_FUNCTION_ARGS)
     166              : {
     167            0 :         TimestampTz a = PG_GETARG_TIMESTAMPTZ(0);
     168            0 :         TimestampTz b = PG_GETARG_TIMESTAMPTZ(1);
     169            0 :         Interval   *r;
     170              : 
     171            0 :         if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
     172              :         {
     173            0 :                 Interval   *p = palloc_object(Interval);
     174              : 
     175            0 :                 p->day = INT_MAX;
     176            0 :                 p->month = INT_MAX;
     177            0 :                 p->time = PG_INT64_MAX;
     178            0 :                 PG_RETURN_INTERVAL_P(p);
     179            0 :         }
     180              : 
     181            0 :         r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
     182              :                                                                                           PG_GETARG_DATUM(0),
     183              :                                                                                           PG_GETARG_DATUM(1)));
     184            0 :         PG_RETURN_INTERVAL_P(abs_interval(r));
     185            0 : }
     186              : 
     187              : /**************************************************
     188              :  * GiST support functions
     189              :  **************************************************/
     190              : 
     191              : static inline Timestamp
     192            0 : tstz_to_ts_gmt(TimestampTz ts)
     193              : {
     194              :         /* No timezone correction is needed, since GMT is offset 0 by definition */
     195            0 :         return (Timestamp) ts;
     196              : }
     197              : 
     198              : 
     199              : Datum
     200            0 : gbt_ts_compress(PG_FUNCTION_ARGS)
     201              : {
     202            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     203              : 
     204            0 :         PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
     205            0 : }
     206              : 
     207              : Datum
     208            0 : gbt_tstz_compress(PG_FUNCTION_ARGS)
     209              : {
     210            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     211            0 :         GISTENTRY  *retval;
     212              : 
     213            0 :         if (entry->leafkey)
     214              :         {
     215            0 :                 tsKEY      *r = palloc_object(tsKEY);
     216            0 :                 TimestampTz ts = DatumGetTimestampTz(entry->key);
     217            0 :                 Timestamp       gmt;
     218              : 
     219            0 :                 gmt = tstz_to_ts_gmt(ts);
     220              : 
     221            0 :                 retval = palloc_object(GISTENTRY);
     222            0 :                 r->lower = r->upper = gmt;
     223            0 :                 gistentryinit(*retval, PointerGetDatum(r),
     224              :                                           entry->rel, entry->page,
     225              :                                           entry->offset, false);
     226            0 :         }
     227              :         else
     228            0 :                 retval = entry;
     229              : 
     230            0 :         PG_RETURN_POINTER(retval);
     231            0 : }
     232              : 
     233              : Datum
     234            0 : gbt_ts_fetch(PG_FUNCTION_ARGS)
     235              : {
     236            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     237              : 
     238            0 :         PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
     239            0 : }
     240              : 
     241              : Datum
     242            0 : gbt_ts_consistent(PG_FUNCTION_ARGS)
     243              : {
     244            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     245            0 :         Timestamp       query = PG_GETARG_TIMESTAMP(1);
     246            0 :         StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     247              : #ifdef NOT_USED
     248              :         Oid                     subtype = PG_GETARG_OID(3);
     249              : #endif
     250            0 :         bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     251            0 :         tsKEY      *kkk = (tsKEY *) DatumGetPointer(entry->key);
     252            0 :         GBT_NUMKEY_R key;
     253              : 
     254              :         /* All cases served by this function are exact */
     255            0 :         *recheck = false;
     256              : 
     257            0 :         key.lower = (GBT_NUMKEY *) &kkk->lower;
     258            0 :         key.upper = (GBT_NUMKEY *) &kkk->upper;
     259              : 
     260            0 :         PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
     261              :                                                                           GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     262            0 : }
     263              : 
     264              : Datum
     265            0 : gbt_ts_distance(PG_FUNCTION_ARGS)
     266              : {
     267            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     268            0 :         Timestamp       query = PG_GETARG_TIMESTAMP(1);
     269              : #ifdef NOT_USED
     270              :         Oid                     subtype = PG_GETARG_OID(3);
     271              : #endif
     272            0 :         tsKEY      *kkk = (tsKEY *) DatumGetPointer(entry->key);
     273            0 :         GBT_NUMKEY_R key;
     274              : 
     275            0 :         key.lower = (GBT_NUMKEY *) &kkk->lower;
     276            0 :         key.upper = (GBT_NUMKEY *) &kkk->upper;
     277              : 
     278            0 :         PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
     279              :                                                                           &tinfo, fcinfo->flinfo));
     280            0 : }
     281              : 
     282              : Datum
     283            0 : gbt_tstz_consistent(PG_FUNCTION_ARGS)
     284              : {
     285            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     286            0 :         TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
     287            0 :         StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     288              : #ifdef NOT_USED
     289              :         Oid                     subtype = PG_GETARG_OID(3);
     290              : #endif
     291            0 :         bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     292            0 :         char       *kkk = (char *) DatumGetPointer(entry->key);
     293            0 :         GBT_NUMKEY_R key;
     294            0 :         Timestamp       qqq;
     295              : 
     296              :         /* All cases served by this function are exact */
     297            0 :         *recheck = false;
     298              : 
     299            0 :         key.lower = (GBT_NUMKEY *) &kkk[0];
     300            0 :         key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
     301            0 :         qqq = tstz_to_ts_gmt(query);
     302              : 
     303            0 :         PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
     304              :                                                                           GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     305            0 : }
     306              : 
     307              : Datum
     308            0 : gbt_tstz_distance(PG_FUNCTION_ARGS)
     309              : {
     310            0 :         GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     311            0 :         TimestampTz query = PG_GETARG_TIMESTAMPTZ(1);
     312              : #ifdef NOT_USED
     313              :         Oid                     subtype = PG_GETARG_OID(3);
     314              : #endif
     315            0 :         char       *kkk = (char *) DatumGetPointer(entry->key);
     316            0 :         GBT_NUMKEY_R key;
     317            0 :         Timestamp       qqq;
     318              : 
     319            0 :         key.lower = (GBT_NUMKEY *) &kkk[0];
     320            0 :         key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)];
     321            0 :         qqq = tstz_to_ts_gmt(query);
     322              : 
     323            0 :         PG_RETURN_FLOAT8(gbt_num_distance(&key, &qqq, GIST_LEAF(entry),
     324              :                                                                           &tinfo, fcinfo->flinfo));
     325            0 : }
     326              : 
     327              : 
     328              : Datum
     329            0 : gbt_ts_union(PG_FUNCTION_ARGS)
     330              : {
     331            0 :         GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     332            0 :         void       *out = palloc(sizeof(tsKEY));
     333              : 
     334            0 :         *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
     335            0 :         PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
     336            0 : }
     337              : 
     338              : 
     339              : #define penalty_check_max_float(val) \
     340              :         do { \
     341              :                 if ( val > FLT_MAX ) \
     342              :                                 val = FLT_MAX; \
     343              :                 if ( val < -FLT_MAX ) \
     344              :                                 val = -FLT_MAX; \
     345              :         } while (0)
     346              : 
     347              : 
     348              : Datum
     349            0 : gbt_ts_penalty(PG_FUNCTION_ARGS)
     350              : {
     351            0 :         tsKEY      *origentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     352            0 :         tsKEY      *newentry = (tsKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     353            0 :         float      *result = (float *) PG_GETARG_POINTER(2);
     354              : 
     355            0 :         double          orgdbl[2],
     356              :                                 newdbl[2];
     357              : 
     358              :         /*
     359              :          * We are always using "double" timestamps here. Precision should be good
     360              :          * enough.
     361              :          */
     362            0 :         orgdbl[0] = ((double) origentry->lower);
     363            0 :         orgdbl[1] = ((double) origentry->upper);
     364            0 :         newdbl[0] = ((double) newentry->lower);
     365            0 :         newdbl[1] = ((double) newentry->upper);
     366              : 
     367            0 :         penalty_check_max_float(orgdbl[0]);
     368            0 :         penalty_check_max_float(orgdbl[1]);
     369            0 :         penalty_check_max_float(newdbl[0]);
     370            0 :         penalty_check_max_float(newdbl[1]);
     371              : 
     372            0 :         penalty_num(result, orgdbl[0], orgdbl[1], newdbl[0], newdbl[1]);
     373              : 
     374            0 :         PG_RETURN_POINTER(result);
     375            0 : }
     376              : 
     377              : 
     378              : Datum
     379            0 : gbt_ts_picksplit(PG_FUNCTION_ARGS)
     380              : {
     381            0 :         PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
     382              :                                                                                 (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
     383              :                                                                                 &tinfo, fcinfo->flinfo));
     384              : }
     385              : 
     386              : Datum
     387            0 : gbt_ts_same(PG_FUNCTION_ARGS)
     388              : {
     389            0 :         tsKEY      *b1 = (tsKEY *) PG_GETARG_POINTER(0);
     390            0 :         tsKEY      *b2 = (tsKEY *) PG_GETARG_POINTER(1);
     391            0 :         bool       *result = (bool *) PG_GETARG_POINTER(2);
     392              : 
     393            0 :         *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
     394            0 :         PG_RETURN_POINTER(result);
     395            0 : }
     396              : 
     397              : static int
     398            0 : gbt_ts_ssup_cmp(Datum x, Datum y, SortSupport ssup)
     399              : {
     400            0 :         tsKEY      *arg1 = (tsKEY *) DatumGetPointer(x);
     401            0 :         tsKEY      *arg2 = (tsKEY *) DatumGetPointer(y);
     402              : 
     403              :         /* for leaf items we expect lower == upper, so only compare lower */
     404            0 :         return DatumGetInt32(DirectFunctionCall2(timestamp_cmp,
     405              :                                                                                          TimestampGetDatum(arg1->lower),
     406              :                                                                                          TimestampGetDatum(arg2->lower)));
     407            0 : }
     408              : 
     409              : Datum
     410            0 : gbt_ts_sortsupport(PG_FUNCTION_ARGS)
     411              : {
     412            0 :         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     413              : 
     414            0 :         ssup->comparator = gbt_ts_ssup_cmp;
     415            0 :         ssup->ssup_extra = NULL;
     416              : 
     417            0 :         PG_RETURN_VOID();
     418            0 : }
        

Generated by: LCOV version 2.3.2-1