4 ******************************************************************************
5 This file contains routines that can be bound to a Postgres backend and
6 called by the backend in the process of processing queries. The calling
7 format for these routines is dictated by Postgres architecture.
8******************************************************************************/
22 #define DatumGetSegP(X) ((SEG *) DatumGetPointer(X))
23 #define PG_GETARG_SEG_P(n) DatumGetSegP(PG_GETARG_DATUM(n))
28#define GIST_QUERY_DEBUG
37 * Auxiliary data structure for picksplit method.
47** Input/Output routines
57** GiST support methods
72** R-tree support functions
99static int restore(
char *result,
float val,
int n);
102/*****************************************************************************
103 * Input/Output functions
104 *****************************************************************************/
115 if (
seg_yyparse(result, fcinfo->context, scanner) != 0)
116 seg_yyerror(result, fcinfo->context, scanner,
"bogus input");
130 p = result = (
char *)
palloc(40);
138 * indicates that this interval was built by seg_in off a single point
144 if (seg->
l_ext !=
'-')
146 /* print the lower boundary if exists */
151 if (seg->
u_ext !=
'-')
153 /* print the upper boundary if exists */
189/*****************************************************************************
191 *****************************************************************************/
194** The GiST Consistent method for segments
195** Should return false if for all data items x below entry,
196** the predicate x op query == false, where op is the oper
197** corresponding to strategy in the pg_amop table.
206 /* Oid subtype = PG_GETARG_OID(3); */
209 /* All cases served by this function are exact */
213 * if entry is not leaf, use gseg_internal_consistent, else use
214 * gseg_leaf_consistent
223** The GiST Union method for segments
224** returns the minimal bounding seg that encloses all the entries in entryvec
240 numranges = entryvec->
n;
242 *sizep =
sizeof(
SEG);
244 for (
i = 1;
i < numranges;
i++)
254** GiST Compress and Decompress methods for segments
255** do not do anything.
270** The GiST Penalty method for segments
271** As in the R-tree paper, we use change in area as our penalty metric
288 *result = tmp1 - tmp2;
292 fprintf(stderr,
"\t%g\n", *result);
299 * Compare function for gseg_picksplit_item: sort by center.
316 * The GiST PickSplit method for segments
318 * We used to use Guttman's split algorithm here, but since the data is 1-D
319 * it's easier and more robust to just sort the segments by center-point and
320 * split at the middle.
338 fprintf(stderr,
"picksplit\n");
341 /* Valid items in entryvec->vector[] are indexed 1..maxoff */
342 maxoff = entryvec->
n - 1;
345 * Prepare the auxiliary array and sort it.
349 for (
i = 1;
i <= maxoff;
i++)
352 /* center calculation is done this way to avoid possible overflow */
355 sort_items[
i - 1].
data = seg;
360 /* sort items below "firstright" will go into the left side */
361 firstright = maxoff / 2;
371 * Emit segments to the left output page, and compute its bounding box.
374 memcpy(seg_l, sort_items[0].
data,
sizeof(
SEG));
375 *left++ = sort_items[0].
index;
377 for (
i = 1;
i < firstright;
i++)
384 *left++ = sort_items[
i].
index;
389 * Likewise for the right page.
392 memcpy(seg_r, sort_items[firstright].
data,
sizeof(
SEG));
393 *right++ = sort_items[firstright].
index;
395 for (
i = firstright + 1;
i < maxoff;
i++)
402 *right++ = sort_items[
i].
index;
426 fprintf(stderr,
"same: %s\n", (*result ?
"TRUE" :
"FALSE"));
440#ifdef GIST_QUERY_DEBUG
441 fprintf(stderr,
"leaf_consistent, %d\n", strategy);
484#ifdef GIST_QUERY_DEBUG
485 fprintf(stderr,
"internal_consistent, %d\n", strategy);
534 *sizep =
sizeof(
SEG);
558/*****************************************************************************
559 * Operator class for R-tree indexing
560 *****************************************************************************/
572/* seg_overlap -- does a overlap b?
581 ((
b->upper >=
a->upper) && (
b->lower <=
a->upper)));
584/* seg_over_left -- is the right edge of (a) located at or left of the right edge of (b)?
595/* seg_left -- is (a) entirely on the left of (b)?
606/* seg_right -- is (a) entirely on the right of (b)?
617/* seg_over_right -- is the left edge of (a) located at or right of the left edge of (b)?
637 /* take max of upper endpoints */
638 if (
a->upper >
b->upper)
651 /* take min of lower endpoints */
652 if (
a->lower <
b->lower)
677 /* take min of upper endpoints */
678 if (
a->upper <
b->upper)
691 /* take max of lower endpoints */
692 if (
a->lower >
b->lower)
711 if (
a == (
SEG *) NULL ||
a->upper <=
a->lower)
714 *size = fabsf(
a->upper -
a->lower);
726/*****************************************************************************
727 * Miscellaneous operators
728 *****************************************************************************/
736 * First compare on lower boundary position
738 if (
a->lower <
b->lower)
740 if (
a->lower >
b->lower)
744 * a->lower == b->lower, so consider type of boundary.
746 * A '-' lower bound is < any other kind (this could only be relevant if
747 * -HUGE_VAL is used as a regular data value). A '<' lower bound is < any
748 * other kind except '-'. A '>' lower bound is > any other kind.
750 if (
a->l_ext !=
b->l_ext)
767 * For other boundary types, consider # of significant digits first.
769 if (
a->l_sigd <
b->l_sigd)
/* (a) is blurred and is likely to include (b) */
771 if (
a->l_sigd >
b->l_sigd)
/* (a) is less blurred and is likely to be
776 * For same # of digits, an approximate boundary is more blurred than
779 if (
a->l_ext !=
b->l_ext)
781 if (
a->l_ext ==
'~')
/* (a) is approximate, while (b) is exact */
785 /* can't get here unless data is corrupt */
786 elog(
ERROR,
"bogus lower boundary types %d %d",
787 (
int)
a->l_ext, (
int)
b->l_ext);
790 /* at this point, the lower boundaries are identical */
793 * First compare on upper boundary position
795 if (
a->upper <
b->upper)
797 if (
a->upper >
b->upper)
801 * a->upper == b->upper, so consider type of boundary.
803 * A '-' upper bound is > any other kind (this could only be relevant if
804 * HUGE_VAL is used as a regular data value). A '<' upper bound is < any
805 * other kind. A '>' upper bound is > any other kind except '-'.
807 if (
a->u_ext !=
b->u_ext)
824 * For other boundary types, consider # of significant digits first. Note
825 * result here is converse of the lower-boundary case.
827 if (
a->u_sigd <
b->u_sigd)
/* (a) is blurred and is likely to include (b) */
829 if (
a->u_sigd >
b->u_sigd)
/* (a) is less blurred and is likely to be
834 * For same # of digits, an approximate boundary is more blurred than
835 * exact. Again, result is converse of lower-boundary case.
837 if (
a->u_ext !=
b->u_ext)
839 if (
a->u_ext ==
'~')
/* (a) is approximate, while (b) is exact */
843 /* can't get here unless data is corrupt */
844 elog(
ERROR,
"bogus upper boundary types %d %d",
845 (
int)
a->u_ext, (
int)
b->u_ext);
904/*****************************************************************************
905 * Auxiliary functions
906 *****************************************************************************/
909 * The purpose of this routine is to print the given floating point
910 * value with exactly n significant digits. Its behaviour
911 * is similar to %.ng except it prints 8.00 where %.ng would
912 * print 8. Returns the length of the string written at "result".
914 * Caller must provide a sufficiently large result buffer; 16 bytes
915 * should be enough for all known float implementations.
921 '0',
'0',
'0',
'0',
'0',
922 '0',
'0',
'0',
'0',
'0',
923 '0',
'0',
'0',
'0',
'0',
924 '0',
'0',
'0',
'0',
'0',
925 '0',
'0',
'0',
'0',
'0円'
934 * Put a cap on the number of significant digits to avoid garbage in the
935 * output and ensure we don't overrun the result buffer. (n should not be
936 * negative, but check to protect ourselves against corrupted data.)
943 /* remember the sign */
946 /* print, in %e style to start with */
949 /* find the exponent */
950 p = strchr(result,
'e');
952 /* punt if we have 'inf' or similar */
954 return strlen(result);
959 /* just truncate off the 'e+00' */
967 * remove the decimal point from the mantissa and write the digits
970 for (p = result +
sign,
i = 10, dp = 0; *p !=
'e'; p++,
i++)
975 dp =
i--;
/* skip the decimal point */
979 dp =
i--;
/* no decimal point was found in the above
984 if (dp - 10 + exp >= n)
987 * the decimal point is behind the last significant digit;
988 * the digits in between must be converted to the exponent
989 * and the decimal point placed after the first digit
991 exp = dp - 10 + exp - n;
994 /* insert the decimal point */
998 for (
i = 23;
i > dp;
i--)
1004 * adjust the exponent by the number of digits after the
1015 strcpy(result, &
buf[9]);
1018 strcpy(result, &
buf[10]);
1021 {
/* insert the decimal point */
1023 for (
i = 23;
i > dp;
i--)
1030 strcpy(result, &
buf[9]);
1033 strcpy(result, &
buf[10]);
1044 strcpy(result, &
buf[dp - 2]);
1047 strcpy(result, &
buf[dp - 1]);
1051 /* do nothing for abs(exp) > 4; %e must be OK */
1052 /* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */
1054 /* ... this is not done yet. */
1056 return strlen(result);
1064/* find out the number of significant digits in a string representing
1065 * a floating point number
1076 /* skip leading zeroes and sign */
1077 for (
c = *p; (
c ==
'0' ||
c ==
'+' ||
c ==
'-') &&
c != 0;
c = *(++p));
1079 /* skip decimal point and following zeroes */
1080 for (
c = *p; (
c ==
'0' ||
c ==
'.') &&
c != 0;
c = *(++p))
1086 /* count significant digits (n) */
1087 for (
c = *p, n = 0;
c != 0;
c = *(++p))
1089 if (!((
c >=
'0' &&
c <=
'9') || (
c ==
'.')))
#define fprintf(file, fmt, msg)
#define DirectFunctionCall2(func, arg1, arg2)
#define PG_GETARG_POINTER(n)
#define PG_RETURN_CSTRING(x)
#define PG_GETARG_DATUM(n)
#define PG_GETARG_CSTRING(n)
#define PG_GETARG_UINT16(n)
#define PG_RETURN_INT32(x)
#define PG_RETURN_DATUM(x)
#define PG_RETURN_POINTER(x)
#define PG_RETURN_FLOAT4(x)
#define PG_RETURN_BOOL(x)
#define qsort(a, b, c, d)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static Datum BoolGetDatum(bool X)
static int32 DatumGetInt32(Datum X)
static int cmp(const chr *x, const chr *y, size_t len)
Datum seg_le(PG_FUNCTION_ARGS)
Datum gseg_decompress(PG_FUNCTION_ARGS)
Datum seg_gt(PG_FUNCTION_ARGS)
static Datum gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy)
Datum gseg_penalty(PG_FUNCTION_ARGS)
Datum gseg_union(PG_FUNCTION_ARGS)
Datum gseg_consistent(PG_FUNCTION_ARGS)
Datum seg_center(PG_FUNCTION_ARGS)
PG_MODULE_MAGIC_EXT(.name="seg",.version=PG_VERSION)
Datum seg_over_right(PG_FUNCTION_ARGS)
Datum seg_contained(PG_FUNCTION_ARGS)
Datum seg_overlap(PG_FUNCTION_ARGS)
Datum seg_right(PG_FUNCTION_ARGS)
#define PG_GETARG_SEG_P(n)
Datum gseg_same(PG_FUNCTION_ARGS)
static int gseg_picksplit_item_cmp(const void *a, const void *b)
Datum seg_lt(PG_FUNCTION_ARGS)
Datum seg_size(PG_FUNCTION_ARGS)
Datum seg_union(PG_FUNCTION_ARGS)
int significant_digits(const char *s)
Datum seg_upper(PG_FUNCTION_ARGS)
static Datum gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy)
Datum seg_ge(PG_FUNCTION_ARGS)
Datum seg_lower(PG_FUNCTION_ARGS)
Datum gseg_picksplit(PG_FUNCTION_ARGS)
Datum seg_in(PG_FUNCTION_ARGS)
Datum seg_cmp(PG_FUNCTION_ARGS)
static int restore(char *result, float val, int n)
Datum seg_inter(PG_FUNCTION_ARGS)
Datum seg_left(PG_FUNCTION_ARGS)
static void rt_seg_size(SEG *a, float *size)
Datum seg_out(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(seg_in)
static Datum gseg_binary_union(Datum r1, Datum r2, int *sizep)
Datum seg_over_left(PG_FUNCTION_ARGS)
Datum gseg_compress(PG_FUNCTION_ARGS)
Datum seg_contains(PG_FUNCTION_ARGS)
Datum seg_same(PG_FUNCTION_ARGS)
Datum seg_different(PG_FUNCTION_ARGS)
void seg_yyerror(SEG *result, struct Node *escontext, yyscan_t yyscanner, const char *message)
void seg_scanner_init(const char *str, yyscan_t *yyscannerp)
int seg_yyparse(SEG *result, struct Node *escontext, yyscan_t yyscanner)
void seg_scanner_finish(yyscan_t yyscanner)
#define RTOldContainsStrategyNumber
#define RTOverlapStrategyNumber
#define RTLeftStrategyNumber
#define RTOverRightStrategyNumber
#define RTRightStrategyNumber
#define RTSameStrategyNumber
#define RTContainsStrategyNumber
#define RTOverLeftStrategyNumber
#define RTOldContainedByStrategyNumber
#define RTContainedByStrategyNumber
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]