mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
7861d72ea2
uses of the long-deprecated float32 in contrib/seg; the definitions themselves are still there, but no longer used. fmgr/README updated to match. I added a CREATE FUNCTION to account for existing seg_center() code in seg.c too, and some tests for it and the neighbor functions. At the same time, remove checks for NULL which are not needed (because the functions are declared STRICT). I had to do some adjustments to contrib's btree_gist too. The choices for representation there are not ideal for changing the underlying types :-( Original patch by Zoltan Boszormenyi, with some adjustments by me.
255 lines
5.5 KiB
C
255 lines
5.5 KiB
C
#include "btree_gist.h"
|
|
#include "btree_utils_num.h"
|
|
#include "utils/date.h"
|
|
|
|
GISTENTRY *
|
|
gbt_num_compress(GISTENTRY *retval, GISTENTRY *entry, const gbtree_ninfo * tinfo)
|
|
{
|
|
|
|
if (entry->leafkey)
|
|
{
|
|
|
|
union
|
|
{
|
|
int16 i2;
|
|
int32 i4;
|
|
float4 f4;
|
|
DateADT dt;
|
|
} v;
|
|
|
|
GBT_NUMKEY *r = (GBT_NUMKEY *) palloc0(2 * tinfo->size);
|
|
void *leaf = NULL;
|
|
|
|
switch (tinfo->t)
|
|
{
|
|
case gbt_t_int2:
|
|
v.i2 = DatumGetInt16(entry->key);
|
|
leaf = &v.i2;
|
|
break;
|
|
case gbt_t_int4:
|
|
v.i4 = DatumGetInt32(entry->key);
|
|
leaf = &v.i4;
|
|
break;
|
|
case gbt_t_oid:
|
|
v.i4 = DatumGetObjectId(entry->key);
|
|
leaf = &v.i4;
|
|
break;
|
|
case gbt_t_date:
|
|
v.dt = DatumGetDateADT(entry->key);
|
|
leaf = &v.dt;
|
|
break;
|
|
case gbt_t_float4:
|
|
v.f4 = DatumGetFloat4(entry->key);
|
|
leaf = &v.f4;
|
|
break;
|
|
default:
|
|
leaf = DatumGetPointer(entry->key);
|
|
}
|
|
|
|
memcpy((void *) &r[0], leaf, tinfo->size);
|
|
memcpy((void *) &r[tinfo->size], leaf, tinfo->size);
|
|
retval = palloc(sizeof(GISTENTRY));
|
|
gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
|
|
entry->offset, FALSE);
|
|
}
|
|
else
|
|
retval = entry;
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
** The GiST union method for numerical values
|
|
*/
|
|
|
|
void *
|
|
gbt_num_union(GBT_NUMKEY * out, const GistEntryVector *entryvec, const gbtree_ninfo * tinfo)
|
|
{
|
|
int i,
|
|
numranges;
|
|
GBT_NUMKEY *cur;
|
|
GBT_NUMKEY_R o,
|
|
c;
|
|
|
|
numranges = entryvec->n;
|
|
cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[0].key));
|
|
|
|
|
|
o.lower = &((GBT_NUMKEY *) out)[0];
|
|
o.upper = &((GBT_NUMKEY *) out)[tinfo->size];
|
|
|
|
memcpy((void *) out, (void *) cur, 2 * tinfo->size);
|
|
|
|
for (i = 1; i < numranges; i++)
|
|
{
|
|
cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
|
|
c.lower = &cur[0];
|
|
c.upper = &cur[tinfo->size];
|
|
if ((*tinfo->f_gt) (o.lower, c.lower)) /* out->lower > cur->lower */
|
|
memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
|
|
if ((*tinfo->f_lt) (o.upper, c.upper)) /* out->upper < cur->upper */
|
|
memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** The GiST same method for numerical values
|
|
*/
|
|
|
|
bool
|
|
gbt_num_same(const GBT_NUMKEY * a, const GBT_NUMKEY * b, const gbtree_ninfo * tinfo)
|
|
{
|
|
|
|
GBT_NUMKEY_R b1,
|
|
b2;
|
|
|
|
b1.lower = &(((GBT_NUMKEY *) a)[0]);
|
|
b1.upper = &(((GBT_NUMKEY *) a)[tinfo->size]);
|
|
b2.lower = &(((GBT_NUMKEY *) b)[0]);
|
|
b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
|
|
|
|
if (
|
|
(*tinfo->f_eq) (b1.lower, b2.lower) &&
|
|
(*tinfo->f_eq) (b1.upper, b2.upper)
|
|
)
|
|
return TRUE;
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
void
|
|
gbt_num_bin_union(Datum *u, GBT_NUMKEY * e, const gbtree_ninfo * tinfo)
|
|
{
|
|
|
|
GBT_NUMKEY_R rd;
|
|
|
|
rd.lower = &e[0];
|
|
rd.upper = &e[tinfo->size];
|
|
|
|
if (!DatumGetPointer(*u))
|
|
{
|
|
*u = PointerGetDatum(palloc(2 * tinfo->size));
|
|
memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]), (void *) rd.lower, tinfo->size);
|
|
memcpy((void *) &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]), (void *) rd.upper, tinfo->size);
|
|
}
|
|
else
|
|
{
|
|
GBT_NUMKEY_R ur;
|
|
|
|
ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
|
|
ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
|
|
if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower))
|
|
memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
|
|
if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper))
|
|
memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** The GiST consistent method
|
|
*/
|
|
|
|
bool
|
|
gbt_num_consistent(
|
|
const GBT_NUMKEY_R * key,
|
|
const void *query,
|
|
const StrategyNumber *strategy,
|
|
bool is_leaf,
|
|
const gbtree_ninfo * tinfo
|
|
)
|
|
{
|
|
|
|
bool retval = FALSE;
|
|
|
|
switch (*strategy)
|
|
{
|
|
case BTLessEqualStrategyNumber:
|
|
retval = (*tinfo->f_ge) (query, key->lower);
|
|
break;
|
|
case BTLessStrategyNumber:
|
|
if (is_leaf)
|
|
retval = (*tinfo->f_gt) (query, key->lower);
|
|
else
|
|
retval = (*tinfo->f_ge) (query, key->lower);
|
|
break;
|
|
case BTEqualStrategyNumber:
|
|
if (is_leaf)
|
|
retval = (*tinfo->f_eq) (query, key->lower);
|
|
else
|
|
retval = (*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper);
|
|
break;
|
|
case BTGreaterStrategyNumber:
|
|
if (is_leaf)
|
|
retval = (*tinfo->f_lt) (query, key->upper);
|
|
else
|
|
retval = (*tinfo->f_le) (query, key->upper);
|
|
break;
|
|
case BTGreaterEqualStrategyNumber:
|
|
retval = (*tinfo->f_le) (query, key->upper);
|
|
break;
|
|
default:
|
|
retval = FALSE;
|
|
}
|
|
|
|
return (retval);
|
|
}
|
|
|
|
|
|
GIST_SPLITVEC *
|
|
gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
|
|
const gbtree_ninfo * tinfo)
|
|
{
|
|
OffsetNumber i,
|
|
maxoff = entryvec->n - 1;
|
|
Nsrt *arr;
|
|
int nbytes;
|
|
|
|
arr = (Nsrt *) palloc((maxoff + 1) * sizeof(Nsrt));
|
|
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
|
|
v->spl_left = (OffsetNumber *) palloc(nbytes);
|
|
v->spl_right = (OffsetNumber *) palloc(nbytes);
|
|
v->spl_ldatum = PointerGetDatum(0);
|
|
v->spl_rdatum = PointerGetDatum(0);
|
|
v->spl_nleft = 0;
|
|
v->spl_nright = 0;
|
|
|
|
/* Sort entries */
|
|
|
|
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
|
{
|
|
arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
|
|
arr[i].i = i;
|
|
}
|
|
qsort((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), tinfo->f_cmp);
|
|
|
|
/* We do simply create two parts */
|
|
|
|
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
|
|
{
|
|
if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
|
|
{
|
|
gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
|
|
v->spl_left[v->spl_nleft] = arr[i].i;
|
|
v->spl_nleft++;
|
|
}
|
|
else
|
|
{
|
|
gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
|
|
v->spl_right[v->spl_nright] = arr[i].i;
|
|
v->spl_nright++;
|
|
}
|
|
}
|
|
|
|
return v;
|
|
}
|