PostgreSQL/contrib/btree_gist/btree_numeric.c
Peter Eisentraut ff89e182d4 Add missing Datum conversions
Add various missing conversions from and to Datum.  The previous code
mostly relied on implicit conversions or its own explicit casts
instead of using the correct DatumGet*() or *GetDatum() functions.

We think these omissions are harmless.  Some actual bugs that were
discovered during this process have been committed
separately (80c758a2e1d, fd2ab03fea2).

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/flat/8246d7ff-f4b7-4363-913e-827dadfeb145%40eisentraut.org
2025-08-08 22:06:57 +02:00

253 lines
6.2 KiB
C

/*
* contrib/btree_gist/btree_numeric.c
*/
#include "postgres.h"
#include <math.h>
#include <float.h>
#include "btree_gist.h"
#include "btree_utils_var.h"
#include "utils/builtins.h"
#include "utils/numeric.h"
#include "utils/rel.h"
#include "utils/sortsupport.h"
/* GiST support functions */
PG_FUNCTION_INFO_V1(gbt_numeric_compress);
PG_FUNCTION_INFO_V1(gbt_numeric_union);
PG_FUNCTION_INFO_V1(gbt_numeric_picksplit);
PG_FUNCTION_INFO_V1(gbt_numeric_consistent);
PG_FUNCTION_INFO_V1(gbt_numeric_penalty);
PG_FUNCTION_INFO_V1(gbt_numeric_same);
PG_FUNCTION_INFO_V1(gbt_numeric_sortsupport);
/* define for comparison */
static bool
gbt_numeric_gt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
{
return DatumGetBool(DirectFunctionCall2(numeric_gt,
PointerGetDatum(a),
PointerGetDatum(b)));
}
static bool
gbt_numeric_ge(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
{
return DatumGetBool(DirectFunctionCall2(numeric_ge,
PointerGetDatum(a),
PointerGetDatum(b)));
}
static bool
gbt_numeric_eq(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
{
return DatumGetBool(DirectFunctionCall2(numeric_eq,
PointerGetDatum(a),
PointerGetDatum(b)));
}
static bool
gbt_numeric_le(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
{
return DatumGetBool(DirectFunctionCall2(numeric_le,
PointerGetDatum(a),
PointerGetDatum(b)));
}
static bool
gbt_numeric_lt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
{
return DatumGetBool(DirectFunctionCall2(numeric_lt,
PointerGetDatum(a),
PointerGetDatum(b)));
}
static int32
gbt_numeric_cmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
{
return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
PointerGetDatum(a),
PointerGetDatum(b)));
}
static const gbtree_vinfo tinfo =
{
gbt_t_numeric,
0,
false,
gbt_numeric_gt,
gbt_numeric_ge,
gbt_numeric_eq,
gbt_numeric_le,
gbt_numeric_lt,
gbt_numeric_cmp,
NULL
};
/**************************************************
* GiST support functions
**************************************************/
Datum
gbt_numeric_compress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
}
Datum
gbt_numeric_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
void *query = DatumGetNumeric(PG_GETARG_DATUM(1));
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
bool retval;
GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
GBT_VARKEY_R r = gbt_var_key_readable(key);
/* All cases served by this function are exact */
*recheck = false;
retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
PG_RETURN_BOOL(retval);
}
Datum
gbt_numeric_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int32 *size = (int *) PG_GETARG_POINTER(1);
PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
&tinfo, fcinfo->flinfo));
}
Datum
gbt_numeric_same(PG_FUNCTION_ARGS)
{
Datum d1 = PG_GETARG_DATUM(0);
Datum d2 = PG_GETARG_DATUM(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
PG_RETURN_POINTER(result);
}
Datum
gbt_numeric_penalty(PG_FUNCTION_ARGS)
{
GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
float *result = (float *) PG_GETARG_POINTER(2);
Numeric us,
os,
ds;
GBT_VARKEY *org = (GBT_VARKEY *) DatumGetPointer(o->key);
GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
Datum uni;
GBT_VARKEY_R rk,
ok,
uk;
rk = gbt_var_key_readable(org);
uni = PointerGetDatum(gbt_var_key_copy(&rk));
gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
ok = gbt_var_key_readable(org);
uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
us = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
PointerGetDatum(uk.upper),
PointerGetDatum(uk.lower)));
os = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
PointerGetDatum(ok.upper),
PointerGetDatum(ok.lower)));
ds = DatumGetNumeric(DirectFunctionCall2(numeric_sub,
NumericGetDatum(us),
NumericGetDatum(os)));
if (numeric_is_nan(us))
{
if (numeric_is_nan(os))
*result = 0.0;
else
*result = 1.0;
}
else
{
Numeric nul = int64_to_numeric(0);
*result = 0.0;
if (DatumGetBool(DirectFunctionCall2(numeric_gt, NumericGetDatum(ds), NumericGetDatum(nul))))
{
*result += FLT_MIN;
os = DatumGetNumeric(DirectFunctionCall2(numeric_div,
NumericGetDatum(ds),
NumericGetDatum(us)));
*result += (float4) DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, NumericGetDatum(os)));
}
}
if (*result > 0)
*result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1));
PG_RETURN_POINTER(result);
}
Datum
gbt_numeric_picksplit(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
&tinfo, fcinfo->flinfo);
PG_RETURN_POINTER(v);
}
static int
gbt_numeric_ssup_cmp(Datum x, Datum y, SortSupport ssup)
{
GBT_VARKEY *key1 = PG_DETOAST_DATUM(x);
GBT_VARKEY *key2 = PG_DETOAST_DATUM(y);
GBT_VARKEY_R arg1 = gbt_var_key_readable(key1);
GBT_VARKEY_R arg2 = gbt_var_key_readable(key2);
Datum result;
/* for leaf items we expect lower == upper, so only compare lower */
result = DirectFunctionCall2(numeric_cmp,
PointerGetDatum(arg1.lower),
PointerGetDatum(arg2.lower));
GBT_FREE_IF_COPY(key1, x);
GBT_FREE_IF_COPY(key2, y);
return DatumGetInt32(result);
}
Datum
gbt_numeric_sortsupport(PG_FUNCTION_ARGS)
{
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
ssup->comparator = gbt_numeric_ssup_cmp;
ssup->ssup_extra = NULL;
PG_RETURN_VOID();
}