LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_numeric.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.6 % 89 86
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 21 21
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 75.0 % 12 9

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * contrib/btree_gist/btree_numeric.c
       3                 :             :  *
       4                 :             :  * Support for numeric data type.
       5                 :             :  */
       6                 :             : #include "postgres.h"
       7                 :             : 
       8                 :             : #include <float.h>
       9                 :             : 
      10                 :             : #include "btree_gist.h"
      11                 :             : #include "btree_utils_var.h"
      12                 :             : #include "utils/builtins.h"
      13                 :             : #include "utils/numeric.h"
      14                 :             : #include "utils/rel.h"
      15                 :             : #include "utils/sortsupport.h"
      16                 :             : 
      17                 :             : /* GiST support functions */
      18                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_compress);
      19                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_union);
      20                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_picksplit);
      21                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_consistent);
      22                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_penalty);
      23                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_same);
      24                 :           5 : PG_FUNCTION_INFO_V1(gbt_numeric_sortsupport);
      25                 :             : 
      26                 :             : 
      27                 :             : /* define for comparison */
      28                 :             : 
      29                 :             : static bool
      30                 :        1695 : gbt_numeric_gt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
      31                 :             : {
      32                 :        1695 :     return DatumGetBool(DirectFunctionCall2(numeric_gt,
      33                 :             :                                             PointerGetDatum(a),
      34                 :             :                                             PointerGetDatum(b)));
      35                 :             : }
      36                 :             : 
      37                 :             : static bool
      38                 :        1965 : gbt_numeric_ge(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
      39                 :             : {
      40                 :        1965 :     return DatumGetBool(DirectFunctionCall2(numeric_ge,
      41                 :             :                                             PointerGetDatum(a),
      42                 :             :                                             PointerGetDatum(b)));
      43                 :             : }
      44                 :             : 
      45                 :             : static bool
      46                 :         567 : gbt_numeric_eq(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
      47                 :             : {
      48                 :         567 :     return DatumGetBool(DirectFunctionCall2(numeric_eq,
      49                 :             :                                             PointerGetDatum(a),
      50                 :             :                                             PointerGetDatum(b)));
      51                 :             : }
      52                 :             : 
      53                 :             : static bool
      54                 :        2198 : gbt_numeric_le(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
      55                 :             : {
      56                 :        2198 :     return DatumGetBool(DirectFunctionCall2(numeric_le,
      57                 :             :                                             PointerGetDatum(a),
      58                 :             :                                             PointerGetDatum(b)));
      59                 :             : }
      60                 :             : 
      61                 :             : static bool
      62                 :        2185 : gbt_numeric_lt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
      63                 :             : {
      64                 :        2185 :     return DatumGetBool(DirectFunctionCall2(numeric_lt,
      65                 :             :                                             PointerGetDatum(a),
      66                 :             :                                             PointerGetDatum(b)));
      67                 :             : }
      68                 :             : 
      69                 :             : static int32
      70                 :       43544 : gbt_numeric_cmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
      71                 :             : {
      72                 :       43544 :     return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
      73                 :             :                                              PointerGetDatum(a),
      74                 :             :                                              PointerGetDatum(b)));
      75                 :             : }
      76                 :             : 
      77                 :             : 
      78                 :             : /*
      79                 :             :  * We could conceivably support internal-key truncation here, but it would
      80                 :             :  * require custom truncation code, and most values wouldn't be long enough
      81                 :             :  * to make it worthwhile.
      82                 :             :  */
      83                 :             : static const gbtree_vinfo tinfo =
      84                 :             : {
      85                 :             :     gbt_t_numeric,
      86                 :             :     false,                      /* no truncation permitted */
      87                 :             :     gbt_numeric_gt,
      88                 :             :     gbt_numeric_ge,
      89                 :             :     gbt_numeric_eq,
      90                 :             :     gbt_numeric_le,
      91                 :             :     gbt_numeric_lt,
      92                 :             :     gbt_numeric_cmp,
      93                 :             :     NULL
      94                 :             : };
      95                 :             : 
      96                 :             : 
      97                 :             : /**************************************************
      98                 :             :  * GiST support functions
      99                 :             :  **************************************************/
     100                 :             : 
     101                 :             : Datum
     102                 :        3154 : gbt_numeric_compress(PG_FUNCTION_ARGS)
     103                 :             : {
     104                 :        3154 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     105                 :             : 
     106                 :        3154 :     PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
     107                 :             : }
     108                 :             : 
     109                 :             : Datum
     110                 :        8729 : gbt_numeric_consistent(PG_FUNCTION_ARGS)
     111                 :             : {
     112                 :        8729 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     113                 :        8729 :     void       *query = DatumGetNumeric(PG_GETARG_DATUM(1));
     114                 :        8729 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     115                 :             : #ifdef NOT_USED
     116                 :             :     Oid         subtype = PG_GETARG_OID(3);
     117                 :             : #endif
     118                 :        8729 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     119                 :             :     bool        retval;
     120                 :        8729 :     GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
     121                 :        8729 :     GBT_VARKEY_R r = gbt_var_key_readable(key);
     122                 :             : 
     123                 :             :     /* All cases served by this function are exact */
     124                 :        8729 :     *recheck = false;
     125                 :             : 
     126                 :       17458 :     retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
     127                 :        8729 :                                 GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
     128                 :        8729 :     PG_RETURN_BOOL(retval);
     129                 :             : }
     130                 :             : 
     131                 :             : Datum
     132                 :        1859 : gbt_numeric_union(PG_FUNCTION_ARGS)
     133                 :             : {
     134                 :        1859 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     135                 :        1859 :     int32      *size = (int *) PG_GETARG_POINTER(1);
     136                 :             : 
     137                 :        1859 :     PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
     138                 :             :                                     &tinfo, fcinfo->flinfo));
     139                 :             : }
     140                 :             : 
     141                 :             : Datum
     142                 :        1814 : gbt_numeric_same(PG_FUNCTION_ARGS)
     143                 :             : {
     144                 :        1814 :     Datum       d1 = PG_GETARG_DATUM(0);
     145                 :        1814 :     Datum       d2 = PG_GETARG_DATUM(1);
     146                 :        1814 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     147                 :             : 
     148                 :        1814 :     *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
     149                 :        1814 :     PG_RETURN_POINTER(result);
     150                 :             : }
     151                 :             : 
     152                 :             : Datum
     153                 :        3494 : gbt_numeric_penalty(PG_FUNCTION_ARGS)
     154                 :             : {
     155                 :        3494 :     GISTENTRY  *o = (GISTENTRY *) PG_GETARG_POINTER(0);
     156                 :        3494 :     GISTENTRY  *n = (GISTENTRY *) PG_GETARG_POINTER(1);
     157                 :        3494 :     float      *result = (float *) PG_GETARG_POINTER(2);
     158                 :             : 
     159                 :             :     Numeric     us,
     160                 :             :                 os,
     161                 :             :                 ds;
     162                 :             : 
     163                 :        3494 :     GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
     164                 :        3494 :     GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
     165                 :             :     Datum       uni;
     166                 :             :     GBT_VARKEY_R rk,
     167                 :             :                 ok,
     168                 :             :                 uk;
     169                 :             : 
     170                 :        3494 :     rk = gbt_var_key_readable(org);
     171                 :        3494 :     uni = PointerGetDatum(gbt_var_key_copy(&rk));
     172                 :        3494 :     gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
     173                 :        3494 :     ok = gbt_var_key_readable(org);
     174                 :        3494 :     uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
     175                 :             : 
     176                 :        3494 :     us = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
     177                 :             :                                              PointerGetDatum(uk.upper),
     178                 :             :                                              PointerGetDatum(uk.lower)));
     179                 :             : 
     180                 :        3494 :     os = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
     181                 :             :                                              PointerGetDatum(ok.upper),
     182                 :             :                                              PointerGetDatum(ok.lower)));
     183                 :             : 
     184                 :        3494 :     ds = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
     185                 :             :                                              NumericGetDatum(us),
     186                 :             :                                              NumericGetDatum(os)));
     187                 :             : 
     188         [ -  + ]:        3494 :     if (numeric_is_nan(us))
     189                 :             :     {
     190         [ #  # ]:           0 :         if (numeric_is_nan(os))
     191                 :           0 :             *result = 0.0;
     192                 :             :         else
     193                 :           0 :             *result = 1.0;
     194                 :             :     }
     195                 :             :     else
     196                 :             :     {
     197                 :        3494 :         Numeric     nul = int64_to_numeric(0);
     198                 :             : 
     199                 :        3494 :         *result = 0.0;
     200                 :             : 
     201         [ +  + ]:        3494 :         if (DatumGetBool(DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul))))
     202                 :             :         {
     203                 :          14 :             *result += FLT_MIN;
     204                 :          14 :             os = DatumGetNumeric(DirectFunctionCall2(numeric_div,
     205                 :             :                                                      NumericGetDatum(ds),
     206                 :             :                                                      NumericGetDatum(us)));
     207                 :          14 :             *result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
     208                 :             :         }
     209                 :             :     }
     210                 :             : 
     211         [ +  + ]:        3494 :     if (*result > 0)
     212                 :          14 :         *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
     213                 :             : 
     214                 :        3494 :     PG_RETURN_POINTER(result);
     215                 :             : }
     216                 :             : 
     217                 :             : Datum
     218                 :          24 : gbt_numeric_picksplit(PG_FUNCTION_ARGS)
     219                 :             : {
     220                 :          24 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     221                 :          24 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     222                 :             : 
     223                 :          24 :     gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
     224                 :             :                       &tinfo, fcinfo->flinfo);
     225                 :          24 :     PG_RETURN_POINTER(v);
     226                 :             : }
     227                 :             : 
     228                 :             : static int
     229                 :       11514 : gbt_numeric_ssup_cmp(Datum x, Datum y, SortSupport ssup)
     230                 :             : {
     231                 :       11514 :     GBT_VARKEY *key1 = PG_DETOAST_DATUM(x);
     232                 :       11514 :     GBT_VARKEY *key2 = PG_DETOAST_DATUM(y);
     233                 :             : 
     234                 :       11514 :     GBT_VARKEY_R arg1 = gbt_var_key_readable(key1);
     235                 :       11514 :     GBT_VARKEY_R arg2 = gbt_var_key_readable(key2);
     236                 :             :     Datum       result;
     237                 :             : 
     238                 :             :     /* for leaf items we expect lower == upper, so only compare lower */
     239                 :       11514 :     result = DirectFunctionCall2(numeric_cmp,
     240                 :             :                                  PointerGetDatum(arg1.lower),
     241                 :             :                                  PointerGetDatum(arg2.lower));
     242                 :             : 
     243         [ +  + ]:       11514 :     GBT_FREE_IF_COPY(key1, x);
     244         [ +  + ]:       11514 :     GBT_FREE_IF_COPY(key2, y);
     245                 :             : 
     246                 :       11514 :     return DatumGetInt32(result);
     247                 :             : }
     248                 :             : 
     249                 :             : Datum
     250                 :           2 : gbt_numeric_sortsupport(PG_FUNCTION_ARGS)
     251                 :             : {
     252                 :           2 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     253                 :             : 
     254                 :           2 :     ssup->comparator = gbt_numeric_ssup_cmp;
     255                 :           2 :     ssup->ssup_extra = NULL;
     256                 :             : 
     257                 :           2 :     PG_RETURN_VOID();
     258                 :             : }
        

Generated by: LCOV version 2.0-1