1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-21 12:05:57 +03:00
postgres/contrib/btree_gist/btree_float8.c
Heikki Linnakangas e4309f73f6 Add support for sorted gist index builds to btree_gist
This enables sortsupport in the btree_gist extension for faster builds
of gist indexes.

Sorted gist index build strategy is the new default now. Regression
tests are unchanged (except for one small change in the 'enum' test to
add coverage for enum values added later) and are using the sorted
build strategy instead.

One version of this was committed a long time ago already, in commit
9f984ba6d2, but it was quickly reverted because of buildfarm
failures. The failures were presumably caused by some small bugs, but
we never got around to debug and commit it again. This patch was
written from scratch, implementing the same idea, with some fragments
and ideas from the original patch.

Author: Bernd Helmle <mailings@oopsware.de>
Author: Andrey Borodin <x4mmm@yandex-team.ru>
Discussion: https://www.postgresql.org/message-id/64d324ce2a6d535d3f0f3baeeea7b25beff82ce4.camel@oopsware.de
2025-04-03 13:46:35 +03:00

238 lines
5.6 KiB
C

/*
* contrib/btree_gist/btree_float8.c
*/
#include "postgres.h"
#include "btree_gist.h"
#include "btree_utils_num.h"
#include "utils/float.h"
#include "utils/sortsupport.h"
typedef struct float8key
{
float8 lower;
float8 upper;
} float8KEY;
/* GiST support functions */
PG_FUNCTION_INFO_V1(gbt_float8_compress);
PG_FUNCTION_INFO_V1(gbt_float8_fetch);
PG_FUNCTION_INFO_V1(gbt_float8_union);
PG_FUNCTION_INFO_V1(gbt_float8_picksplit);
PG_FUNCTION_INFO_V1(gbt_float8_consistent);
PG_FUNCTION_INFO_V1(gbt_float8_distance);
PG_FUNCTION_INFO_V1(gbt_float8_penalty);
PG_FUNCTION_INFO_V1(gbt_float8_same);
PG_FUNCTION_INFO_V1(gbt_float8_sortsupport);
static bool
gbt_float8gt(const void *a, const void *b, FmgrInfo *flinfo)
{
return (*((const float8 *) a) > *((const float8 *) b));
}
static bool
gbt_float8ge(const void *a, const void *b, FmgrInfo *flinfo)
{
return (*((const float8 *) a) >= *((const float8 *) b));
}
static bool
gbt_float8eq(const void *a, const void *b, FmgrInfo *flinfo)
{
return (*((const float8 *) a) == *((const float8 *) b));
}
static bool
gbt_float8le(const void *a, const void *b, FmgrInfo *flinfo)
{
return (*((const float8 *) a) <= *((const float8 *) b));
}
static bool
gbt_float8lt(const void *a, const void *b, FmgrInfo *flinfo)
{
return (*((const float8 *) a) < *((const float8 *) b));
}
static int
gbt_float8key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
{
float8KEY *ia = (float8KEY *) (((const Nsrt *) a)->t);
float8KEY *ib = (float8KEY *) (((const Nsrt *) b)->t);
if (ia->lower == ib->lower)
{
if (ia->upper == ib->upper)
return 0;
return (ia->upper > ib->upper) ? 1 : -1;
}
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_float8_dist(const void *a, const void *b, FmgrInfo *flinfo)
{
float8 arg1 = *(const float8 *) a;
float8 arg2 = *(const float8 *) b;
float8 r;
r = arg1 - arg2;
if (unlikely(isinf(r)) && !isinf(arg1) && !isinf(arg2))
float_overflow_error();
return fabs(r);
}
static const gbtree_ninfo tinfo =
{
gbt_t_float8,
sizeof(float8),
16, /* sizeof(gbtreekey16) */
gbt_float8gt,
gbt_float8ge,
gbt_float8eq,
gbt_float8le,
gbt_float8lt,
gbt_float8key_cmp,
gbt_float8_dist
};
PG_FUNCTION_INFO_V1(float8_dist);
Datum
float8_dist(PG_FUNCTION_ARGS)
{
float8 a = PG_GETARG_FLOAT8(0);
float8 b = PG_GETARG_FLOAT8(1);
float8 r;
r = a - b;
if (unlikely(isinf(r)) && !isinf(a) && !isinf(b))
float_overflow_error();
PG_RETURN_FLOAT8(fabs(r));
}
/**************************************************
* GiST support functions
**************************************************/
Datum
gbt_float8_compress(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
}
Datum
gbt_float8_fetch(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
}
Datum
gbt_float8_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
float8 query = PG_GETARG_FLOAT8(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
float8KEY *kkk = (float8KEY *) DatumGetPointer(entry->key);
GBT_NUMKEY_R key;
/* All cases served by this function are exact */
*recheck = false;
key.lower = (GBT_NUMKEY *) &kkk->lower;
key.upper = (GBT_NUMKEY *) &kkk->upper;
PG_RETURN_BOOL(gbt_num_consistent(&key, &query, &strategy,
GIST_LEAF(entry), &tinfo,
fcinfo->flinfo));
}
Datum
gbt_float8_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
float8 query = PG_GETARG_FLOAT8(1);
/* Oid subtype = PG_GETARG_OID(3); */
float8KEY *kkk = (float8KEY *) DatumGetPointer(entry->key);
GBT_NUMKEY_R key;
key.lower = (GBT_NUMKEY *) &kkk->lower;
key.upper = (GBT_NUMKEY *) &kkk->upper;
PG_RETURN_FLOAT8(gbt_num_distance(&key, &query, GIST_LEAF(entry),
&tinfo, fcinfo->flinfo));
}
Datum
gbt_float8_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
void *out = palloc(sizeof(float8KEY));
*(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
PG_RETURN_POINTER(gbt_num_union(out, entryvec, &tinfo, fcinfo->flinfo));
}
Datum
gbt_float8_penalty(PG_FUNCTION_ARGS)
{
float8KEY *origentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
float8KEY *newentry = (float8KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
float *result = (float *) PG_GETARG_POINTER(2);
penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper);
PG_RETURN_POINTER(result);
}
Datum
gbt_float8_picksplit(PG_FUNCTION_ARGS)
{
PG_RETURN_POINTER(gbt_num_picksplit((GistEntryVector *) PG_GETARG_POINTER(0),
(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
&tinfo, fcinfo->flinfo));
}
Datum
gbt_float8_same(PG_FUNCTION_ARGS)
{
float8KEY *b1 = (float8KEY *) PG_GETARG_POINTER(0);
float8KEY *b2 = (float8KEY *) PG_GETARG_POINTER(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
PG_RETURN_POINTER(result);
}
static int
gbt_float8_ssup_cmp(Datum x, Datum y, SortSupport ssup)
{
float8KEY *arg1 = (float8KEY *) DatumGetPointer(x);
float8KEY *arg2 = (float8KEY *) DatumGetPointer(y);
/* for leaf items we expect lower == upper, so only compare lower */
return float8_cmp_internal(arg1->lower, arg2->lower);
}
Datum
gbt_float8_sortsupport(PG_FUNCTION_ARGS)
{
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
ssup->comparator = gbt_float8_ssup_cmp;
ssup->ssup_extra = NULL;
PG_RETURN_VOID();
}