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

Generated by: LCOV version 1.14