#include "btree_gist.h" #define __DEFINE_BTREE_TYPE_HERE__ 1 typedef struct __BTREE_GIST_TYPE__key { __BTREE_GIST_TYPE__ lower; __BTREE_GIST_TYPE__ upper; } __BTREE_GIST_TYPE__KEY; /* ** __BTREE_GIST_TYPE__key in/out */ PG_FUNCTION_INFO_V1(__BTREE_GIST_TYPE2__key_in); PG_FUNCTION_INFO_V1(__BTREE_GIST_TYPE2__key_out); Datum __BTREE_GIST_TYPE2__key_in(PG_FUNCTION_ARGS); Datum __BTREE_GIST_TYPE2__key_out(PG_FUNCTION_ARGS); /* ** __BTREE_GIST_TYPE__ ops */ PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___compress); PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___union); PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___picksplit); PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___consistent); PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___penalty); PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___same); Datum g__BTREE_GIST_TYPE2___compress(PG_FUNCTION_ARGS); Datum g__BTREE_GIST_TYPE2___union(PG_FUNCTION_ARGS); Datum g__BTREE_GIST_TYPE2___picksplit(PG_FUNCTION_ARGS); Datum g__BTREE_GIST_TYPE2___consistent(PG_FUNCTION_ARGS); Datum g__BTREE_GIST_TYPE2___penalty(PG_FUNCTION_ARGS); Datum g__BTREE_GIST_TYPE2___same(PG_FUNCTION_ARGS); static void g__BTREE_GIST_TYPE2___binary_union(Datum *r1, char *r2); static int __BTREE_GIST_TYPE2__key_cmp(const void *a, const void *b); /************************************************** * __BTREE_GIST_TYPE__ ops **************************************************/ Datum g__BTREE_GIST_TYPE2___compress(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); GISTENTRY *retval; if (entry->leafkey) { __BTREE_GIST_TYPE__KEY *r = ( __BTREE_GIST_TYPE__KEY * ) palloc(sizeof(__BTREE_GIST_TYPE__KEY)); #ifdef BTREE_GIST_INT2 int16 leaf = DatumGetInt16(entry->key); #endif #ifdef BTREE_GIST_INT4 int32 leaf = DatumGetInt32(entry->key); #endif #ifdef BTREE_GIST_INT8 int64 leaf = DatumGetInt64(entry->key); #endif #ifdef BTREE_GIST_FLOAT4 float4 leaf = DatumGetFloat4(entry->key); #endif #ifdef BTREE_GIST_FLOAT8 float8 leaf = DatumGetFloat8(entry->key); #endif retval = palloc(sizeof(GISTENTRY)); r->lower = r->upper = leaf ; gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, entry->offset, sizeof(__BTREE_GIST_TYPE__KEY), FALSE); } else retval = entry; PG_RETURN_POINTER(retval); } Datum g__BTREE_GIST_TYPE2___consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); #ifdef BTREE_GIST_INT2 int16 query = PG_GETARG_INT16(1); #endif #ifdef BTREE_GIST_INT4 int32 query = PG_GETARG_INT32(1); #endif #ifdef BTREE_GIST_INT8 int64 query = PG_GETARG_INT64(1); #endif #ifdef BTREE_GIST_FLOAT4 float4 query = PG_GETARG_FLOAT4(1); #endif #ifdef BTREE_GIST_FLOAT8 float8 query = PG_GETARG_FLOAT8(1); #endif __BTREE_GIST_TYPE__KEY *kkk = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(entry->key); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); bool retval; switch (strategy) { case BTLessEqualStrategyNumber: retval = (query >= kkk->lower); break; case BTLessStrategyNumber: if (GIST_LEAF(entry)) retval = (query > kkk->lower); else retval = (query >= kkk->lower); break; case BTEqualStrategyNumber: /* in leaf page kkk->lower always = kkk->upper */ if (GIST_LEAF(entry)) retval = (query == kkk->lower); else retval = (kkk->lower <= query && query <= kkk->upper); break; case BTGreaterStrategyNumber: if (GIST_LEAF(entry)) retval = (query < kkk->upper); else retval = (query <= kkk->upper); break; case BTGreaterEqualStrategyNumber: retval = (query <= kkk->upper); break; default: retval = FALSE; } PG_RETURN_BOOL(retval); } Datum g__BTREE_GIST_TYPE2___union(PG_FUNCTION_ARGS) { bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); int i, numranges; __BTREE_GIST_TYPE__KEY *cur, *out = palloc(sizeof(__BTREE_GIST_TYPE__KEY)); numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); *(int *) PG_GETARG_POINTER(1) = sizeof(__BTREE_GIST_TYPE__KEY); cur = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key)); out->lower = cur->lower; out->upper = cur->upper; for (i = 1; i < numranges; i++) { cur = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); if (out->lower > cur->lower) out->lower = cur->lower; if (out->upper < cur->upper) out->upper = cur->upper; } PG_RETURN_POINTER(out); } Datum g__BTREE_GIST_TYPE2___penalty(PG_FUNCTION_ARGS) { __BTREE_GIST_TYPE__KEY *origentry = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); __BTREE_GIST_TYPE__KEY *newentry = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); *result = Max(newentry->upper - origentry->upper, 0) + Max(origentry->lower - newentry->lower, 0); PG_RETURN_POINTER(result); } Datum g__BTREE_GIST_TYPE2___picksplit(PG_FUNCTION_ARGS) { PG_RETURN_POINTER(btree_picksplit( (bytea *) PG_GETARG_POINTER(0), (GIST_SPLITVEC *) PG_GETARG_POINTER(1), g__BTREE_GIST_TYPE2___binary_union, __BTREE_GIST_TYPE2__key_cmp )); } Datum g__BTREE_GIST_TYPE2___same(PG_FUNCTION_ARGS) { __BTREE_GIST_TYPE__KEY *b1 = (__BTREE_GIST_TYPE__KEY *) PG_GETARG_POINTER(0); __BTREE_GIST_TYPE__KEY *b2 = (__BTREE_GIST_TYPE__KEY *) PG_GETARG_POINTER(1); bool *result = (bool *) PG_GETARG_POINTER(2); *result = (b1->lower == b2->lower && b1->upper == b2->upper) ? TRUE : FALSE; PG_RETURN_POINTER(result); } static void g__BTREE_GIST_TYPE2___binary_union(Datum *r1, char *r2) { __BTREE_GIST_TYPE__KEY *b1; __BTREE_GIST_TYPE__KEY *b2 = (__BTREE_GIST_TYPE__KEY *) r2; if (!DatumGetPointer(*r1)) { *r1 = PointerGetDatum(palloc(sizeof(__BTREE_GIST_TYPE__KEY))); b1 = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(*r1); b1->upper = b2->upper; b1->lower = b2->lower; } else { b1 = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(*r1); b1->lower = (b1->lower > b2->lower) ? b2->lower : b1->lower; b1->upper = (b1->upper > b2->upper) ? b1->upper : b2->upper; } } static int __BTREE_GIST_TYPE2__key_cmp(const void *a, const void *b) { if (((__BTREE_GIST_TYPE__KEY *) (((RIX *) a)->r))->lower > ((__BTREE_GIST_TYPE__KEY *) (((RIX *) b)->r))->lower){ return 1; } else if (((__BTREE_GIST_TYPE__KEY *) (((RIX *) a)->r))->lower < ((__BTREE_GIST_TYPE__KEY *) (((RIX *) b)->r))->lower){ return -1; } else { return 0; } } /************************************************** * In/Out for keys **************************************************/ Datum __BTREE_GIST_TYPE2__key_in(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("key_in() not implemented"))); PG_RETURN_POINTER(NULL); } Datum __BTREE_GIST_TYPE2__key_out(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("key_out() not implemented"))); PG_RETURN_POINTER(NULL); }