LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_time.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 121 122 99.2 %
Date: 2019-08-24 15:07:19 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/builtins.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 (float8) Abs(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(
     220             :                    gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
     221             :         );
     222             : }
     223             : 
     224             : Datum
     225         290 : gbt_time_distance(PG_FUNCTION_ARGS)
     226             : {
     227         290 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     228         290 :     TimeADT     query = PG_GETARG_TIMEADT(1);
     229             : 
     230             :     /* Oid      subtype = PG_GETARG_OID(3); */
     231         290 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     232             :     GBT_NUMKEY_R key;
     233             : 
     234         290 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     235         290 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     236             : 
     237         290 :     PG_RETURN_FLOAT8(
     238             :                      gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
     239             :         );
     240             : }
     241             : 
     242             : Datum
     243        9582 : gbt_timetz_consistent(PG_FUNCTION_ARGS)
     244             : {
     245        9582 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     246        9582 :     TimeTzADT  *query = PG_GETARG_TIMETZADT_P(1);
     247        9582 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     248             : 
     249             :     /* Oid      subtype = PG_GETARG_OID(3); */
     250        9582 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     251        9582 :     timeKEY    *kkk = (timeKEY *) DatumGetPointer(entry->key);
     252             :     TimeADT     qqq;
     253             :     GBT_NUMKEY_R key;
     254             : 
     255             :     /* All cases served by this function are inexact */
     256        9582 :     *recheck = true;
     257             : 
     258        9582 :     qqq = query->time + (query->zone * INT64CONST(1000000));
     259             : 
     260        9582 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     261        9582 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     262             : 
     263        9582 :     PG_RETURN_BOOL(
     264             :                    gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
     265             :         );
     266             : }
     267             : 
     268             : 
     269             : Datum
     270        1198 : gbt_time_union(PG_FUNCTION_ARGS)
     271             : {
     272        1198 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     273        1198 :     void       *out = palloc(sizeof(timeKEY));
     274             : 
     275        1198 :     *(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
     276        1198 :     PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
     277             : }
     278             : 
     279             : 
     280             : Datum
     281        2108 : gbt_time_penalty(PG_FUNCTION_ARGS)
     282             : {
     283        2108 :     timeKEY    *origentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     284        2108 :     timeKEY    *newentry = (timeKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     285        2108 :     float      *result = (float *) PG_GETARG_POINTER(2);
     286             :     Interval   *intr;
     287             :     double      res;
     288             :     double      res2;
     289             : 
     290        2108 :     intr = DatumGetIntervalP(DirectFunctionCall2(
     291             :                                                  time_mi_time,
     292             :                                                  TimeADTGetDatumFast(newentry->upper),
     293             :                                                  TimeADTGetDatumFast(origentry->upper)));
     294        2108 :     res = INTERVAL_TO_SEC(intr);
     295        2108 :     res = Max(res, 0);
     296             : 
     297        2108 :     intr = DatumGetIntervalP(DirectFunctionCall2(
     298             :                                                  time_mi_time,
     299             :                                                  TimeADTGetDatumFast(origentry->lower),
     300             :                                                  TimeADTGetDatumFast(newentry->lower)));
     301        2108 :     res2 = INTERVAL_TO_SEC(intr);
     302        2108 :     res2 = Max(res2, 0);
     303             : 
     304        2108 :     res += res2;
     305             : 
     306        2108 :     *result = 0.0;
     307             : 
     308        2108 :     if (res > 0)
     309             :     {
     310         926 :         intr = DatumGetIntervalP(DirectFunctionCall2(
     311             :                                                      time_mi_time,
     312             :                                                      TimeADTGetDatumFast(origentry->upper),
     313             :                                                      TimeADTGetDatumFast(origentry->lower)));
     314         926 :         *result += FLT_MIN;
     315         926 :         *result += (float) (res / (res + INTERVAL_TO_SEC(intr)));
     316         926 :         *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
     317             :     }
     318             : 
     319        2108 :     PG_RETURN_POINTER(result);
     320             : }
     321             : 
     322             : 
     323             : Datum
     324           8 : gbt_time_picksplit(PG_FUNCTION_ARGS)
     325             : {
     326           8 :     PG_RETURN_POINTER(gbt_num_picksplit(
     327             :                                         (GistEntryVector *) PG_GETARG_POINTER(0),
     328             :                                         (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
     329             :                                         &tinfo, fcinfo->flinfo
     330             :                                         ));
     331             : }
     332             : 
     333             : Datum
     334        1194 : gbt_time_same(PG_FUNCTION_ARGS)
     335             : {
     336        1194 :     timeKEY    *b1 = (timeKEY *) PG_GETARG_POINTER(0);
     337        1194 :     timeKEY    *b2 = (timeKEY *) PG_GETARG_POINTER(1);
     338        1194 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     339             : 
     340        1194 :     *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
     341        1194 :     PG_RETURN_POINTER(result);
     342             : }

Generated by: LCOV version 1.13