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

Generated by: LCOV version 1.14