postgresql/contrib/btree_gist/btree_utils_num.c
Teodor Sigaev 7b81988f9b - Add aligment of variable data types
- Add aligment for interval data types
- Avoid floating point overflow in penalty functions
Janko Richter <jankorichter@yahoo.de> and teodor
2004-06-03 12:26:10 +00:00

255 lines
6.9 KiB
C

#include "btree_gist.h"
#include "btree_utils_num.h"
#include "utils/date.h"
extern GISTENTRY *
gbt_num_compress( GISTENTRY *retval , GISTENTRY *entry , const gbtree_ninfo * tinfo )
{
if (entry->leafkey)
{
union {
int16 i2;
int32 i4;
TimeADT ts;
DateADT dt;
} v ;
GBT_NUMKEY *r = ( GBT_NUMKEY * ) palloc(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_time :
v.ts = DatumGetTimeADT(entry->key);
leaf = &v.ts;
break;
case gbt_t_date :
v.dt = DatumGetDateADT(entry->key);
leaf = &v.dt;
break;
default :
leaf = DatumGetPointer(entry->key);
}
memset ( (void*) &r[0] , 0 , 2*tinfo->size );
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,( 2 * tinfo->size ), FALSE);
} else
retval = entry;
return retval;
}
/*
** The GiST union method for numerical values
*/
extern 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
*/
extern 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;
}
extern 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
*/
extern 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[maxoff+1] ;
int nbytes ;
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;
}