postgresql/contrib/btree_gist/btree_numeric.c
Peter Eisentraut 2eb4a831e5 Change TRUE/FALSE to true/false
The lower case spellings are C and C++ standard and are used in most
parts of the PostgreSQL sources.  The upper case spellings are only used
in some files/modules.  So standardize on the standard spellings.

The APIs for ICU, Perl, and Windows define their own TRUE and FALSE, so
those are left as is when using those APIs.

In code comments, we use the lower-case spelling for the C concepts and
keep the upper-case spelling for the SQL concepts.

Reviewed-by: Michael Paquier <michael.paquier@gmail.com>
2017-11-08 11:37:28 -05:00

239 lines
5.5 KiB
C

/*
* contrib/btree_gist/btree_numeric.c
*/
#include "postgres.h"
#include "btree_gist.h"
#include <math.h>
#include <float.h>
#include "btree_utils_var.h"
#include "utils/builtins.h"
#include "utils/numeric.h"
#include "utils/rel.h"
/*
** Bytea ops
*/
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);
/* 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
};
/**************************************************
* Text ops
**************************************************/
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 = (void *) 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 = DatumGetNumeric(DirectFunctionCall1(int4_numeric, Int32GetDatum(0)));
*result = 0.0;
if (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);
}