LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_interval.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 81.8 % 110 90
Test Date: 2026-07-03 19:57:34 Functions: 93.8 % 32 30
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 75.0 % 8 6

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * contrib/btree_gist/btree_interval.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/rel.h"
      10                 :             : #include "utils/sortsupport.h"
      11                 :             : #include "utils/timestamp.h"
      12                 :             : 
      13                 :             : typedef struct
      14                 :             : {
      15                 :             :     Interval    lower,
      16                 :             :                 upper;
      17                 :             : } intvKEY;
      18                 :             : 
      19                 :             : /* GiST support functions */
      20                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_compress);
      21                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_fetch);
      22                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_decompress);
      23                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_union);
      24                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
      25                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_consistent);
      26                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_distance);
      27                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_penalty);
      28                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_same);
      29                 :           4 : PG_FUNCTION_INFO_V1(gbt_intv_sortsupport);
      30                 :             : 
      31                 :             : 
      32                 :             : static bool
      33                 :        2093 : gbt_intvgt(const void *a, const void *b, FmgrInfo *flinfo)
      34                 :             : {
      35                 :        2093 :     return DatumGetBool(DirectFunctionCall2(interval_gt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
      36                 :             : }
      37                 :             : 
      38                 :             : static bool
      39                 :         375 : gbt_intvge(const void *a, const void *b, FmgrInfo *flinfo)
      40                 :             : {
      41                 :         375 :     return DatumGetBool(DirectFunctionCall2(interval_ge, IntervalPGetDatum(a), IntervalPGetDatum(b)));
      42                 :             : }
      43                 :             : 
      44                 :             : static bool
      45                 :         150 : gbt_intveq(const void *a, const void *b, FmgrInfo *flinfo)
      46                 :             : {
      47                 :         150 :     return DatumGetBool(DirectFunctionCall2(interval_eq, IntervalPGetDatum(a), IntervalPGetDatum(b)));
      48                 :             : }
      49                 :             : 
      50                 :             : static bool
      51                 :         770 : gbt_intvle(const void *a, const void *b, FmgrInfo *flinfo)
      52                 :             : {
      53                 :         770 :     return DatumGetBool(DirectFunctionCall2(interval_le, IntervalPGetDatum(a), IntervalPGetDatum(b)));
      54                 :             : }
      55                 :             : 
      56                 :             : static bool
      57                 :        2243 : gbt_intvlt(const void *a, const void *b, FmgrInfo *flinfo)
      58                 :             : {
      59                 :        2243 :     return DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
      60                 :             : }
      61                 :             : 
      62                 :             : static int
      63                 :        1197 : gbt_intvkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
      64                 :             : {
      65                 :        1197 :     intvKEY    *ia = (intvKEY *) (((const Nsrt *) a)->t);
      66                 :        1197 :     intvKEY    *ib = (intvKEY *) (((const Nsrt *) b)->t);
      67                 :             :     int         res;
      68                 :             : 
      69                 :        1197 :     res = DatumGetInt32(DirectFunctionCall2(interval_cmp, IntervalPGetDatum(&ia->lower), IntervalPGetDatum(&ib->lower)));
      70         [ -  + ]:        1197 :     if (res == 0)
      71                 :           0 :         return DatumGetInt32(DirectFunctionCall2(interval_cmp, IntervalPGetDatum(&ia->upper), IntervalPGetDatum(&ib->upper)));
      72                 :             : 
      73                 :        1197 :     return res;
      74                 :             : }
      75                 :             : 
      76                 :             : 
      77                 :             : static double
      78                 :         612 : intr2num(const Interval *i)
      79                 :             : {
      80                 :         612 :     return INTERVAL_TO_SEC(i);
      81                 :             : }
      82                 :             : 
      83                 :             : static float8
      84                 :         306 : gbt_intv_dist(const void *a, const void *b, FmgrInfo *flinfo)
      85                 :             : {
      86                 :         306 :     return fabs(intr2num((const Interval *) a) - intr2num((const Interval *) b));
      87                 :             : }
      88                 :             : 
      89                 :             : /*
      90                 :             :  * INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
      91                 :             :  * in pg_type.  This might be less than sizeof(Interval) if the compiler
      92                 :             :  * insists on adding alignment padding at the end of the struct.  (Note:
      93                 :             :  * this concern is obsolete with the current definition of Interval, but
      94                 :             :  * was real before a separate "day" field was added to it.)
      95                 :             :  */
      96                 :             : #define INTERVALSIZE 16
      97                 :             : 
      98                 :             : static const gbtree_ninfo tinfo =
      99                 :             : {
     100                 :             :     gbt_t_intv,
     101                 :             :     sizeof(Interval),
     102                 :             :     32,                         /* sizeof(gbtreekey32) */
     103                 :             :     gbt_intvgt,
     104                 :             :     gbt_intvge,
     105                 :             :     gbt_intveq,
     106                 :             :     gbt_intvle,
     107                 :             :     gbt_intvlt,
     108                 :             :     gbt_intvkey_cmp,
     109                 :             :     gbt_intv_dist
     110                 :             : };
     111                 :             : 
     112                 :             : 
     113                 :             : Interval *
     114                 :        2234 : abs_interval(Interval *a)
     115                 :             : {
     116                 :             :     static const Interval zero = {0, 0, 0};
     117                 :             : 
     118         [ +  + ]:        2234 :     if (DatumGetBool(DirectFunctionCall2(interval_lt,
     119                 :             :                                          IntervalPGetDatum(a),
     120                 :             :                                          IntervalPGetDatum(&zero))))
     121                 :        1239 :         a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
     122                 :             :                                                   IntervalPGetDatum(a)));
     123                 :             : 
     124                 :        2234 :     return a;
     125                 :             : }
     126                 :             : 
     127                 :           4 : PG_FUNCTION_INFO_V1(interval_dist);
     128                 :             : Datum
     129                 :         606 : interval_dist(PG_FUNCTION_ARGS)
     130                 :             : {
     131                 :         606 :     Datum       diff = DirectFunctionCall2(interval_mi,
     132                 :             :                                            PG_GETARG_DATUM(0),
     133                 :             :                                            PG_GETARG_DATUM(1));
     134                 :             : 
     135                 :         606 :     PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
     136                 :             : }
     137                 :             : 
     138                 :             : 
     139                 :             : /**************************************************
     140                 :             :  * GiST support functions
     141                 :             :  **************************************************/
     142                 :             : 
     143                 :             : Datum
     144                 :         604 : gbt_intv_compress(PG_FUNCTION_ARGS)
     145                 :             : {
     146                 :         604 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     147                 :         604 :     GISTENTRY  *retval = entry;
     148                 :             : 
     149         [ +  + ]:         604 :     if (entry->leafkey || INTERVALSIZE != sizeof(Interval))
     150                 :             :     {
     151                 :         600 :         char       *r = (char *) palloc(2 * INTERVALSIZE);
     152                 :             : 
     153                 :         600 :         retval = palloc_object(GISTENTRY);
     154                 :             : 
     155         [ +  - ]:         600 :         if (entry->leafkey)
     156                 :             :         {
     157                 :         600 :             Interval   *key = DatumGetIntervalP(entry->key);
     158                 :             : 
     159                 :         600 :             memcpy(r, key, INTERVALSIZE);
     160                 :         600 :             memcpy(r + INTERVALSIZE, key, INTERVALSIZE);
     161                 :             :         }
     162                 :             :         else
     163                 :             :         {
     164                 :           0 :             intvKEY    *key = (intvKEY *) DatumGetPointer(entry->key);
     165                 :             : 
     166                 :           0 :             memcpy(r, &key->lower, INTERVALSIZE);
     167                 :           0 :             memcpy(r + INTERVALSIZE, &key->upper, INTERVALSIZE);
     168                 :             :         }
     169                 :         600 :         gistentryinit(*retval, PointerGetDatum(r),
     170                 :             :                       entry->rel, entry->page,
     171                 :             :                       entry->offset, false);
     172                 :             :     }
     173                 :             : 
     174                 :         604 :     PG_RETURN_POINTER(retval);
     175                 :             : }
     176                 :             : 
     177                 :             : Datum
     178                 :        1351 : gbt_intv_fetch(PG_FUNCTION_ARGS)
     179                 :             : {
     180                 :        1351 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     181                 :             : 
     182                 :        1351 :     PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
     183                 :             : }
     184                 :             : 
     185                 :             : Datum
     186                 :        4378 : gbt_intv_decompress(PG_FUNCTION_ARGS)
     187                 :             : {
     188                 :        4378 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     189                 :        4378 :     GISTENTRY  *retval = entry;
     190                 :             : 
     191                 :             :     if (INTERVALSIZE != sizeof(Interval))
     192                 :             :     {
     193                 :             :         intvKEY    *r = palloc_object(intvKEY);
     194                 :             :         char       *key = DatumGetPointer(entry->key);
     195                 :             : 
     196                 :             :         retval = palloc_object(GISTENTRY);
     197                 :             :         memcpy(&r->lower, key, INTERVALSIZE);
     198                 :             :         memcpy(&r->upper, key + INTERVALSIZE, INTERVALSIZE);
     199                 :             : 
     200                 :             :         gistentryinit(*retval, PointerGetDatum(r),
     201                 :             :                       entry->rel, entry->page,
     202                 :             :                       entry->offset, false);
     203                 :             :     }
     204                 :        4378 :     PG_RETURN_POINTER(retval);
     205                 :             : }
     206                 :             : 
     207                 :             : 
     208                 :             : Datum
     209                 :        1670 : gbt_intv_consistent(PG_FUNCTION_ARGS)
     210                 :             : {
     211                 :        1670 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     212                 :        1670 :     Interval   *query = PG_GETARG_INTERVAL_P(1);
     213                 :        1670 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     214                 :             : #ifdef NOT_USED
     215                 :             :     Oid         subtype = PG_GETARG_OID(3);
     216                 :             : #endif
     217                 :        1670 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     218                 :        1670 :     intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
     219                 :             :     GBT_NUMKEY_R key;
     220                 :             : 
     221                 :             :     /* All cases served by this function are exact */
     222                 :        1670 :     *recheck = false;
     223                 :             : 
     224                 :        1670 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     225                 :        1670 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     226                 :             : 
     227                 :        1670 :     PG_RETURN_BOOL(gbt_num_consistent(&key, query, strategy,
     228                 :             :                                       GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
     229                 :             : }
     230                 :             : 
     231                 :             : 
     232                 :             : Datum
     233                 :         308 : gbt_intv_distance(PG_FUNCTION_ARGS)
     234                 :             : {
     235                 :         308 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     236                 :         308 :     Interval   *query = PG_GETARG_INTERVAL_P(1);
     237                 :             : #ifdef NOT_USED
     238                 :             :     Oid         subtype = PG_GETARG_OID(3);
     239                 :             : #endif
     240                 :         308 :     intvKEY    *kkk = (intvKEY *) DatumGetPointer(entry->key);
     241                 :             :     GBT_NUMKEY_R key;
     242                 :             : 
     243                 :         308 :     key.lower = (GBT_NUMKEY *) &kkk->lower;
     244                 :         308 :     key.upper = (GBT_NUMKEY *) &kkk->upper;
     245                 :             : 
     246                 :         308 :     PG_RETURN_FLOAT8(gbt_num_distance(&key, query, GIST_LEAF(entry),
     247                 :             :                                       &tinfo, fcinfo->flinfo));
     248                 :             : }
     249                 :             : 
     250                 :             : 
     251                 :             : Datum
     252                 :           1 : gbt_intv_union(PG_FUNCTION_ARGS)
     253                 :             : {
     254                 :           1 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     255                 :           1 :     void       *out = palloc(sizeof(intvKEY));
     256                 :             : 
     257                 :           1 :     *(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
     258                 :           1 :     PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
     259                 :             : }
     260                 :             : 
     261                 :             : 
     262                 :             : Datum
     263                 :           0 : gbt_intv_penalty(PG_FUNCTION_ARGS)
     264                 :             : {
     265                 :           0 :     intvKEY    *origentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
     266                 :           0 :     intvKEY    *newentry = (intvKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
     267                 :           0 :     float      *result = (float *) PG_GETARG_POINTER(2);
     268                 :             :     double      iorg[2],
     269                 :             :                 inew[2];
     270                 :             : 
     271                 :           0 :     iorg[0] = intr2num(&origentry->lower);
     272                 :           0 :     iorg[1] = intr2num(&origentry->upper);
     273                 :           0 :     inew[0] = intr2num(&newentry->lower);
     274                 :           0 :     inew[1] = intr2num(&newentry->upper);
     275                 :             : 
     276                 :           0 :     penalty_num(result, iorg[0], iorg[1], inew[0], inew[1]);
     277                 :             : 
     278                 :           0 :     PG_RETURN_POINTER(result);
     279                 :             : }
     280                 :             : 
     281                 :             : Datum
     282                 :           3 : gbt_intv_picksplit(PG_FUNCTION_ARGS)
     283                 :             : {
     284                 :           3 :     PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
     285                 :             :                                         (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
     286                 :             :                                         &tinfo, fcinfo->flinfo));
     287                 :             : }
     288                 :             : 
     289                 :             : Datum
     290                 :           0 : gbt_intv_same(PG_FUNCTION_ARGS)
     291                 :             : {
     292                 :           0 :     intvKEY    *b1 = (intvKEY *) PG_GETARG_POINTER(0);
     293                 :           0 :     intvKEY    *b2 = (intvKEY *) PG_GETARG_POINTER(1);
     294                 :           0 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     295                 :             : 
     296                 :           0 :     *result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
     297                 :           0 :     PG_RETURN_POINTER(result);
     298                 :             : }
     299                 :             : 
     300                 :             : static int
     301                 :        5676 : gbt_intv_ssup_cmp(Datum x, Datum y, SortSupport ssup)
     302                 :             : {
     303                 :        5676 :     intvKEY    *arg1 = (intvKEY *) DatumGetPointer(x);
     304                 :        5676 :     intvKEY    *arg2 = (intvKEY *) DatumGetPointer(y);
     305                 :             : 
     306                 :             :     /* for leaf items we expect lower == upper, so only compare lower */
     307                 :        5676 :     return DatumGetInt32(DirectFunctionCall2(interval_cmp,
     308                 :             :                                              IntervalPGetDatum(&arg1->lower),
     309                 :             :                                              IntervalPGetDatum(&arg2->lower)));
     310                 :             : }
     311                 :             : 
     312                 :             : Datum
     313                 :           1 : gbt_intv_sortsupport(PG_FUNCTION_ARGS)
     314                 :             : {
     315                 :           1 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     316                 :             : 
     317                 :           1 :     ssup->comparator = gbt_intv_ssup_cmp;
     318                 :           1 :     ssup->ssup_extra = NULL;
     319                 :             : 
     320                 :           1 :     PG_RETURN_VOID();
     321                 :             : }
        

Generated by: LCOV version 2.0-1