diff --git a/contrib/rtree_gist/rtree_gist.c b/contrib/rtree_gist/rtree_gist.c
index f4ce58460fbeee1fec02d0f324f4d23ecf5dbb4d..d6292b803e83268aecefcaefb275c575ec313bdc 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 2fc38a7024e459e25671b15e541ed497453f6cc0..e59edcacff0583d0b8b16aa0af662d059e9dba1a 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 02ca4f896e3c5ab29be0d1e4808ea68131226b01..8c7a48308ec6e2ac979ebb34a14cd7f8e299a261 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 41f87d60f66ba984348c849941c7b5708fc63288..3bb530b60e8c64120d18da08e19b068200519219 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 0b254324485b6324e3d75e379302223979fbb8db..5764198e271a3d3de27cc51481502d2c10713099 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 c7104c9520ce26934046995bb509eb8d693d8959..1b72d980da66bb8b45df2cd27d5f44144e5943dc 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 4aa19828a852a4797627e71d991c1287df9087bc..e2794482633f768dafcc40913a0f0f259d509641 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 744f116fe37470e2964874a82e84b1fea08b4643..d5aa103af7c0deb19d646bb33388eb96d872e0a3 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 84e07725cf860faf9950961f6b2432b88cdc354d..ab1b6c0a5dd7eed4dbb167250755544e93ce2934 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 2cb22643280b8c8a16a8b5f44d515933d5844f72..b5ecdd9c7389c81963122a4b51e68e6416eb5ab4 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 2b30f67a16a8d33280d90fdca44a5dcc0040dd95..e318898f4f6c21b490680a6f782a1c3b5d469789 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 ac098366ed3d1b2d3a94d7924be35a97cb17d05a..f87b6a07383ef40d747a8548600301aa6e988b23 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 f219065b61ce0a8cc13454213ff3a5c42676a6ac..892835075aa1d25d888ace8eb6d4f1cd728dd27f 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 64ba6d22eb1d40037ca84cd9cf152033dd982331..9bf7ce089984e6f997cbe7209c0fb5ebdf54bf4b 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 e2e59d675e67a4dcb2d04d4ede786373bcdae871..05bfe054d7a4a35f91241b23157e0ebedb597da7 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 e9032d4dbcdead66dcf5a91fce12d64286b28c07..3d761e527fb669ede33f6095de3d40f4969c8e4f 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 1e20f38175336742549c8e2fb44594c4fa4897c5..5ac3343cb1cb1d0b962525c01d155e4b3e5bdc6a 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;