From b90f8f20f035c3313f8a284346b5a1d155cfd2f0 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 24 Jun 2005 20:53:34 +0000 Subject: [PATCH] Extend r-tree operator classes to handle Y-direction tests equivalent to the existing X-direction tests. An rtree class now includes 4 actual 2-D tests, 4 1-D X-direction tests, and 4 1-D Y-direction tests. This involved adding four new Y-direction test operators for each of box and polygon; I followed the PostGIS project's lead as to the names of these operators. NON BACKWARDS COMPATIBLE CHANGE: the poly_overleft (&<) and poly_overright (&>) operators now have semantics comparable to box_overleft and box_overright. This is necessary to make r-tree indexes work correctly on polygons. Also, I changed circle_left and circle_right to agree with box_left and box_right --- formerly they allowed the boundaries to touch. This isn't actually essential given the lack of any r-tree opclass for circles, but it seems best to sync all the definitions while we are at it. --- contrib/rtree_gist/rtree_gist.c | 40 ++++- contrib/rtree_gist/rtree_gist.sql.in | 10 +- doc/src/sgml/func.sgml | 49 ++++-- doc/src/sgml/indices.sgml | 7 +- doc/src/sgml/xindex.sgml | 38 +++-- src/backend/access/rtree/rtstrat.c | 14 +- src/backend/utils/adt/geo_ops.c | 198 ++++++++++++++++++++--- src/include/access/rtree.h | 8 +- src/include/catalog/catversion.h | 4 +- src/include/catalog/pg_am.h | 4 +- src/include/catalog/pg_amop.h | 42 +++-- src/include/catalog/pg_operator.h | 16 +- src/include/catalog/pg_proc.h | 28 +++- src/include/utils/geo_decls.h | 16 +- src/test/regress/expected/opr_sanity.out | 6 +- src/test/regress/expected/polygon.out | 11 +- src/test/regress/sql/polygon.sql | 2 +- 17 files changed, 394 insertions(+), 99 deletions(-) diff --git a/contrib/rtree_gist/rtree_gist.c b/contrib/rtree_gist/rtree_gist.c index f4ce58460f..d6292b803e 100644 --- a/contrib/rtree_gist/rtree_gist.c +++ b/contrib/rtree_gist/rtree_gist.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * rtree_gist.c - * pg_amproc entries for GiSTs over 2-D boxes. + * pg_amproc entries for GiSTs over 2-D boxes and polygons. * * This gives R-tree behavior, with Guttman's poly-time split algorithm. * * * IDENTIFICATION - * $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.13 2005/06/24 00:18:52 tgl Exp $ + * $PostgreSQL: pgsql/contrib/rtree_gist/rtree_gist.c,v 1.14 2005/06/24 20:53:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,8 +23,8 @@ typedef Datum (*BINARY_UNION) (Datum, Datum, int *); typedef float (*SIZE_BOX) (Datum); /* -** box ops -*/ + * box ops + */ PG_FUNCTION_INFO_V1(gbox_compress); PG_FUNCTION_INFO_V1(gbox_union); PG_FUNCTION_INFO_V1(gbox_picksplit); @@ -43,8 +43,8 @@ static bool gbox_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy); static float size_box(Datum box); /* -** Polygon ops -*/ + * Polygon ops + */ PG_FUNCTION_INFO_V1(gpoly_compress); PG_FUNCTION_INFO_V1(gpoly_consistent); @@ -52,8 +52,8 @@ Datum gpoly_compress(PG_FUNCTION_ARGS); Datum gpoly_consistent(PG_FUNCTION_ARGS); /* -** Common rtree-function (for all ops) -*/ + * Common rtree-function (for all ops) + */ static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy); PG_FUNCTION_INFO_V1(rtree_decompress); @@ -441,6 +441,18 @@ gbox_leaf_consistent(BOX *key, case RTContainedByStrategyNumber: retval = DatumGetBool(DirectFunctionCall2(box_contained, PointerGetDatum(key), PointerGetDatum(query))); break; + case RTOverBelowStrategyNumber: + retval = DatumGetBool(DirectFunctionCall2(box_overbelow, PointerGetDatum(key), PointerGetDatum(query))); + break; + case RTBelowStrategyNumber: + retval = DatumGetBool(DirectFunctionCall2(box_below, PointerGetDatum(key), PointerGetDatum(query))); + break; + case RTAboveStrategyNumber: + retval = DatumGetBool(DirectFunctionCall2(box_above, PointerGetDatum(key), PointerGetDatum(query))); + break; + case RTOverAboveStrategyNumber: + retval = DatumGetBool(DirectFunctionCall2(box_overabove, PointerGetDatum(key), PointerGetDatum(query))); + break; default: retval = FALSE; } @@ -558,6 +570,18 @@ rtree_internal_consistent(BOX *key, case RTContainedByStrategyNumber: retval = DatumGetBool(DirectFunctionCall2(box_overlap, PointerGetDatum(key), PointerGetDatum(query))); break; + case RTOverBelowStrategyNumber: + retval = !DatumGetBool(DirectFunctionCall2(box_above, PointerGetDatum(key), PointerGetDatum(query))); + break; + case RTBelowStrategyNumber: + retval = !DatumGetBool(DirectFunctionCall2(box_overabove, PointerGetDatum(key), PointerGetDatum(query))); + break; + case RTAboveStrategyNumber: + retval = !DatumGetBool(DirectFunctionCall2(box_overbelow, PointerGetDatum(key), PointerGetDatum(query))); + break; + case RTOverAboveStrategyNumber: + retval = !DatumGetBool(DirectFunctionCall2(box_below, PointerGetDatum(key), PointerGetDatum(query))); + break; default: retval = FALSE; } diff --git a/contrib/rtree_gist/rtree_gist.sql.in b/contrib/rtree_gist/rtree_gist.sql.in index 2fc38a7024..e59edcacff 100644 --- a/contrib/rtree_gist/rtree_gist.sql.in +++ b/contrib/rtree_gist/rtree_gist.sql.in @@ -27,7 +27,7 @@ LANGUAGE 'C'; CREATE FUNCTION gbox_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' -LANGUAGE 'C' with (isstrict); +LANGUAGE 'C' STRICT; CREATE FUNCTION gbox_picksplit(internal, internal) RETURNS internal @@ -56,6 +56,10 @@ AS OPERATOR 6 ~= , OPERATOR 7 ~ , OPERATOR 8 @ , + OPERATOR 9 &<| , + OPERATOR 10 <<| , + OPERATOR 11 |>> , + OPERATOR 12 |&> , FUNCTION 1 gbox_consistent (internal, box, int4), FUNCTION 2 gbox_union (internal, internal), FUNCTION 3 gbox_compress (internal), @@ -95,6 +99,10 @@ AS OPERATOR 6 ~= RECHECK, OPERATOR 7 ~ RECHECK, OPERATOR 8 @ RECHECK, + OPERATOR 9 &<| RECHECK, + OPERATOR 10 <<| RECHECK, + OPERATOR 11 |>> RECHECK, + OPERATOR 12 |&> RECHECK, FUNCTION 1 gpoly_consistent (internal, polygon, int4), FUNCTION 2 gbox_union (internal, internal), FUNCTION 3 gpoly_compress (internal), diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 02ca4f896e..8c7a48308e 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,5 +1,5 @@ @@ -5854,6 +5854,17 @@ SELECT TIMESTAMP 'now'; -- incorrect for use with DEFAULT linkend="functions-geometry-conv-table">. + + + Note that the same as operator, ~=, represents + the usual notion of equality for the point, + box, polygon, and circle types. + Some of these types also have an = operator, but it compares + for equal areas only. The other scalar comparison operators + (<= and so on) likewise compare areas for these types. + + + Geometric Operators @@ -5920,6 +5931,16 @@ SELECT TIMESTAMP 'now'; -- incorrect for use with DEFAULT Overlaps? box '((0,0),(1,1))' && box '((0,0),(2,2))' + + << + Is strictly left of? + circle '((0,0),1)' << circle '((5,0),1)' + + + >> + Is strictly right of? + circle '((5,0),1)' >> circle '((0,0),1)' + &< Does not extend to the right of? @@ -5931,23 +5952,33 @@ SELECT TIMESTAMP 'now'; -- incorrect for use with DEFAULT box '((0,0),(3,3))' &> box '((0,0),(2,2))' - << - Is left of? - circle '((0,0),1)' << circle '((5,0),1)' + <<| + Is strictly below? + box '((0,0),(3,3))' <<| box '((3,4),(5,5))' - >> - Is right of? - circle '((5,0),1)' >> circle '((0,0),1)' + |>> + Is strictly above? + box '((3,4),(5,5))' |>> box '((0,0),(3,3))' + + + &<| + Does not extend above? + box '((0,0),(1,1))' &<| box '((0,0),(2,2))' + + + |&> + Does not extend below? + box '((0,0),(3,3))' |&> box '((0,0),(2,2))' <^ - Is below? + Is below (allows touching)? circle '((0,0),1)' <^ circle '((0,5),1)' >^ - Is above? + Is above (allows touching)? circle '((0,5),1)' >^ circle '((0,0),1)' diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index 41f87d60f6..3bb530b60e 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -1,4 +1,4 @@ - + Indexes @@ -177,6 +177,11 @@ CREATE INDEX name ON table &< &> >> + <<| + &<| + |&> + |>> + ~ @ ~= && diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 0b25432448..5764198e27 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -1,5 +1,5 @@ @@ -169,8 +169,12 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.39 2005/02/13 03:04:15 tgl Exp $
- R-tree indexes express rectangle-containment relationships. - They use eight strategies, shown in . + R-tree indexes express relationships in two-dimensional space. + They use twelve strategies, shown in + . Four of these are true + two-dimensional tests (overlaps, same, contains, contained by); + four of them consider only the X direction; and the other four + provide the same tests in the Y direction. @@ -184,23 +188,23 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.39 2005/02/13 03:04:15 tgl Exp $ - left of + strictly left of 1 - left of or overlapping + does not extend to right of 2 - overlapping + overlaps 3 - right of or overlapping + does not extend to left of 4 - right of + strictly right of 5 @@ -215,6 +219,22 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.39 2005/02/13 03:04:15 tgl Exp $ contained by 8 + + does not extend above + 9 + + + strictly below + 10 + + + strictly above + 11 + + + does not extend below + 12 +
@@ -398,7 +418,7 @@ $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.39 2005/02/13 03:04:15 tgl Exp $ Unlike strategy operators, support functions return whichever data - type the particular index method expects, for example in the case + type the particular index method expects; for example in the case of the comparison function for B-trees, a signed integer. diff --git a/src/backend/access/rtree/rtstrat.c b/src/backend/access/rtree/rtstrat.c index c7104c9520..1b72d980da 100644 --- a/src/backend/access/rtree/rtstrat.c +++ b/src/backend/access/rtree/rtstrat.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/rtree/rtstrat.c,v 1.26 2005/06/24 00:18:52 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/rtree/rtstrat.c,v 1.27 2005/06/24 20:53:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,7 +37,11 @@ static const StrategyNumber RTOperMap[RTNStrategies] = { RTOverLeftStrategyNumber, /* right */ RTContainsStrategyNumber, /* same */ RTContainsStrategyNumber, /* contains */ - RTOverlapStrategyNumber /* contained-by */ + RTOverlapStrategyNumber, /* contained-by */ + RTAboveStrategyNumber, /* overbelow */ + RTOverAboveStrategyNumber, /* below */ + RTOverBelowStrategyNumber, /* above */ + RTBelowStrategyNumber /* overabove */ }; /* @@ -52,7 +56,11 @@ static const bool RTNegateMap[RTNStrategies] = { true, /* right */ false, /* same */ false, /* contains */ - false /* contained-by */ + false, /* contained-by */ + true, /* overbelow */ + true, /* below */ + true, /* above */ + true /* overabove */ }; diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 4aa19828a8..e279448263 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.88 2004/12/31 22:01:21 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.89 2005/06/24 20:53:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -567,30 +567,30 @@ box_ov(BOX *box1, BOX *box2) FPle(box2->low.y, box1->high.y))); } -/* box_overleft - is the right edge of box1 to the left of - * the right edge of box2? - * - * This is "less than or equal" for the end of a time range, - * when time ranges are stored as rectangles. +/* box_left - is box1 strictly left of box2? */ Datum -box_overleft(PG_FUNCTION_ARGS) +box_left(PG_FUNCTION_ARGS) { BOX *box1 = PG_GETARG_BOX_P(0); BOX *box2 = PG_GETARG_BOX_P(1); - PG_RETURN_BOOL(FPle(box1->high.x, box2->high.x)); + PG_RETURN_BOOL(FPlt(box1->high.x, box2->low.x)); } -/* box_left - is box1 strictly left of box2? +/* box_overleft - is the right edge of box1 at or left of + * the right edge of box2? + * + * This is "less than or equal" for the end of a time range, + * when time ranges are stored as rectangles. */ Datum -box_left(PG_FUNCTION_ARGS) +box_overleft(PG_FUNCTION_ARGS) { BOX *box1 = PG_GETARG_BOX_P(0); BOX *box2 = PG_GETARG_BOX_P(1); - PG_RETURN_BOOL(FPlt(box1->high.x, box2->low.x)); + PG_RETURN_BOOL(FPle(box1->high.x, box2->high.x)); } /* box_right - is box1 strictly right of box2? @@ -604,7 +604,7 @@ box_right(PG_FUNCTION_ARGS) PG_RETURN_BOOL(FPgt(box1->low.x, box2->high.x)); } -/* box_overright - is the left edge of box1 to the right of +/* box_overright - is the left edge of box1 at or right of * the left edge of box2? * * This is "greater than or equal" for time ranges, when time ranges @@ -619,6 +619,52 @@ box_overright(PG_FUNCTION_ARGS) PG_RETURN_BOOL(FPge(box1->low.x, box2->low.x)); } +/* box_below - is box1 strictly below box2? + */ +Datum +box_below(PG_FUNCTION_ARGS) +{ + BOX *box1 = PG_GETARG_BOX_P(0); + BOX *box2 = PG_GETARG_BOX_P(1); + + PG_RETURN_BOOL(FPlt(box1->high.y, box2->low.y)); +} + +/* box_overbelow - is the upper edge of box1 at or below + * the upper edge of box2? + */ +Datum +box_overbelow(PG_FUNCTION_ARGS) +{ + BOX *box1 = PG_GETARG_BOX_P(0); + BOX *box2 = PG_GETARG_BOX_P(1); + + PG_RETURN_BOOL(FPle(box1->high.y, box2->high.y)); +} + +/* box_above - is box1 strictly above box2? + */ +Datum +box_above(PG_FUNCTION_ARGS) +{ + BOX *box1 = PG_GETARG_BOX_P(0); + BOX *box2 = PG_GETARG_BOX_P(1); + + PG_RETURN_BOOL(FPgt(box1->low.y, box2->high.y)); +} + +/* box_overabove - is the lower edge of box1 at or above + * the lower edge of box2? + */ +Datum +box_overabove(PG_FUNCTION_ARGS) +{ + BOX *box1 = PG_GETARG_BOX_P(0); + BOX *box2 = PG_GETARG_BOX_P(1); + + PG_RETURN_BOOL(FPge(box1->low.y, box2->low.y)); +} + /* box_contained - is box1 contained by box2? */ Datum @@ -650,9 +696,14 @@ box_contain(PG_FUNCTION_ARGS) /* box_positionop - * is box1 entirely {above,below} box2? + * + * box_below_eq and box_above_eq are obsolete versions that (probably + * erroneously) accept the equal-boundaries case. Since these are not + * in sync with the box_left and box_right code, they are deprecated and + * not supported in the PG 8.1 rtree operator class extension. */ Datum -box_below(PG_FUNCTION_ARGS) +box_below_eq(PG_FUNCTION_ARGS) { BOX *box1 = PG_GETARG_BOX_P(0); BOX *box2 = PG_GETARG_BOX_P(1); @@ -661,7 +712,7 @@ box_below(PG_FUNCTION_ARGS) } Datum -box_above(PG_FUNCTION_ARGS) +box_above_eq(PG_FUNCTION_ARGS) { BOX *box1 = PG_GETARG_BOX_P(0); BOX *box2 = PG_GETARG_BOX_P(1); @@ -3504,7 +3555,7 @@ poly_left(PG_FUNCTION_ARGS) /*------------------------------------------------------- * Is polygon A overlapping or left of polygon B? i.e. is - * the left most point of A left of the right most point + * the right most point of A at or left of the right most point * of B? *-------------------------------------------------------*/ Datum @@ -3514,7 +3565,7 @@ poly_overleft(PG_FUNCTION_ARGS) POLYGON *polyb = PG_GETARG_POLYGON_P(1); bool result; - result = polya->boundbox.low.x <= polyb->boundbox.high.x; + result = polya->boundbox.high.x <= polyb->boundbox.high.x; /* * Avoid leaking memory for toasted inputs ... needed for rtree @@ -3552,7 +3603,7 @@ poly_right(PG_FUNCTION_ARGS) /*------------------------------------------------------- * Is polygon A overlapping or right of polygon B? i.e. is - * the right most point of A right of the left most point + * the left most point of A at or right of the left most point * of B? *-------------------------------------------------------*/ Datum @@ -3562,7 +3613,31 @@ poly_overright(PG_FUNCTION_ARGS) POLYGON *polyb = PG_GETARG_POLYGON_P(1); bool result; - result = polya->boundbox.high.x > polyb->boundbox.low.x; + result = polya->boundbox.low.x >= polyb->boundbox.low.x; + + /* + * Avoid leaking memory for toasted inputs ... needed for rtree + * indexes + */ + PG_FREE_IF_COPY(polya, 0); + PG_FREE_IF_COPY(polyb, 1); + + PG_RETURN_BOOL(result); +} + +/*------------------------------------------------------- + * Is polygon A strictly below polygon B? i.e. is + * the upper most point of A below the lower most point + * of B? + *-------------------------------------------------------*/ +Datum +poly_below(PG_FUNCTION_ARGS) +{ + POLYGON *polya = PG_GETARG_POLYGON_P(0); + POLYGON *polyb = PG_GETARG_POLYGON_P(1); + bool result; + + result = polya->boundbox.high.y < polyb->boundbox.low.y; /* * Avoid leaking memory for toasted inputs ... needed for rtree @@ -3574,6 +3649,79 @@ poly_overright(PG_FUNCTION_ARGS) PG_RETURN_BOOL(result); } +/*------------------------------------------------------- + * Is polygon A overlapping or below polygon B? i.e. is + * the upper most point of A at or below the upper most point + * of B? + *-------------------------------------------------------*/ +Datum +poly_overbelow(PG_FUNCTION_ARGS) +{ + POLYGON *polya = PG_GETARG_POLYGON_P(0); + POLYGON *polyb = PG_GETARG_POLYGON_P(1); + bool result; + + result = polya->boundbox.high.y <= polyb->boundbox.high.y; + + /* + * Avoid leaking memory for toasted inputs ... needed for rtree + * indexes + */ + PG_FREE_IF_COPY(polya, 0); + PG_FREE_IF_COPY(polyb, 1); + + PG_RETURN_BOOL(result); +} + +/*------------------------------------------------------- + * Is polygon A strictly above polygon B? i.e. is + * the lower most point of A above the upper most point + * of B? + *-------------------------------------------------------*/ +Datum +poly_above(PG_FUNCTION_ARGS) +{ + POLYGON *polya = PG_GETARG_POLYGON_P(0); + POLYGON *polyb = PG_GETARG_POLYGON_P(1); + bool result; + + result = polya->boundbox.low.y > polyb->boundbox.high.y; + + /* + * Avoid leaking memory for toasted inputs ... needed for rtree + * indexes + */ + PG_FREE_IF_COPY(polya, 0); + PG_FREE_IF_COPY(polyb, 1); + + PG_RETURN_BOOL(result); +} + +/*------------------------------------------------------- + * Is polygon A overlapping or above polygon B? i.e. is + * the lower most point of A at or above the lower most point + * of B? + *-------------------------------------------------------*/ +Datum +poly_overabove(PG_FUNCTION_ARGS) +{ + POLYGON *polya = PG_GETARG_POLYGON_P(0); + POLYGON *polyb = PG_GETARG_POLYGON_P(1); + bool result; + + result = polya->boundbox.low.y >= polyb->boundbox.low.y; + + /* + * Avoid leaking memory for toasted inputs ... needed for rtree + * indexes + */ + PG_FREE_IF_COPY(polya, 0); + PG_FREE_IF_COPY(polyb, 1); + + PG_RETURN_BOOL(result); +} + + /*------------------------------------------------------- * Is polygon A the same as polygon B? i.e. are all the * points the same? @@ -3607,7 +3755,7 @@ poly_same(PG_FUNCTION_ARGS) * Determine if polygon A overlaps polygon B by determining if * their bounding boxes overlap. * - * XXX ought to do a more correct check? + * XXX ought to do a more correct check! *-----------------------------------------------------------------*/ Datum poly_overlap(PG_FUNCTION_ARGS) @@ -3696,8 +3844,7 @@ poly_contain(PG_FUNCTION_ARGS) /*----------------------------------------------------------------- - * Determine if polygon A is contained by polygon B by determining - * if A's bounding box is contained by B's bounding box. + * Determine if polygon A is contained by polygon B *-----------------------------------------------------------------*/ Datum poly_contained(PG_FUNCTION_ARGS) @@ -3705,6 +3852,7 @@ poly_contained(PG_FUNCTION_ARGS) Datum polya = PG_GETARG_DATUM(0); Datum polyb = PG_GETARG_DATUM(1); + /* Just switch the arguments and pass it off to poly_contain */ PG_RETURN_DATUM(DirectFunctionCall2(poly_contain, polyb, polya)); } @@ -4384,7 +4532,7 @@ circle_overlap(PG_FUNCTION_ARGS) circle1->radius + circle2->radius)); } -/* circle_overleft - is the right edge of circle1 to the left of +/* circle_overleft - is the right edge of circle1 at or left of * the right edge of circle2? */ Datum @@ -4405,7 +4553,7 @@ circle_left(PG_FUNCTION_ARGS) CIRCLE *circle1 = PG_GETARG_CIRCLE_P(0); CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1); - PG_RETURN_BOOL(FPle((circle1->center.x + circle1->radius), + PG_RETURN_BOOL(FPlt((circle1->center.x + circle1->radius), (circle2->center.x - circle2->radius))); } @@ -4417,11 +4565,11 @@ circle_right(PG_FUNCTION_ARGS) CIRCLE *circle1 = PG_GETARG_CIRCLE_P(0); CIRCLE *circle2 = PG_GETARG_CIRCLE_P(1); - PG_RETURN_BOOL(FPge((circle1->center.x - circle1->radius), + PG_RETURN_BOOL(FPgt((circle1->center.x - circle1->radius), (circle2->center.x + circle2->radius))); } -/* circle_overright - is the left edge of circle1 to the right of +/* circle_overright - is the left edge of circle1 at or right of * the left edge of circle2? */ Datum diff --git a/src/include/access/rtree.h b/src/include/access/rtree.h index 744f116fe3..d5aa103af7 100644 --- a/src/include/access/rtree.h +++ b/src/include/access/rtree.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.40 2005/06/24 00:18:52 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/rtree.h,v 1.41 2005/06/24 20:53:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,7 @@ #include "utils/rel.h" /* see rtstrat.c for what all this is about */ -#define RTNStrategies 8 +#define RTNStrategies 12 #define RTLeftStrategyNumber 1 #define RTOverLeftStrategyNumber 2 #define RTOverlapStrategyNumber 3 @@ -30,6 +30,10 @@ #define RTSameStrategyNumber 6 #define RTContainsStrategyNumber 7 #define RTContainedByStrategyNumber 8 +#define RTOverBelowStrategyNumber 9 +#define RTBelowStrategyNumber 10 +#define RTAboveStrategyNumber 11 +#define RTOverAboveStrategyNumber 12 #define RTNProcs 3 #define RT_UNION_PROC 1 diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 84e07725cf..ab1b6c0a5d 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.280 2005/06/21 04:02:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.281 2005/06/24 20:53:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200506202 +#define CATALOG_VERSION_NO 200506241 #endif diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index 2cb2264328..b5ecdd9c73 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.35 2005/06/20 10:29:37 teodor Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.36 2005/06/24 20:53:31 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -104,7 +104,7 @@ typedef FormData_pg_am *Form_pg_am; * ---------------- */ -DATA(insert OID = 402 ( rtree 8 3 0 f f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate )); +DATA(insert OID = 402 ( rtree 12 3 0 f f f f f rtinsert rtbeginscan rtgettuple rtgetmulti rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete - rtcostestimate )); DESCR("r-tree index access method"); DATA(insert OID = 403 ( btree 5 1 1 t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate )); DESCR("b-tree index access method"); diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index 2b30f67a16..e318898f4f 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -23,7 +23,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.63 2005/04/14 01:38:20 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.64 2005/06/24 20:53:31 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -84,27 +84,35 @@ typedef FormData_pg_amop *Form_pg_amop; * rtree box_ops */ -DATA(insert ( 425 0 1 f 493 )); -DATA(insert ( 425 0 2 f 494 )); -DATA(insert ( 425 0 3 f 500 )); -DATA(insert ( 425 0 4 f 495 )); -DATA(insert ( 425 0 5 f 496 )); -DATA(insert ( 425 0 6 f 499 )); -DATA(insert ( 425 0 7 f 498 )); -DATA(insert ( 425 0 8 f 497 )); +DATA(insert ( 425 0 1 f 493 )); +DATA(insert ( 425 0 2 f 494 )); +DATA(insert ( 425 0 3 f 500 )); +DATA(insert ( 425 0 4 f 495 )); +DATA(insert ( 425 0 5 f 496 )); +DATA(insert ( 425 0 6 f 499 )); +DATA(insert ( 425 0 7 f 498 )); +DATA(insert ( 425 0 8 f 497 )); +DATA(insert ( 425 0 9 f 2571 )); +DATA(insert ( 425 0 10 f 2570 )); +DATA(insert ( 425 0 11 f 2573 )); +DATA(insert ( 425 0 12 f 2572 )); /* * rtree poly_ops (supports polygons) */ -DATA(insert ( 1993 0 1 f 485 )); -DATA(insert ( 1993 0 2 f 486 )); -DATA(insert ( 1993 0 3 f 492 )); -DATA(insert ( 1993 0 4 f 487 )); -DATA(insert ( 1993 0 5 f 488 )); -DATA(insert ( 1993 0 6 f 491 )); -DATA(insert ( 1993 0 7 f 490 )); -DATA(insert ( 1993 0 8 f 489 )); +DATA(insert ( 1993 0 1 f 485 )); +DATA(insert ( 1993 0 2 f 486 )); +DATA(insert ( 1993 0 3 f 492 )); +DATA(insert ( 1993 0 4 f 487 )); +DATA(insert ( 1993 0 5 f 488 )); +DATA(insert ( 1993 0 6 f 491 )); +DATA(insert ( 1993 0 7 f 490 )); +DATA(insert ( 1993 0 8 f 489 )); +DATA(insert ( 1993 0 9 f 2575 )); +DATA(insert ( 1993 0 10 f 2574 )); +DATA(insert ( 1993 0 11 f 2577 )); +DATA(insert ( 1993 0 12 f 2576 )); /* * btree int2_ops diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index ac098366ed..f87b6a0738 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.133 2005/06/08 21:15:28 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.134 2005/06/24 20:53:31 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -373,8 +373,8 @@ DATA(insert OID = 796 ( ">=" PGNSP PGUID b f 602 602 16 795 0 0 0 0 0 p DATA(insert OID = 797 ( "#" PGNSP PGUID l f 0 602 23 0 0 0 0 0 0 path_npoints - - )); DATA(insert OID = 798 ( "?#" PGNSP PGUID b f 602 602 16 0 0 0 0 0 0 path_inter - - )); DATA(insert OID = 799 ( "@-@" PGNSP PGUID l f 0 602 701 0 0 0 0 0 0 path_length - - )); -DATA(insert OID = 800 ( ">^" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_above positionsel positionjoinsel )); -DATA(insert OID = 801 ( "<^" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_below positionsel positionjoinsel )); +DATA(insert OID = 800 ( ">^" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_above_eq positionsel positionjoinsel )); +DATA(insert OID = 801 ( "<^" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_below_eq positionsel positionjoinsel )); DATA(insert OID = 802 ( "?#" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_overlap areasel areajoinsel )); DATA(insert OID = 803 ( "#" PGNSP PGUID b f 603 603 603 0 0 0 0 0 0 box_intersect - - )); DATA(insert OID = 804 ( "+" PGNSP PGUID b f 603 600 603 0 0 0 0 0 0 box_add - - )); @@ -865,6 +865,16 @@ DATA(insert OID = 2553 ( "+" PGNSP PGUID b f 1186 1114 1114 2066 0 0 0 0 0 i DATA(insert OID = 2554 ( "+" PGNSP PGUID b f 1186 1184 1184 1327 0 0 0 0 0 interval_pl_timestamptz - - )); DATA(insert OID = 2555 ( "+" PGNSP PGUID b f 23 1082 1082 1100 0 0 0 0 0 integer_pl_date - - )); +/* new operators for Y-direction rtree opclasses */ +DATA(insert OID = 2570 ( "<<|" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_below positionsel positionjoinsel )); +DATA(insert OID = 2571 ( "&<|" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_overbelow positionsel positionjoinsel )); +DATA(insert OID = 2572 ( "|&>" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_overabove positionsel positionjoinsel )); +DATA(insert OID = 2573 ( "|>>" PGNSP PGUID b f 603 603 16 0 0 0 0 0 0 box_above positionsel positionjoinsel )); +DATA(insert OID = 2574 ( "<<|" PGNSP PGUID b f 604 604 16 0 0 0 0 0 0 poly_below positionsel positionjoinsel )); +DATA(insert OID = 2575 ( "&<|" PGNSP PGUID b f 604 604 16 0 0 0 0 0 0 poly_overbelow positionsel positionjoinsel )); +DATA(insert OID = 2576 ( "|&>" PGNSP PGUID b f 604 604 16 0 0 0 0 0 0 poly_overabove positionsel positionjoinsel )); +DATA(insert OID = 2577 ( "|>>" PGNSP PGUID b f 604 604 16 0 0 0 0 0 0 poly_above positionsel positionjoinsel )); + /* * function prototypes diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index f219065b61..892835075a 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.369 2005/06/20 10:29:37 teodor Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.370 2005/06/24 20:53:32 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -241,10 +241,10 @@ DESCR("convert int2 to text"); DATA(insert OID = 114 ( text PGNSP PGUID 12 f f t f i 1 25 "26" _null_ _null_ _null_ oid_text - _null_ )); DESCR("convert oid to text"); -DATA(insert OID = 115 ( box_above PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_above - _null_ )); -DESCR("is above"); -DATA(insert OID = 116 ( box_below PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_below - _null_ )); -DESCR("is below"); +DATA(insert OID = 115 ( box_above_eq PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_above_eq - _null_ )); +DESCR("is above (allows touching)"); +DATA(insert OID = 116 ( box_below_eq PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_below_eq - _null_ )); +DESCR("is below (allows touching)"); DATA(insert OID = 117 ( point_in PGNSP PGUID 12 f f t f i 1 600 "2275" _null_ _null_ _null_ point_in - _null_ )); DESCR("I/O"); @@ -3658,6 +3658,24 @@ DESCR("current value from last used sequence"); DATA(insert OID = 2560 ( pg_postmaster_start_time PGNSP PGUID 12 f f t f s 0 1184 "" _null_ _null_ _null_ pgsql_postmaster_start_time - _null_ )); DESCR("postmaster start time"); +/* new functions for Y-direction rtree opclasses */ +DATA(insert OID = 2562 ( box_below PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_below - _null_ )); +DESCR("is below"); +DATA(insert OID = 2563 ( box_overbelow PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_overbelow - _null_ )); +DESCR("overlaps or is below"); +DATA(insert OID = 2564 ( box_overabove PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_overabove - _null_ )); +DESCR("overlaps or is above"); +DATA(insert OID = 2565 ( box_above PGNSP PGUID 12 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_above - _null_ )); +DESCR("is above"); +DATA(insert OID = 2566 ( poly_below PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_below - _null_ )); +DESCR("is below"); +DATA(insert OID = 2567 ( poly_overbelow PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_overbelow - _null_ )); +DESCR("overlaps or is below"); +DATA(insert OID = 2568 ( poly_overabove PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_overabove - _null_ )); +DESCR("overlaps or is above"); +DATA(insert OID = 2569 ( poly_above PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_above - _null_ )); +DESCR("is above"); + /* * Symbolic values for provolatile column: these indicate whether the result diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index 64ba6d22eb..9bf7ce0899 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.46 2004/12/31 22:03:46 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.47 2005/06/24 20:53:33 tgl Exp $ * * NOTE * These routines do *not* use the float types from adt/. @@ -278,14 +278,18 @@ extern Datum box_recv(PG_FUNCTION_ARGS); extern Datum box_send(PG_FUNCTION_ARGS); extern Datum box_same(PG_FUNCTION_ARGS); extern Datum box_overlap(PG_FUNCTION_ARGS); -extern Datum box_overleft(PG_FUNCTION_ARGS); extern Datum box_left(PG_FUNCTION_ARGS); +extern Datum box_overleft(PG_FUNCTION_ARGS); extern Datum box_right(PG_FUNCTION_ARGS); extern Datum box_overright(PG_FUNCTION_ARGS); -extern Datum box_contained(PG_FUNCTION_ARGS); -extern Datum box_contain(PG_FUNCTION_ARGS); extern Datum box_below(PG_FUNCTION_ARGS); +extern Datum box_overbelow(PG_FUNCTION_ARGS); extern Datum box_above(PG_FUNCTION_ARGS); +extern Datum box_overabove(PG_FUNCTION_ARGS); +extern Datum box_contained(PG_FUNCTION_ARGS); +extern Datum box_contain(PG_FUNCTION_ARGS); +extern Datum box_below_eq(PG_FUNCTION_ARGS); +extern Datum box_above_eq(PG_FUNCTION_ARGS); extern Datum box_lt(PG_FUNCTION_ARGS); extern Datum box_gt(PG_FUNCTION_ARGS); extern Datum box_eq(PG_FUNCTION_ARGS); @@ -343,6 +347,10 @@ extern Datum poly_left(PG_FUNCTION_ARGS); extern Datum poly_overleft(PG_FUNCTION_ARGS); extern Datum poly_right(PG_FUNCTION_ARGS); extern Datum poly_overright(PG_FUNCTION_ARGS); +extern Datum poly_below(PG_FUNCTION_ARGS); +extern Datum poly_overbelow(PG_FUNCTION_ARGS); +extern Datum poly_above(PG_FUNCTION_ARGS); +extern Datum poly_overabove(PG_FUNCTION_ARGS); extern Datum poly_same(PG_FUNCTION_ARGS); extern Datum poly_overlap(PG_FUNCTION_ARGS); extern Datum poly_contain(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index e2e59d675e..05bfe054d7 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -803,6 +803,10 @@ ORDER BY 1, 2, 3; 402 | 6 | ~= 402 | 7 | ~ 402 | 8 | @ + 402 | 9 | &<| + 402 | 10 | <<| + 402 | 11 | |>> + 402 | 12 | |&> 403 | 1 | < 403 | 1 | ~<~ 403 | 2 | <= @@ -815,7 +819,7 @@ ORDER BY 1, 2, 3; 403 | 5 | ~>~ 405 | 1 | = 405 | 1 | ~=~ -(20 rows) +(24 rows) -- Check that all operators linked to by opclass entries have selectivity -- estimators. This is not absolutely required, but it seems a reasonable diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out index e9032d4dbc..3d761e527f 100644 --- a/src/test/regress/expected/polygon.out +++ b/src/test/regress/expected/polygon.out @@ -67,9 +67,8 @@ SELECT '' AS two, p.* WHERE p.f1 &> '(3.0,1.0),(3.0,3.0),(1.0,0.0)'; two | f1 -----+--------------------- - | ((2,0),(2,4),(0,0)) | ((3,1),(3,3),(1,0)) -(2 rows) +(1 row) -- left of SELECT '' AS one, p.* @@ -144,10 +143,10 @@ SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' << polygon '(3.0,1.0),(3.0,3.0),( (1 row) -- right overlap -SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' &> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS true; - true ------- - t +SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' &> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; + false +------- + f (1 row) -- right of diff --git a/src/test/regress/sql/polygon.sql b/src/test/regress/sql/polygon.sql index 1e20f38175..5ac3343cb1 100644 --- a/src/test/regress/sql/polygon.sql +++ b/src/test/regress/sql/polygon.sql @@ -100,7 +100,7 @@ SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' << polygon '(3.0,1.0),(3.0,3.0),( SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' << polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS true; -- right overlap -SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' &> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS true; +SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' &> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; -- right of SELECT polygon '(2.0,0.0),(2.0,4.0),(0.0,0.0)' >> polygon '(3.0,1.0),(3.0,3.0),(1.0,0.0)' AS false; -- 2.40.0