LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_time.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 108 133 81.2 %
Date: 2026-02-02 14:17:46 Functions: 30 33 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * contrib/btree_gist/btree_time.c
       3             :  */
       4             : #include "postgres.h"
       5             : 
       6             : #include "btree_gist.h"
       7             : #include "btree_utils_num.h"
       8             : #include "utils/fmgrprotos.h"
       9             : #include "utils/date.h"
      10             : #include "utils/rel.h"
      11             : #include "utils/sortsupport.h"
      12             : #include "utils/timestamp.h"
      13             : 
      14             : typedef struct
      15             : {
      16             :     TimeADT     lower;
      17             :     TimeADT     upper;
      18             : } timeKEY;
      19             : 
      20             : /* GiST support functions */
      21           8 : PG_FUNCTION_INFO_V1(gbt_time_compress);
      22           8 : PG_FUNCTION_INFO_V1(gbt_timetz_compress);
      23           8 : PG_FUNCTION_INFO_V1(gbt_time_fetch);
      24          10 : PG_FUNCTION_INFO_V1(gbt_time_union);
      25          10 : PG_FUNCTION_INFO_V1(gbt_time_picksplit);
      26           8 : PG_FUNCTION_INFO_V1(gbt_time_consistent);
      27           8 : PG_FUNCTION_INFO_V1(gbt_time_distance);
      28           8 : PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
      29          10 : PG_FUNCTION_INFO_V1(gbt_time_penalty);
      30          10 : PG_FUNCTION_INFO_V1(gbt_time_same);
      31          10 : PG_FUNCTION_INFO_V1(gbt_time_sortsupport);
      32           0 : PG_FUNCTION_INFO_V1(gbt_timetz_sortsupport);
      33             : 
      34             : 
      35             : static bool
      36        6422 : gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)
      37             : {
      38        6422 :     const TimeADT *aa = (const TimeADT *) a;
      39        6422 :     const TimeADT *bb = (const TimeADT *) b;
      40             : 
      41        6422 :     return DatumGetBool(DirectFunctionCall2(time_gt,
      42             :                                             TimeADTGetDatum(*aa),
      43             :                                             TimeADTGetDatum(*bb)));
      44             : }
      45             : 
      46             : static bool
      47        2670 : gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)
      48             : {
      49        2670 :     const TimeADT *aa = (const TimeADT *) a;
      50        2670 :     const TimeADT *bb = (const TimeADT *) b;
      51             : 
      52        2670 :     return DatumGetBool(DirectFunctionCall2(time_ge,
      53             :                                             TimeADTGetDatum(*aa),
      54             :                                             TimeADTGetDatum(*bb)));
      55             : }
      56             : 
      57             : static bool
      58        2134 : gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)
      59             : {
      60        2134 :     const TimeADT *aa = (const TimeADT *) a;
      61        2134 :     const TimeADT *bb = (const TimeADT *) b;
      62             : 
      63        2134 :     return DatumGetBool(DirectFunctionCall2(time_eq,
      64             :                                             TimeADTGetDatum(*aa),
      65             :                                             TimeADTGetDatum(*bb)));
      66             : }
      67             : 
      68             : static bool
      69        4878 : gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)
      70             : {
      71        4878 :     const TimeADT *aa = (const TimeADT *) a;
      72        4878 :     const TimeADT *bb = (const TimeADT *) b;
      73             : 
      74        4878 :     return DatumGetBool(DirectFunctionCall2(time_le,
      75             :                                             TimeADTGetDatum(*aa),
      76             :                                             TimeADTGetDatum(*bb)));
      77             : }
      78             : 
      79             : static bool
      80        8562 : gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)
      81             : {
      82        8562 :     const TimeADT *aa = (const TimeADT *) a;
      83        8562 :     const TimeADT *bb = (const TimeADT *) b;
      84             : 
      85        8562 :     return DatumGetBool(DirectFunctionCall2(time_lt,
      86             :                                             TimeADTGetDatum(*aa),
      87             :                                             TimeADTGetDatum(*bb)));
      88             : }
      89             : 
      90             : static int
      91        2146 : gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
      92             : {
      93        2146 :     timeKEY    *ia = (timeKEY *) (((const Nsrt *) a)->t);
      94        2146 :     timeKEY    *ib = (timeKEY *) (((const Nsrt *) b)->t);
      95             :     int         res;
      96             : 
      97        2146 :     res = DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->lower), TimeADTGetDatum(ib->lower)));
      98        2146 :     if (res == 0)
      99           2 :         return DatumGetInt32(DirectFunctionCall2(time_cmp, TimeADTGetDatum(ia->upper), TimeADTGetDatum(ib->upper)));
     100             : 
     101        2144 :     return res;
     102             : }
     103             : 
     104             : static float8
     105         546 : gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)
     106             : {
     107         546 :     const TimeADT *aa = (const TimeADT *) a;
     108         546 :     const TimeADT *bb = (const TimeADT *) b;
     109             :     Interval   *i;
     110             : 
     111         546 :     i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     112             :                                               TimeADTGetDatum(*aa),
     113             :                                               TimeADTGetDatum(*bb)));
     114         546 :     return fabs(INTERVAL_TO_SEC(i));
     115             : }
     116             : 
     117             : 
     118             : static const gbtree_ninfo tinfo =
     119             : {
     120             :     gbt_t_time,
     121             :     sizeof(TimeADT),
     122             :     16,                         /* sizeof(gbtreekey16) */
     123             :     gbt_timegt,
     124             :     gbt_timege,
     125             :     gbt_timeeq,
     126             :     gbt_timele,
     127             :     gbt_timelt,
     128             :     gbt_timekey_cmp,
     129             :     gbt_time_dist
     130             : };
     131             : 
     132             : 
     133           8 : PG_FUNCTION_INFO_V1(time_dist);
     134             : Datum
     135        1094 : time_dist(PG_FUNCTION_ARGS)
     136             : {
     137        1094 :     Datum       diff = DirectFunctionCall2(time_mi_time,
     138             :                                            PG_GETARG_DATUM(0),
     139             :                                            PG_GETARG_DATUM(1));
     140             : 
     141        1094 :     PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
     142             : }
     143             : 
     144             : 
     145             : /**************************************************
     146             :  * GiST support functions
     147             :  **************************************************/
     148             : 
     149             : Datum
     150        1092 : gbt_time_compress(PG_FUNCTION_ARGS)
     151             : {
     152        1092 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     153             : 
     154        1092 :     PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
     155             : }
     156             : 
     157             : Datum
     158        1066 : gbt_timetz_compress(PG_FUNCTION_ARGS)
     159             : {
     160        1066 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     161             :     GISTENTRY  *retval;
     162             : 
     163        1066 :     if (entry->leafkey)
     164             :     {
     165        1062 :         timeKEY    *r = palloc_object(timeKEY);
     166        1062 :         TimeTzADT  *tz = DatumGetTimeTzADTP(entry->key);
     167             :         TimeADT     tmp;
     168             : 
     169        1062 :         retval = palloc_object(GISTENTRY);
     170             : 
     171             :         /* We are using the time + zone only to compress */
     172        1062 :         tmp = tz->time + (tz->zone * INT64CONST(1000000));
     173        1062 :         r->lower = r->upper = tmp;
     174        1062 :         gistentryinit(*retval, PointerGetDatum(r),
     175             :                       entry->rel, entry->page,
     176             :                       entry->offset, false);
     177             :     }
     178             :     else
     179           4 :         retval = entry;
     180        1066 :     PG_RETURN_POINTER(retval);
     181             : }
     182             : 
     183             : Datum
     184         544 : gbt_time_fetch(PG_FUNCTION_ARGS)
     185             : {
     186         544 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     187             : 
     188         544 :     PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
     189             : }
     190             : 
     191             : Datum
     192        3828 : gbt_time_consistent(PG_FUNCTION_ARGS)
     193             : {
     194        3828 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     195        3828 :     TimeADT     query = PG_GETARG_TIMEADT(1);
     196        3828 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     197             : #ifdef NOT_USED
     198             :     Oid         subtype = PG_GETARG_OID(3);
     199             : #endif
     200        3828 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     201        3828 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     202             :     GBT_NUMKEY_R key;
     203             : 
     204             :     /* All cases served by this function are exact */
     205        3828 :     *recheck = false;
     206             : 
     207        3828 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     208        3828 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     209             : 
     210        3828 :     PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
     211             :                                       GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     212             : }
     213             : 
     214             : Datum
     215         548 : gbt_time_distance(PG_FUNCTION_ARGS)
     216             : {
     217         548 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     218         548 :     TimeADT     query = PG_GETARG_TIMEADT(1);
     219             : #ifdef NOT_USED
     220             :     Oid         subtype = PG_GETARG_OID(3);
     221             : #endif
     222         548 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     223             :     GBT_NUMKEY_R key;
     224             : 
     225         548 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     226         548 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     227             : 
     228         548 :     PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
     229             :                                       &tinfo, fcinfo->flinfo));
     230             : }
     231             : 
     232             : Datum
     233       11202 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
     234             : {
     235       11202 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     236       11202 :     TimeTzADT  *query = PG_GETARG_TIMETZADT_P(1);
     237       11202 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     238             : #ifdef NOT_USED
     239             :     Oid         subtype = PG_GETARG_OID(3);
     240             : #endif
     241       11202 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     242       11202 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     243             :     TimeADT     qqq;
     244             :     GBT_NUMKEY_R key;
     245             : 
     246             :     /* All cases served by this function are inexact */
     247       11202 :     *recheck = true;
     248             : 
     249       11202 :     qqq = query->time + (query->zone * INT64CONST(1000000));
     250             : 
     251       11202 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     252       11202 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     253             : 
     254       11202 :     PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
     255             :                                       GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     256             : }
     257             : 
     258             : Datum
     259           4 : gbt_time_union(PG_FUNCTION_ARGS)
     260             : {
     261           4 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     262           4 :     void       *out = palloc(sizeof(timeKEY));
     263             : 
     264           4 :     *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
     265           4 :     PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
     266             : }
     267             : 
     268             : Datum
     269           0 : gbt_time_penalty(PG_FUNCTION_ARGS)
     270             : {
     271           0 :     timeKEY    *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     272           0 :     timeKEY    *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     273           0 :     float      *result = (float *) PG_GETARG_POINTER(2);
     274             :     Interval   *intr;
     275             :     double      res;
     276             :     double      res2;
     277             : 
     278           0 :     intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     279             :                                                  TimeADTGetDatum(newentry->upper),
     280             :                                                  TimeADTGetDatum(origentry->upper)));
     281           0 :     res = INTERVAL_TO_SEC(intr);
     282           0 :     res = Max(res, 0);
     283             : 
     284           0 :     intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     285             :                                                  TimeADTGetDatum(origentry->lower),
     286             :                                                  TimeADTGetDatum(newentry->lower)));
     287           0 :     res2 = INTERVAL_TO_SEC(intr);
     288           0 :     res2 = Max(res2, 0);
     289             : 
     290           0 :     res += res2;
     291             : 
     292           0 :     *result = 0.0;
     293             : 
     294           0 :     if (res > 0)
     295             :     {
     296           0 :         intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     297             :                                                      TimeADTGetDatum(origentry->upper),
     298             :                                                      TimeADTGetDatum(origentry->lower)));
     299           0 :         *result += FLT_MIN;
     300           0 :         *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
     301           0 :         *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
     302             :     }
     303             : 
     304           0 :     PG_RETURN_POINTER(result);
     305             : }
     306             : 
     307             : Datum
     308           4 : gbt_time_picksplit(PG_FUNCTION_ARGS)
     309             : {
     310           4 :     PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
     311             :                                         (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
     312             :                                         &tinfo, fcinfo->flinfo));
     313             : }
     314             : 
     315             : Datum
     316           0 : gbt_time_same(PG_FUNCTION_ARGS)
     317             : {
     318           0 :     timeKEY    *b1 = (timeKEY *) PG_GETARG_POINTER(0);
     319           0 :     timeKEY    *b2 = (timeKEY *) PG_GETARG_POINTER(1);
     320           0 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     321             : 
     322           0 :     *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
     323           0 :     PG_RETURN_POINTER(result);
     324             : }
     325             : 
     326             : static int
     327       21270 : gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
     328             : {
     329       21270 :     timeKEY    *arg1 = (timeKEY *) DatumGetPointer(x);
     330       21270 :     timeKEY    *arg2 = (timeKEY *) DatumGetPointer(y);
     331             : 
     332             :     /* for leaf items we expect lower == upper, so only compare lower */
     333       21270 :     return DatumGetInt32(DirectFunctionCall2(time_cmp,
     334             :                                              TimeADTGetDatum(arg1->lower),
     335             :                                              TimeADTGetDatum(arg2->lower)));
     336             : }
     337             : 
     338             : Datum
     339           4 : gbt_time_sortsupport(PG_FUNCTION_ARGS)
     340             : {
     341           4 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     342             : 
     343           4 :     ssup->comparator = gbt_timekey_ssup_cmp;
     344           4 :     ssup->ssup_extra = NULL;
     345             : 
     346           4 :     PG_RETURN_VOID();
     347             : }

Generated by: LCOV version 1.16