Commit 389bb281 authored by Andres Freund's avatar Andres Freund

Move contrib/seg to only use V1 calling conventions.

A later commit will remove V0 support.

Author: Andres Freund, with contributions by Craig Ringer
Reviewed-By: Peter Eisentraut, Craig Ringer
Discussion: https://postgr.es/m/20161208213441.k3mbno4twhg2qf7g@alap3.anarazel.de
parent f90d23d0
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
#include "segdata.h" #include "segdata.h"
#define DatumGetSegP(X) ((SEG *) DatumGetPointer(X))
#define PG_GETARG_SEG_P(n) DatumGetSegP(PG_GETARG_POINTER(n))
/* /*
#define GIST_DEBUG #define GIST_DEBUG
#define GIST_QUERY_DEBUG #define GIST_QUERY_DEBUG
...@@ -47,52 +52,45 @@ PG_FUNCTION_INFO_V1(seg_center); ...@@ -47,52 +52,45 @@ PG_FUNCTION_INFO_V1(seg_center);
/* /*
** GiST support methods ** GiST support methods
*/ */
bool gseg_consistent(GISTENTRY *entry, PG_FUNCTION_INFO_V1(gseg_consistent);
SEG *query, PG_FUNCTION_INFO_V1(gseg_compress);
StrategyNumber strategy, PG_FUNCTION_INFO_V1(gseg_decompress);
Oid subtype, PG_FUNCTION_INFO_V1(gseg_picksplit);
bool *recheck); PG_FUNCTION_INFO_V1(gseg_penalty);
GISTENTRY *gseg_compress(GISTENTRY *entry); PG_FUNCTION_INFO_V1(gseg_union);
GISTENTRY *gseg_decompress(GISTENTRY *entry); PG_FUNCTION_INFO_V1(gseg_same);
float *gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result); static Datum gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy);
GIST_SPLITVEC *gseg_picksplit(GistEntryVector *entryvec, GIST_SPLITVEC *v); static Datum gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy);
bool gseg_leaf_consistent(SEG *key, SEG *query, StrategyNumber strategy); static Datum gseg_binary_union(Datum r1, Datum r2, int *sizep);
bool gseg_internal_consistent(SEG *key, SEG *query, StrategyNumber strategy);
SEG *gseg_union(GistEntryVector *entryvec, int *sizep);
SEG *gseg_binary_union(SEG *r1, SEG *r2, int *sizep);
bool *gseg_same(SEG *b1, SEG *b2, bool *result);
/* /*
** R-tree support functions ** R-tree support functions
*/ */
bool seg_same(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_same);
bool seg_contains_int(SEG *a, int *b); PG_FUNCTION_INFO_V1(seg_contains);
bool seg_contains_float4(SEG *a, float4 *b); PG_FUNCTION_INFO_V1(seg_contained);
bool seg_contains_float8(SEG *a, float8 *b); PG_FUNCTION_INFO_V1(seg_overlap);
bool seg_contains(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_left);
bool seg_contained(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_over_left);
bool seg_overlap(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_right);
bool seg_left(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_over_right);
bool seg_over_left(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_union);
bool seg_right(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_inter);
bool seg_over_right(SEG *a, SEG *b); static void rt_seg_size(SEG *a, float *size);
SEG *seg_union(SEG *a, SEG *b);
SEG *seg_inter(SEG *a, SEG *b);
void rt_seg_size(SEG *a, float *sz);
/* /*
** Various operators ** Various operators
*/ */
int32 seg_cmp(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_cmp);
bool seg_lt(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_lt);
bool seg_le(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_le);
bool seg_gt(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_gt);
bool seg_ge(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_ge);
bool seg_different(SEG *a, SEG *b); PG_FUNCTION_INFO_V1(seg_different);
/* /*
** Auxiliary funxtions ** Auxiliary functions
*/ */
static int restore(char *s, float val, int n); static int restore(char *s, float val, int n);
...@@ -120,7 +118,7 @@ seg_in(PG_FUNCTION_ARGS) ...@@ -120,7 +118,7 @@ seg_in(PG_FUNCTION_ARGS)
Datum Datum
seg_out(PG_FUNCTION_ARGS) seg_out(PG_FUNCTION_ARGS)
{ {
SEG *seg = (SEG *) PG_GETARG_POINTER(0); SEG *seg = PG_GETARG_SEG_P(0);
char *result; char *result;
char *p; char *p;
...@@ -161,7 +159,7 @@ seg_out(PG_FUNCTION_ARGS) ...@@ -161,7 +159,7 @@ seg_out(PG_FUNCTION_ARGS)
Datum Datum
seg_center(PG_FUNCTION_ARGS) seg_center(PG_FUNCTION_ARGS)
{ {
SEG *seg = (SEG *) PG_GETARG_POINTER(0); SEG *seg = PG_GETARG_SEG_P(0);
PG_RETURN_FLOAT4(((float) seg->lower + (float) seg->upper) / 2.0); PG_RETURN_FLOAT4(((float) seg->lower + (float) seg->upper) / 2.0);
} }
...@@ -169,7 +167,7 @@ seg_center(PG_FUNCTION_ARGS) ...@@ -169,7 +167,7 @@ seg_center(PG_FUNCTION_ARGS)
Datum Datum
seg_lower(PG_FUNCTION_ARGS) seg_lower(PG_FUNCTION_ARGS)
{ {
SEG *seg = (SEG *) PG_GETARG_POINTER(0); SEG *seg = PG_GETARG_SEG_P(0);
PG_RETURN_FLOAT4(seg->lower); PG_RETURN_FLOAT4(seg->lower);
} }
...@@ -177,7 +175,7 @@ seg_lower(PG_FUNCTION_ARGS) ...@@ -177,7 +175,7 @@ seg_lower(PG_FUNCTION_ARGS)
Datum Datum
seg_upper(PG_FUNCTION_ARGS) seg_upper(PG_FUNCTION_ARGS)
{ {
SEG *seg = (SEG *) PG_GETARG_POINTER(0); SEG *seg = PG_GETARG_SEG_P(0);
PG_RETURN_FLOAT4(seg->upper); PG_RETURN_FLOAT4(seg->upper);
} }
...@@ -193,13 +191,16 @@ seg_upper(PG_FUNCTION_ARGS) ...@@ -193,13 +191,16 @@ seg_upper(PG_FUNCTION_ARGS)
** the predicate x op query == FALSE, where op is the oper ** the predicate x op query == FALSE, where op is the oper
** corresponding to strategy in the pg_amop table. ** corresponding to strategy in the pg_amop table.
*/ */
bool Datum
gseg_consistent(GISTENTRY *entry, gseg_consistent(PG_FUNCTION_ARGS)
SEG *query,
StrategyNumber strategy,
Oid subtype,
bool *recheck)
{ {
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
Datum query = PG_GETARG_DATUM(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
/* All cases served by this function are exact */ /* All cases served by this function are exact */
*recheck = false; *recheck = false;
...@@ -208,73 +209,77 @@ gseg_consistent(GISTENTRY *entry, ...@@ -208,73 +209,77 @@ gseg_consistent(GISTENTRY *entry,
* gseg_leaf_consistent * gseg_leaf_consistent
*/ */
if (GIST_LEAF(entry)) if (GIST_LEAF(entry))
return (gseg_leaf_consistent((SEG *) DatumGetPointer(entry->key), query, strategy)); return gseg_leaf_consistent(entry->key, query, strategy);
else else
return (gseg_internal_consistent((SEG *) DatumGetPointer(entry->key), query, strategy)); return gseg_internal_consistent(entry->key, query, strategy);
} }
/* /*
** The GiST Union method for segments ** The GiST Union method for segments
** returns the minimal bounding seg that encloses all the entries in entryvec ** returns the minimal bounding seg that encloses all the entries in entryvec
*/ */
SEG * Datum
gseg_union(GistEntryVector *entryvec, int *sizep) gseg_union(PG_FUNCTION_ARGS)
{ {
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
int *sizep = (int *) PG_GETARG_POINTER(1);
int numranges, int numranges,
i; i;
SEG *out = (SEG *) NULL; Datum out = 0;
SEG *tmp; Datum tmp;
#ifdef GIST_DEBUG #ifdef GIST_DEBUG
fprintf(stderr, "union\n"); fprintf(stderr, "union\n");
#endif #endif
numranges = entryvec->n; numranges = entryvec->n;
tmp = (SEG *) DatumGetPointer(entryvec->vector[0].key); tmp = entryvec->vector[0].key;
*sizep = sizeof(SEG); *sizep = sizeof(SEG);
for (i = 1; i < numranges; i++) for (i = 1; i < numranges; i++)
{ {
out = gseg_binary_union(tmp, (SEG *) out = gseg_binary_union(tmp, entryvec->vector[i].key, sizep);
DatumGetPointer(entryvec->vector[i].key),
sizep);
tmp = out; tmp = out;
} }
return (out); PG_RETURN_DATUM(out);
} }
/* /*
** GiST Compress and Decompress methods for segments ** GiST Compress and Decompress methods for segments
** do not do anything. ** do not do anything.
*/ */
GISTENTRY * Datum
gseg_compress(GISTENTRY *entry) gseg_compress(PG_FUNCTION_ARGS)
{ {
return (entry); PG_RETURN_POINTER(PG_GETARG_POINTER(0));
} }
GISTENTRY * Datum
gseg_decompress(GISTENTRY *entry) gseg_decompress(PG_FUNCTION_ARGS)
{ {
return (entry); PG_RETURN_POINTER(PG_GETARG_POINTER(0));
} }
/* /*
** The GiST Penalty method for segments ** The GiST Penalty method for segments
** As in the R-tree paper, we use change in area as our penalty metric ** As in the R-tree paper, we use change in area as our penalty metric
*/ */
float * Datum
gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result) gseg_penalty(PG_FUNCTION_ARGS)
{ {
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
float *result = (float *) PG_GETARG_POINTER(2);
SEG *ud; SEG *ud;
float tmp1, float tmp1,
tmp2; tmp2;
ud = seg_union((SEG *) DatumGetPointer(origentry->key), ud = DatumGetSegP(DirectFunctionCall2(seg_union,
(SEG *) DatumGetPointer(newentry->key)); origentry->key,
newentry->key));
rt_seg_size(ud, &tmp1); rt_seg_size(ud, &tmp1);
rt_seg_size((SEG *) DatumGetPointer(origentry->key), &tmp2); rt_seg_size(DatumGetSegP(origentry->key), &tmp2);
*result = tmp1 - tmp2; *result = tmp1 - tmp2;
#ifdef GIST_DEBUG #ifdef GIST_DEBUG
...@@ -282,7 +287,7 @@ gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result) ...@@ -282,7 +287,7 @@ gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
fprintf(stderr, "\t%g\n", *result); fprintf(stderr, "\t%g\n", *result);
#endif #endif
return (result); PG_RETURN_POINTER(result);
} }
/* /*
...@@ -309,14 +314,15 @@ gseg_picksplit_item_cmp(const void *a, const void *b) ...@@ -309,14 +314,15 @@ gseg_picksplit_item_cmp(const void *a, const void *b)
* it's easier and more robust to just sort the segments by center-point and * it's easier and more robust to just sort the segments by center-point and
* split at the middle. * split at the middle.
*/ */
GIST_SPLITVEC * Datum
gseg_picksplit(GistEntryVector *entryvec, gseg_picksplit(PG_FUNCTION_ARGS)
GIST_SPLITVEC *v)
{ {
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
int i; int i;
SEG *datum_l, SEG *seg,
*datum_r, *seg_l,
*seg; *seg_r;
gseg_picksplit_item *sort_items; gseg_picksplit_item *sort_items;
OffsetNumber *left, OffsetNumber *left,
*right; *right;
...@@ -337,7 +343,7 @@ gseg_picksplit(GistEntryVector *entryvec, ...@@ -337,7 +343,7 @@ gseg_picksplit(GistEntryVector *entryvec,
palloc(maxoff * sizeof(gseg_picksplit_item)); palloc(maxoff * sizeof(gseg_picksplit_item));
for (i = 1; i <= maxoff; i++) for (i = 1; i <= maxoff; i++)
{ {
seg = (SEG *) DatumGetPointer(entryvec->vector[i].key); seg = DatumGetSegP(entryvec->vector[i].key);
/* center calculation is done this way to avoid possible overflow */ /* center calculation is done this way to avoid possible overflow */
sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f; sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f;
sort_items[i - 1].index = i; sort_items[i - 1].index = i;
...@@ -359,13 +365,17 @@ gseg_picksplit(GistEntryVector *entryvec, ...@@ -359,13 +365,17 @@ gseg_picksplit(GistEntryVector *entryvec,
/* /*
* Emit segments to the left output page, and compute its bounding box. * Emit segments to the left output page, and compute its bounding box.
*/ */
datum_l = (SEG *) palloc(sizeof(SEG)); seg_l = (SEG *) palloc(sizeof(SEG));
memcpy(datum_l, sort_items[0].data, sizeof(SEG)); memcpy(seg_l, sort_items[0].data, sizeof(SEG));
*left++ = sort_items[0].index; *left++ = sort_items[0].index;
v->spl_nleft++; v->spl_nleft++;
for (i = 1; i < firstright; i++) for (i = 1; i < firstright; i++)
{ {
datum_l = seg_union(datum_l, sort_items[i].data); Datum sortitem = PointerGetDatum(sort_items[i].data);
seg_l = DatumGetSegP(DirectFunctionCall2(seg_union,
PointerGetDatum(seg_l),
sortitem));
*left++ = sort_items[i].index; *left++ = sort_items[i].index;
v->spl_nleft++; v->spl_nleft++;
} }
...@@ -373,30 +383,36 @@ gseg_picksplit(GistEntryVector *entryvec, ...@@ -373,30 +383,36 @@ gseg_picksplit(GistEntryVector *entryvec,
/* /*
* Likewise for the right page. * Likewise for the right page.
*/ */
datum_r = (SEG *) palloc(sizeof(SEG)); seg_r = (SEG *) palloc(sizeof(SEG));
memcpy(datum_r, sort_items[firstright].data, sizeof(SEG)); memcpy(seg_r, sort_items[firstright].data, sizeof(SEG));
*right++ = sort_items[firstright].index; *right++ = sort_items[firstright].index;
v->spl_nright++; v->spl_nright++;
for (i = firstright + 1; i < maxoff; i++) for (i = firstright + 1; i < maxoff; i++)
{ {
datum_r = seg_union(datum_r, sort_items[i].data); Datum sortitem = PointerGetDatum(sort_items[i].data);
seg_r = DatumGetSegP(DirectFunctionCall2(seg_union,
PointerGetDatum(seg_r),
sortitem));
*right++ = sort_items[i].index; *right++ = sort_items[i].index;
v->spl_nright++; v->spl_nright++;
} }
v->spl_ldatum = PointerGetDatum(datum_l); v->spl_ldatum = PointerGetDatum(seg_l);
v->spl_rdatum = PointerGetDatum(datum_r); v->spl_rdatum = PointerGetDatum(seg_r);
return v; PG_RETURN_POINTER(v);
} }
/* /*
** Equality methods ** Equality methods
*/ */
bool * Datum
gseg_same(SEG *b1, SEG *b2, bool *result) gseg_same(PG_FUNCTION_ARGS)
{ {
if (seg_same(b1, b2)) bool *result = (bool *) PG_GETARG_POINTER(2);
if (DirectFunctionCall2(seg_same, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)))
*result = TRUE; *result = TRUE;
else else
*result = FALSE; *result = FALSE;
...@@ -405,18 +421,16 @@ gseg_same(SEG *b1, SEG *b2, bool *result) ...@@ -405,18 +421,16 @@ gseg_same(SEG *b1, SEG *b2, bool *result)
fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE")); fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE"));
#endif #endif
return (result); PG_RETURN_POINTER(result);
} }
/* /*
** SUPPORT ROUTINES ** SUPPORT ROUTINES
*/ */
bool static Datum
gseg_leaf_consistent(SEG *key, gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy)
SEG *query,
StrategyNumber strategy)
{ {
bool retval; Datum retval;
#ifdef GIST_QUERY_DEBUG #ifdef GIST_QUERY_DEBUG
fprintf(stderr, "leaf_consistent, %d\n", strategy); fprintf(stderr, "leaf_consistent, %d\n", strategy);
...@@ -425,41 +439,40 @@ gseg_leaf_consistent(SEG *key, ...@@ -425,41 +439,40 @@ gseg_leaf_consistent(SEG *key,
switch (strategy) switch (strategy)
{ {
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
retval = (bool) seg_left(key, query); retval = DirectFunctionCall2(seg_left, key, query);
break; break;
case RTOverLeftStrategyNumber: case RTOverLeftStrategyNumber:
retval = (bool) seg_over_left(key, query); retval = DirectFunctionCall2(seg_over_left, key, query);
break; break;
case RTOverlapStrategyNumber: case RTOverlapStrategyNumber:
retval = (bool) seg_overlap(key, query); retval = DirectFunctionCall2(seg_overlap, key, query);
break; break;
case RTOverRightStrategyNumber: case RTOverRightStrategyNumber:
retval = (bool) seg_over_right(key, query); retval = DirectFunctionCall2(seg_over_right, key, query);
break; break;
case RTRightStrategyNumber: case RTRightStrategyNumber:
retval = (bool) seg_right(key, query); retval = DirectFunctionCall2(seg_right, key, query);
break; break;
case RTSameStrategyNumber: case RTSameStrategyNumber:
retval = (bool) seg_same(key, query); retval = DirectFunctionCall2(seg_same, key, query);
break; break;
case RTContainsStrategyNumber: case RTContainsStrategyNumber:
case RTOldContainsStrategyNumber: case RTOldContainsStrategyNumber:
retval = (bool) seg_contains(key, query); retval = DirectFunctionCall2(seg_contains, key, query);
break; break;
case RTContainedByStrategyNumber: case RTContainedByStrategyNumber:
case RTOldContainedByStrategyNumber: case RTOldContainedByStrategyNumber:
retval = (bool) seg_contained(key, query); retval = DirectFunctionCall2(seg_contained, key, query);
break; break;
default: default:
retval = FALSE; retval = FALSE;
} }
return (retval);
PG_RETURN_DATUM(retval);
} }
bool static Datum
gseg_internal_consistent(SEG *key, gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy)
SEG *query,
StrategyNumber strategy)
{ {
bool retval; bool retval;
...@@ -470,117 +483,147 @@ gseg_internal_consistent(SEG *key, ...@@ -470,117 +483,147 @@ gseg_internal_consistent(SEG *key,
switch (strategy) switch (strategy)
{ {
case RTLeftStrategyNumber: case RTLeftStrategyNumber:
retval = (bool) !seg_over_right(key, query); retval =
!DatumGetBool(DirectFunctionCall2(seg_over_right, key, query));
break; break;
case RTOverLeftStrategyNumber: case RTOverLeftStrategyNumber:
retval = (bool) !seg_right(key, query); retval =
!DatumGetBool(DirectFunctionCall2(seg_right, key, query));
break; break;
case RTOverlapStrategyNumber: case RTOverlapStrategyNumber:
retval = (bool) seg_overlap(key, query); retval =
DatumGetBool(DirectFunctionCall2(seg_overlap, key, query));
break; break;
case RTOverRightStrategyNumber: case RTOverRightStrategyNumber:
retval = (bool) !seg_left(key, query); retval =
!DatumGetBool(DirectFunctionCall2(seg_left, key, query));
break; break;
case RTRightStrategyNumber: case RTRightStrategyNumber:
retval = (bool) !seg_over_left(key, query); retval =
!DatumGetBool(DirectFunctionCall2(seg_over_left, key, query));
break; break;
case RTSameStrategyNumber: case RTSameStrategyNumber:
case RTContainsStrategyNumber: case RTContainsStrategyNumber:
case RTOldContainsStrategyNumber: case RTOldContainsStrategyNumber:
retval = (bool) seg_contains(key, query); retval =
DatumGetBool(DirectFunctionCall2(seg_contains, key, query));
break; break;
case RTContainedByStrategyNumber: case RTContainedByStrategyNumber:
case RTOldContainedByStrategyNumber: case RTOldContainedByStrategyNumber:
retval = (bool) seg_overlap(key, query); retval =
DatumGetBool(DirectFunctionCall2(seg_overlap, key, query));
break; break;
default: default:
retval = FALSE; retval = FALSE;
} }
return (retval);
PG_RETURN_BOOL(retval);
} }
SEG * static Datum
gseg_binary_union(SEG *r1, SEG *r2, int *sizep) gseg_binary_union(Datum r1, Datum r2, int *sizep)
{ {
SEG *retval; Datum retval;
retval = seg_union(r1, r2); retval = DirectFunctionCall2(seg_union, r1, r2);
*sizep = sizeof(SEG); *sizep = sizeof(SEG);
return (retval); return (retval);
} }
bool Datum
seg_contains(SEG *a, SEG *b) seg_contains(PG_FUNCTION_ARGS)
{ {
return ((a->lower <= b->lower) && (a->upper >= b->upper)); SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
PG_RETURN_BOOL((a->lower <= b->lower) && (a->upper >= b->upper));
} }
bool Datum
seg_contained(SEG *a, SEG *b) seg_contained(PG_FUNCTION_ARGS)
{ {
return (seg_contains(b, a)); Datum a = PG_GETARG_DATUM(0);
Datum b = PG_GETARG_DATUM(1);
PG_RETURN_DATUM(DirectFunctionCall2(seg_contains, b, a));
} }
/***************************************************************************** /*****************************************************************************
* Operator class for R-tree indexing * Operator class for R-tree indexing
*****************************************************************************/ *****************************************************************************/
bool Datum
seg_same(SEG *a, SEG *b) seg_same(PG_FUNCTION_ARGS)
{ {
return seg_cmp(a, b) == 0; int cmp = DatumGetInt32(
DirectFunctionCall2(seg_cmp, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(cmp == 0);
} }
/* seg_overlap -- does a overlap b? /* seg_overlap -- does a overlap b?
*/ */
bool Datum
seg_overlap(SEG *a, SEG *b) seg_overlap(PG_FUNCTION_ARGS)
{ {
return ( SEG *a = PG_GETARG_SEG_P(0);
((a->upper >= b->upper) && (a->lower <= b->upper)) SEG *b = PG_GETARG_SEG_P(1);
||
((b->upper >= a->upper) && (b->lower <= a->upper)) PG_RETURN_BOOL(((a->upper >= b->upper) && (a->lower <= b->upper)) ||
); ((b->upper >= a->upper) && (b->lower <= a->upper)));
} }
/* seg_overleft -- is the right edge of (a) located at or left of the right edge of (b)? /* seg_over_left -- is the right edge of (a) located at or left of the right edge of (b)?
*/ */
bool Datum
seg_over_left(SEG *a, SEG *b) seg_over_left(PG_FUNCTION_ARGS)
{ {
return (a->upper <= b->upper); SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
PG_RETURN_BOOL(a->upper <= b->upper);
} }
/* seg_left -- is (a) entirely on the left of (b)? /* seg_left -- is (a) entirely on the left of (b)?
*/ */
bool Datum
seg_left(SEG *a, SEG *b) seg_left(PG_FUNCTION_ARGS)
{ {
return (a->upper < b->lower); SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
PG_RETURN_BOOL(a->upper < b->lower);
} }
/* seg_right -- is (a) entirely on the right of (b)? /* seg_right -- is (a) entirely on the right of (b)?
*/ */
bool Datum
seg_right(SEG *a, SEG *b) seg_right(PG_FUNCTION_ARGS)
{ {
return (a->lower > b->upper); SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
PG_RETURN_BOOL(a->lower > b->upper);
} }
/* seg_overright -- is the left edge of (a) located at or right of the left edge of (b)? /* seg_over_right -- is the left edge of (a) located at or right of the left edge of (b)?
*/ */
bool Datum
seg_over_right(SEG *a, SEG *b) seg_over_right(PG_FUNCTION_ARGS)
{ {
return (a->lower >= b->lower); SEG *a = PG_GETARG_SEG_P(0);
} SEG *b = PG_GETARG_SEG_P(1);
PG_RETURN_BOOL(a->lower >= b->lower);
}
SEG * Datum
seg_union(SEG *a, SEG *b) seg_union(PG_FUNCTION_ARGS)
{ {
SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
SEG *n; SEG *n;
n = (SEG *) palloc(sizeof(*n)); n = (SEG *) palloc(sizeof(*n));
...@@ -613,13 +656,14 @@ seg_union(SEG *a, SEG *b) ...@@ -613,13 +656,14 @@ seg_union(SEG *a, SEG *b)
n->l_ext = b->l_ext; n->l_ext = b->l_ext;
} }
return (n); PG_RETURN_POINTER(n);
} }
Datum
SEG * seg_inter(PG_FUNCTION_ARGS)
seg_inter(SEG *a, SEG *b)
{ {
SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
SEG *n; SEG *n;
n = (SEG *) palloc(sizeof(*n)); n = (SEG *) palloc(sizeof(*n));
...@@ -652,10 +696,10 @@ seg_inter(SEG *a, SEG *b) ...@@ -652,10 +696,10 @@ seg_inter(SEG *a, SEG *b)
n->l_ext = b->l_ext; n->l_ext = b->l_ext;
} }
return (n); PG_RETURN_POINTER(n);
} }
void static void
rt_seg_size(SEG *a, float *size) rt_seg_size(SEG *a, float *size)
{ {
if (a == (SEG *) NULL || a->upper <= a->lower) if (a == (SEG *) NULL || a->upper <= a->lower)
...@@ -669,7 +713,7 @@ rt_seg_size(SEG *a, float *size) ...@@ -669,7 +713,7 @@ rt_seg_size(SEG *a, float *size)
Datum Datum
seg_size(PG_FUNCTION_ARGS) seg_size(PG_FUNCTION_ARGS)
{ {
SEG *seg = (SEG *) PG_GETARG_POINTER(0); SEG *seg = PG_GETARG_SEG_P(0);
PG_RETURN_FLOAT4((float) Abs(seg->upper - seg->lower)); PG_RETURN_FLOAT4((float) Abs(seg->upper - seg->lower));
} }
...@@ -678,16 +722,19 @@ seg_size(PG_FUNCTION_ARGS) ...@@ -678,16 +722,19 @@ seg_size(PG_FUNCTION_ARGS)
/***************************************************************************** /*****************************************************************************
* Miscellaneous operators * Miscellaneous operators
*****************************************************************************/ *****************************************************************************/
int32 Datum
seg_cmp(SEG *a, SEG *b) seg_cmp(PG_FUNCTION_ARGS)
{ {
SEG *a = PG_GETARG_SEG_P(0);
SEG *b = PG_GETARG_SEG_P(1);
/* /*
* First compare on lower boundary position * First compare on lower boundary position
*/ */
if (a->lower < b->lower) if (a->lower < b->lower)
return -1; PG_RETURN_INT32(-1);
if (a->lower > b->lower) if (a->lower > b->lower)
return 1; PG_RETURN_INT32(1);
/* /*
* a->lower == b->lower, so consider type of boundary. * a->lower == b->lower, so consider type of boundary.
...@@ -699,27 +746,27 @@ seg_cmp(SEG *a, SEG *b) ...@@ -699,27 +746,27 @@ seg_cmp(SEG *a, SEG *b)
if (a->l_ext != b->l_ext) if (a->l_ext != b->l_ext)
{ {
if (a->l_ext == '-') if (a->l_ext == '-')
return -1; PG_RETURN_INT32(-1);
if (b->l_ext == '-') if (b->l_ext == '-')
return 1; PG_RETURN_INT32(1);
if (a->l_ext == '<') if (a->l_ext == '<')
return -1; PG_RETURN_INT32(-1);
if (b->l_ext == '<') if (b->l_ext == '<')
return 1; PG_RETURN_INT32(1);
if (a->l_ext == '>') if (a->l_ext == '>')
return 1; PG_RETURN_INT32(1);
if (b->l_ext == '>') if (b->l_ext == '>')
return -1; PG_RETURN_INT32(-1);
} }
/* /*
* For other boundary types, consider # of significant digits first. * For other boundary types, consider # of significant digits first.
*/ */
if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include (b) */ if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include (b) */
return -1; PG_RETURN_INT32(-1);
if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be
* included in (b) */ * included in (b) */
return 1; PG_RETURN_INT32(1);
/* /*
* For same # of digits, an approximate boundary is more blurred than * For same # of digits, an approximate boundary is more blurred than
...@@ -728,9 +775,9 @@ seg_cmp(SEG *a, SEG *b) ...@@ -728,9 +775,9 @@ seg_cmp(SEG *a, SEG *b)
if (a->l_ext != b->l_ext) if (a->l_ext != b->l_ext)
{ {
if (a->l_ext == '~') /* (a) is approximate, while (b) is exact */ if (a->l_ext == '~') /* (a) is approximate, while (b) is exact */
return -1; PG_RETURN_INT32(-1);
if (b->l_ext == '~') if (b->l_ext == '~')
return 1; PG_RETURN_INT32(1);
/* can't get here unless data is corrupt */ /* can't get here unless data is corrupt */
elog(ERROR, "bogus lower boundary types %d %d", elog(ERROR, "bogus lower boundary types %d %d",
(int) a->l_ext, (int) b->l_ext); (int) a->l_ext, (int) b->l_ext);
...@@ -742,9 +789,9 @@ seg_cmp(SEG *a, SEG *b) ...@@ -742,9 +789,9 @@ seg_cmp(SEG *a, SEG *b)
* First compare on upper boundary position * First compare on upper boundary position
*/ */
if (a->upper < b->upper) if (a->upper < b->upper)
return -1; PG_RETURN_INT32(-1);
if (a->upper > b->upper) if (a->upper > b->upper)
return 1; PG_RETURN_INT32(1);
/* /*
* a->upper == b->upper, so consider type of boundary. * a->upper == b->upper, so consider type of boundary.
...@@ -756,17 +803,17 @@ seg_cmp(SEG *a, SEG *b) ...@@ -756,17 +803,17 @@ seg_cmp(SEG *a, SEG *b)
if (a->u_ext != b->u_ext) if (a->u_ext != b->u_ext)
{ {
if (a->u_ext == '-') if (a->u_ext == '-')
return 1; PG_RETURN_INT32(1);
if (b->u_ext == '-') if (b->u_ext == '-')
return -1; PG_RETURN_INT32(-1);
if (a->u_ext == '<') if (a->u_ext == '<')
return -1; PG_RETURN_INT32(-1);
if (b->u_ext == '<') if (b->u_ext == '<')
return 1; PG_RETURN_INT32(1);
if (a->u_ext == '>') if (a->u_ext == '>')
return 1; PG_RETURN_INT32(1);
if (b->u_ext == '>') if (b->u_ext == '>')
return -1; PG_RETURN_INT32(-1);
} }
/* /*
...@@ -774,10 +821,10 @@ seg_cmp(SEG *a, SEG *b) ...@@ -774,10 +821,10 @@ seg_cmp(SEG *a, SEG *b)
* result here is converse of the lower-boundary case. * result here is converse of the lower-boundary case.
*/ */
if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include (b) */ if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include (b) */
return 1; PG_RETURN_INT32(1);
if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be
* included in (b) */ * included in (b) */
return -1; PG_RETURN_INT32(-1);
/* /*
* For same # of digits, an approximate boundary is more blurred than * For same # of digits, an approximate boundary is more blurred than
...@@ -786,45 +833,61 @@ seg_cmp(SEG *a, SEG *b) ...@@ -786,45 +833,61 @@ seg_cmp(SEG *a, SEG *b)
if (a->u_ext != b->u_ext) if (a->u_ext != b->u_ext)
{ {
if (a->u_ext == '~') /* (a) is approximate, while (b) is exact */ if (a->u_ext == '~') /* (a) is approximate, while (b) is exact */
return 1; PG_RETURN_INT32(1);
if (b->u_ext == '~') if (b->u_ext == '~')
return -1; PG_RETURN_INT32(-1);
/* can't get here unless data is corrupt */ /* can't get here unless data is corrupt */
elog(ERROR, "bogus upper boundary types %d %d", elog(ERROR, "bogus upper boundary types %d %d",
(int) a->u_ext, (int) b->u_ext); (int) a->u_ext, (int) b->u_ext);
} }
return 0; PG_RETURN_INT32(0);
} }
bool Datum
seg_lt(SEG *a, SEG *b) seg_lt(PG_FUNCTION_ARGS)
{ {
return seg_cmp(a, b) < 0; int cmp = DatumGetInt32(
DirectFunctionCall2(seg_cmp, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(cmp < 0);
} }
bool Datum
seg_le(SEG *a, SEG *b) seg_le(PG_FUNCTION_ARGS)
{ {
return seg_cmp(a, b) <= 0; int cmp = DatumGetInt32(
DirectFunctionCall2(seg_cmp, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(cmp <= 0);
} }
bool Datum
seg_gt(SEG *a, SEG *b) seg_gt(PG_FUNCTION_ARGS)
{ {
return seg_cmp(a, b) > 0; int cmp = DatumGetInt32(
DirectFunctionCall2(seg_cmp, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(cmp > 0);
} }
bool Datum
seg_ge(SEG *a, SEG *b) seg_ge(PG_FUNCTION_ARGS)
{ {
return seg_cmp(a, b) >= 0; int cmp = DatumGetInt32(
DirectFunctionCall2(seg_cmp, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(cmp >= 0);
} }
bool
seg_different(SEG *a, SEG *b) Datum
seg_different(PG_FUNCTION_ARGS)
{ {
return seg_cmp(a, b) != 0; int cmp = DatumGetInt32(
DirectFunctionCall2(seg_cmp, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)));
PG_RETURN_BOOL(cmp != 0);
} }
...@@ -985,24 +1048,6 @@ restore(char *result, float val, int n) ...@@ -985,24 +1048,6 @@ restore(char *result, float val, int n)
** Miscellany ** Miscellany
*/ */
bool
seg_contains_int(SEG *a, int *b)
{
return ((a->lower <= *b) && (a->upper >= *b));
}
bool
seg_contains_float4(SEG *a, float4 *b)
{
return ((a->lower <= *b) && (a->upper >= *b));
}
bool
seg_contains_float8(SEG *a, float8 *b)
{
return ((a->lower <= *b) && (a->upper >= *b));
}
/* find out the number of significant digits in a string representing /* find out the number of significant digits in a string representing
* a floating point number * a floating point number
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment