LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_numeric.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 86 89 96.6 %
Date: 2026-02-07 02:18:01 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.16