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: 2025-08-31 01:17:28 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 = (timeKEY *) palloc(sizeof(timeKEY));
     166        1062 :         TimeTzADT  *tz = DatumGetTimeTzADTP(entry->key);
     167             :         TimeADT     tmp;
     168             : 
     169        1062 :         retval = palloc(sizeof(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             : 
     198             :     /* Oid      subtype = PG_GETARG_OID(3); */
     199        3828 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     200        3828 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     201             :     GBT_NUMKEY_R key;
     202             : 
     203             :     /* All cases served by this function are exact */
     204        3828 :     *recheck = false;
     205             : 
     206        3828 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     207        3828 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     208             : 
     209        3828 :     PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
     210             :                                       GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     211             : }
     212             : 
     213             : Datum
     214         548 : gbt_time_distance(PG_FUNCTION_ARGS)
     215             : {
     216         548 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     217         548 :     TimeADT     query = PG_GETARG_TIMEADT(1);
     218             : 
     219             :     /* Oid      subtype = PG_GETARG_OID(3); */
     220         548 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     221             :     GBT_NUMKEY_R key;
     222             : 
     223         548 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     224         548 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     225             : 
     226         548 :     PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
     227             :                                       &tinfo, fcinfo->flinfo));
     228             : }
     229             : 
     230             : Datum
     231       11202 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
     232             : {
     233       11202 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     234       11202 :     TimeTzADT  *query = PG_GETARG_TIMETZADT_P(1);
     235       11202 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     236             : 
     237             :     /* Oid      subtype = PG_GETARG_OID(3); */
     238       11202 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     239       11202 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     240             :     TimeADT     qqq;
     241             :     GBT_NUMKEY_R key;
     242             : 
     243             :     /* All cases served by this function are inexact */
     244       11202 :     *recheck = true;
     245             : 
     246       11202 :     qqq = query->time + (query->zone * INT64CONST(1000000));
     247             : 
     248       11202 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     249       11202 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     250             : 
     251       11202 :     PG_RETURN_BOOL(gbt_num_consistent(&key, &qqq, &strategy,
     252             :                                       GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     253             : }
     254             : 
     255             : Datum
     256           4 : gbt_time_union(PG_FUNCTION_ARGS)
     257             : {
     258           4 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     259           4 :     void       *out = palloc(sizeof(timeKEY));
     260             : 
     261           4 :     *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
     262           4 :     PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
     263             : }
     264             : 
     265             : Datum
     266           0 : gbt_time_penalty(PG_FUNCTION_ARGS)
     267             : {
     268           0 :     timeKEY    *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     269           0 :     timeKEY    *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     270           0 :     float      *result = (float *) PG_GETARG_POINTER(2);
     271             :     Interval   *intr;
     272             :     double      res;
     273             :     double      res2;
     274             : 
     275           0 :     intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     276             :                                                  TimeADTGetDatum(newentry->upper),
     277             :                                                  TimeADTGetDatum(origentry->upper)));
     278           0 :     res = INTERVAL_TO_SEC(intr);
     279           0 :     res = Max(res, 0);
     280             : 
     281           0 :     intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     282             :                                                  TimeADTGetDatum(origentry->lower),
     283             :                                                  TimeADTGetDatum(newentry->lower)));
     284           0 :     res2 = INTERVAL_TO_SEC(intr);
     285           0 :     res2 = Max(res2, 0);
     286             : 
     287           0 :     res += res2;
     288             : 
     289           0 :     *result = 0.0;
     290             : 
     291           0 :     if (res > 0)
     292             :     {
     293           0 :         intr = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
     294             :                                                      TimeADTGetDatum(origentry->upper),
     295             :                                                      TimeADTGetDatum(origentry->lower)));
     296           0 :         *result += FLT_MIN;
     297           0 :         *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
     298           0 :         *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
     299             :     }
     300             : 
     301           0 :     PG_RETURN_POINTER(result);
     302             : }
     303             : 
     304             : Datum
     305           4 : gbt_time_picksplit(PG_FUNCTION_ARGS)
     306             : {
     307           4 :     PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
     308             :                                         (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
     309             :                                         &tinfo, fcinfo->flinfo));
     310             : }
     311             : 
     312             : Datum
     313           0 : gbt_time_same(PG_FUNCTION_ARGS)
     314             : {
     315           0 :     timeKEY    *b1 = (timeKEY *) PG_GETARG_POINTER(0);
     316           0 :     timeKEY    *b2 = (timeKEY *) PG_GETARG_POINTER(1);
     317           0 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     318             : 
     319           0 :     *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
     320           0 :     PG_RETURN_POINTER(result);
     321             : }
     322             : 
     323             : static int
     324       21270 : gbt_timekey_ssup_cmp(Datum x, Datum y, SortSupport ssup)
     325             : {
     326       21270 :     timeKEY    *arg1 = (timeKEY *) DatumGetPointer(x);
     327       21270 :     timeKEY    *arg2 = (timeKEY *) DatumGetPointer(y);
     328             : 
     329             :     /* for leaf items we expect lower == upper, so only compare lower */
     330       21270 :     return DatumGetInt32(DirectFunctionCall2(time_cmp,
     331             :                                              TimeADTGetDatum(arg1->lower),
     332             :                                              TimeADTGetDatum(arg2->lower)));
     333             : }
     334             : 
     335             : Datum
     336           4 : gbt_time_sortsupport(PG_FUNCTION_ARGS)
     337             : {
     338           4 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     339             : 
     340           4 :     ssup->comparator = gbt_timekey_ssup_cmp;
     341           4 :     ssup->ssup_extra = NULL;
     342             : 
     343           4 :     PG_RETURN_VOID();
     344             : }

Generated by: LCOV version 1.16