From 4cbe473938779ec414d90c2063c4398e68a70838 Mon Sep 17 00:00:00 2001
From: Teodor Sigaev <teodor@sigaev.ru>
Date: Thu, 14 Jan 2010 16:31:09 +0000
Subject: [PATCH] Add point_ops opclass for GiST.

---
 src/backend/access/gist/gistproc.c         | 174 ++++++++++++++++++-
 src/backend/utils/adt/geo_ops.c            |  12 +-
 src/include/catalog/catversion.h           |   4 +-
 src/include/catalog/pg_amop.h              |  18 +-
 src/include/catalog/pg_amproc.h            |   9 +-
 src/include/catalog/pg_opclass.h           |   3 +-
 src/include/catalog/pg_operator.h          |  13 +-
 src/include/catalog/pg_opfamily.h          |   3 +-
 src/include/catalog/pg_proc.h              |   8 +-
 src/include/utils/geo_decls.h              |   5 +-
 src/test/regress/expected/create_index.out | 190 +++++++++++++++++++++
 src/test/regress/expected/opr_sanity.out   |  10 +-
 src/test/regress/expected/point.out        |  18 ++
 src/test/regress/expected/sanity_check.out |   2 +-
 src/test/regress/sql/create_index.sql      |  56 ++++++
 src/test/regress/sql/point.sql             |   6 +
 16 files changed, 511 insertions(+), 20 deletions(-)

diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index cf3442763ec..18ee0259a59 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	$PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.19 2010/01/02 16:57:34 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.20 2010/01/14 16:31:09 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,7 +165,8 @@ gist_box_compress(PG_FUNCTION_ARGS)
 }
 
 /*
- * GiST DeCompress method for boxes (also used for polygons and circles)
+ * GiST DeCompress method for boxes (also used for points, polygons
+ * and circles)
  *
  * do not do anything --- we just use the stored box as is.
  */
@@ -176,7 +177,7 @@ gist_box_decompress(PG_FUNCTION_ARGS)
 }
 
 /*
- * The GiST Penalty method for boxes
+ * The GiST Penalty method for boxes (also used for points)
  *
  * As in the R-tree paper, we use change in area as our penalty metric
  */
@@ -341,6 +342,8 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
  *
  * New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree',
  * C.H.Ang and T.C.Tan
+ *
+ * This is used for both boxes and points.
  */
 Datum
 gist_box_picksplit(PG_FUNCTION_ARGS)
@@ -533,6 +536,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 
 /*
  * Equality method
+ *
+ * This is used for both boxes and points.
  */
 Datum
 gist_box_same(PG_FUNCTION_ARGS)
@@ -872,3 +877,166 @@ gist_circle_consistent(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(result);
 }
+
+/**************************************************
+ * Point ops
+ **************************************************/
+
+Datum
+gist_point_compress(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+
+	if (entry->leafkey)			/* Point, actually */
+	{
+		BOX	   *box = palloc(sizeof(BOX));
+		Point  *point = DatumGetPointP(entry->key);
+		GISTENTRY  *retval = palloc(sizeof(GISTENTRY));
+
+		box->high = box->low = *point;
+
+		gistentryinit(*retval, BoxPGetDatum(box),
+					  entry->rel, entry->page, entry->offset, FALSE);
+
+		PG_RETURN_POINTER(retval);
+	}
+
+	PG_RETURN_POINTER(entry);
+}
+
+static bool
+gist_point_consistent_internal(StrategyNumber strategy,
+										   bool isLeaf, BOX *key, Point *query)
+{
+	bool result = false;
+
+	switch (strategy)
+	{
+		case RTLeftStrategyNumber:
+			result = FPlt(key->low.x, query->x);
+			break;
+		case RTRightStrategyNumber:
+			result = FPgt(key->high.x, query->x);
+			break;
+		case RTAboveStrategyNumber:
+			result = FPgt(key->high.y, query->y);
+			break;
+		case RTBelowStrategyNumber:
+			result = FPlt(key->low.y, query->y);
+			break;
+		case RTSameStrategyNumber:
+			if (isLeaf)
+			{
+				result = FPeq(key->low.x, query->x)
+					&& FPeq(key->low.y, query->y);
+			}
+			else
+			{
+				result = (query->x <= key->high.x && query->x >= key->low.x &&
+						  query->y <= key->high.y && query->y >= key->low.y);
+			}
+			break;
+		default:
+			elog(ERROR, "unknown strategy number: %d", strategy);
+	}
+
+	return result;
+}
+
+#define GeoStrategyNumberOffset		20
+#define PointStrategyNumberGroup	0
+#define BoxStrategyNumberGroup		1
+#define PolygonStrategyNumberGroup	2
+#define CircleStrategyNumberGroup	3
+
+Datum
+gist_point_consistent(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	StrategyNumber	strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+	bool		result;
+	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
+	StrategyNumber	strategyGroup = strategy / GeoStrategyNumberOffset;
+
+	switch (strategyGroup)
+	{
+		case PointStrategyNumberGroup:
+			result = gist_point_consistent_internal(strategy % GeoStrategyNumberOffset,
+													GIST_LEAF(entry),
+													DatumGetBoxP(entry->key),
+													PG_GETARG_POINT_P(1));
+			*recheck = false;
+			break;
+		case BoxStrategyNumberGroup:
+			result = DatumGetBool(DirectFunctionCall5(
+											gist_box_consistent,
+											PointerGetDatum(entry),
+											PG_GETARG_DATUM(1),
+											Int16GetDatum(RTOverlapStrategyNumber),
+											0, PointerGetDatum(recheck)));
+			break;
+		case PolygonStrategyNumberGroup:
+			{
+				POLYGON    *query = PG_GETARG_POLYGON_P(1);
+
+				result = DatumGetBool(DirectFunctionCall5(
+												gist_poly_consistent,
+												PointerGetDatum(entry),
+												PolygonPGetDatum(query),
+												Int16GetDatum(RTOverlapStrategyNumber),
+												0, PointerGetDatum(recheck)));
+
+				if (GIST_LEAF(entry) && result)
+				{
+					/*
+					 * We are on leaf page and quick check shows overlapping
+					 * of polygon's bounding box and point
+					 */
+					BOX *box = DatumGetBoxP(entry->key);
+
+					Assert(box->high.x == box->low.x
+						&& box->high.y == box->low.y);
+					result = DatumGetBool(DirectFunctionCall2(
+												poly_contain_pt,
+												PolygonPGetDatum(query),
+												PointPGetDatum(&box->high)));
+					*recheck = false;
+				}
+			}
+			break;
+		case CircleStrategyNumberGroup:
+			{
+				CIRCLE *query = PG_GETARG_CIRCLE_P(1);
+
+				result = DatumGetBool(DirectFunctionCall5(
+												gist_circle_consistent,
+												PointerGetDatum(entry),
+												CirclePGetDatum(query),
+												Int16GetDatum(RTOverlapStrategyNumber),
+												0, PointerGetDatum(recheck)));
+
+				if (GIST_LEAF(entry) && result)
+				{
+					/*
+					 * We are on leaf page and quick check shows overlapping
+					 * of polygon's bounding box and point
+					 */
+					BOX *box = DatumGetBoxP(entry->key);
+
+					Assert(box->high.x == box->low.x
+						&& box->high.y == box->low.y);
+					result = DatumGetBool(DirectFunctionCall2(
+												circle_contain_pt,
+												CirclePGetDatum(query),
+												PointPGetDatum(&box->high)));
+					*recheck = false;
+				}
+			}
+			break;
+		default:
+			result = false;			/* silence compiler warning */
+			elog(ERROR, "unknown strategy number: %d", strategy);
+	}
+
+	PG_RETURN_BOOL(result);
+}
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 2eb72428819..35f1a13ab67 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.106 2010/01/02 16:57:54 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.107 2010/01/14 16:31:09 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3202,6 +3202,16 @@ on_pb(PG_FUNCTION_ARGS)
 				   pt->y <= box->high.y && pt->y >= box->low.y);
 }
 
+Datum
+box_contain_pt(PG_FUNCTION_ARGS) 
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
+				   pt->y <= box->high.y && pt->y >= box->low.y);
+}
+
 /* on_ppath -
  *		Whether a point lies within (on) a polyline.
  *		If open, we have to (groan) check each segment.
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 5217147f363..e981823320c 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.571 2010/01/12 02:42:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.572 2010/01/14 16:31:09 teodor Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	201001111
+#define CATALOG_VERSION_NO	201001141
 
 #endif
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index b107c6e4bae..1f0c1d81d6b 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -29,7 +29,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.92 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.93 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTES
  *	 the genbki.pl script reads this file and generates .bki
@@ -582,6 +582,22 @@ DATA(insert (	2593   603 603 12 2572	783 ));
 DATA(insert (	2593   603 603 13 2863	783 ));
 DATA(insert (	2593   603 603 14 2862	783 ));
 
+/*
+ * gist point_ops
+ */
+DATA(insert (	1029   600 600 11 506 783 ));
+DATA(insert (	1029   600 600 1  507 783 ));
+DATA(insert (	1029   600 600 5  508 783 ));
+DATA(insert (	1029   600 600 10 509 783 ));
+DATA(insert (	1029   600 600 6  510 783 ));
+DATA(insert (	1029   603 600 27  433 783 ));
+DATA(insert (	1029   600 603 28  511 783 ));
+DATA(insert (	1029   604 600 47 757 783 ));
+DATA(insert (	1029   600 604 48 756 783 ));
+DATA(insert (	1029   718 600 67 759 783 ));
+DATA(insert (	1029   600 718 68 758 783 ));
+
+
 /*
  *	gist poly_ops (supports polygons)
  */
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 739f2c4b64e..0f0f6e1fe0b 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.77 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.78 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTES
  *	  the genbki.pl script reads this file and generates .bki
@@ -197,6 +197,13 @@ DATA(insert (	3702   3615 3615 4 3696 ));
 DATA(insert (	3702   3615 3615 5 3700 ));
 DATA(insert (	3702   3615 3615 6 3697 ));
 DATA(insert (	3702   3615 3615 7 3699 ));
+DATA(insert (	1029   600 600 1 2179 ));
+DATA(insert (	1029   600 600 2 2583 ));
+DATA(insert (	1029   600 600 3 1030 ));
+DATA(insert (	1029   600 600 4 2580 ));
+DATA(insert (	1029   600 600 5 2581 ));
+DATA(insert (	1029   600 600 6 2582 ));
+DATA(insert (	1029   600 600 7 2584 ));
 
 
 /* gin */
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index e5f19c895a8..62811213653 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -28,7 +28,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.87 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.88 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTES
  *	  the genbki.pl script reads this file and generates .bki
@@ -170,6 +170,7 @@ DATA(insert (	403		reltime_ops			PGNSP PGUID 2233  703 t 0 ));
 DATA(insert (	403		tinterval_ops		PGNSP PGUID 2234  704 t 0 ));
 DATA(insert (	405		aclitem_ops			PGNSP PGUID 2235 1033 t 0 ));
 DATA(insert (	783		box_ops				PGNSP PGUID 2593  603 t 0 ));
+DATA(insert (	783		point_ops			PGNSP PGUID 1029  600 t 603 ));
 DATA(insert (	783		poly_ops			PGNSP PGUID 2594  604 t 603 ));
 DATA(insert (	783		circle_ops			PGNSP PGUID 2595  718 t 603 ));
 DATA(insert (	2742	_int4_ops			PGNSP PGUID 2745  1007 t 23 ));
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index fd59882006d..25429cf1515 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.169 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.170 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTES
  *	  the genbki.pl script reads this file and generates .bki
@@ -171,7 +171,8 @@ DATA(insert OID = 507 (  "<<"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_left p
 DATA(insert OID = 508 (  ">>"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_right positionsel positionjoinsel ));
 DATA(insert OID = 509 (  "<^"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_below positionsel positionjoinsel ));
 DATA(insert OID = 510 (  "~="	   PGNSP PGUID b f f 600 600	16 510 713 point_eq eqsel eqjoinsel ));
-DATA(insert OID = 511 (  "<@"	   PGNSP PGUID b f f 600 603	16	 0	 0 on_pb - - ));
+DATA(insert OID = 511 (  "<@"	   PGNSP PGUID b f f 600 603	16 433	 0 on_pb contsel contjoinsel ));
+DATA(insert OID = 433 (  "@>"	   PGNSP PGUID b f f 603 600	16 511	 0 box_contain_pt contsel contjoinsel ));
 DATA(insert OID = 512 (  "<@"	   PGNSP PGUID b f f 600 602	16 755	 0 on_ppath - - ));
 DATA(insert OID = 513 (  "@@"	   PGNSP PGUID l f f	 0 603 600	 0	 0 box_center - - ));
 DATA(insert OID = 514 (  "*"	   PGNSP PGUID b f f	23	23	23 514	 0 int4mul - - ));
@@ -359,10 +360,10 @@ DATA(insert OID = 737 (  "-"	   PGNSP PGUID b f f	602  600	602    0  0 path_sub_
 DATA(insert OID = 738 (  "*"	   PGNSP PGUID b f f	602  600	602    0  0 path_mul_pt - - ));
 DATA(insert OID = 739 (  "/"	   PGNSP PGUID b f f	602  600	602    0  0 path_div_pt - - ));
 DATA(insert OID = 755 (  "@>"	   PGNSP PGUID b f f	602  600	 16  512  0 path_contain_pt - - ));
-DATA(insert OID = 756 (  "<@"	   PGNSP PGUID b f f	600  604	 16  757  0 pt_contained_poly - - ));
-DATA(insert OID = 757 (  "@>"	   PGNSP PGUID b f f	604  600	 16  756  0 poly_contain_pt - - ));
-DATA(insert OID = 758 (  "<@"	   PGNSP PGUID b f f	600  718	 16  759  0 pt_contained_circle - - ));
-DATA(insert OID = 759 (  "@>"	   PGNSP PGUID b f f	718  600	 16  758  0 circle_contain_pt - - ));
+DATA(insert OID = 756 (  "<@"	   PGNSP PGUID b f f	600  604	 16  757  0 pt_contained_poly contsel contjoinsel ));
+DATA(insert OID = 757 (  "@>"	   PGNSP PGUID b f f	604  600	 16  756  0 poly_contain_pt contsel contjoinsel ));
+DATA(insert OID = 758 (  "<@"	   PGNSP PGUID b f f	600  718	 16  759  0 pt_contained_circle contsel contjoinsel ));
+DATA(insert OID = 759 (  "@>"	   PGNSP PGUID b f f	718  600	 16  758  0 circle_contain_pt contsel contjoinsel ));
 
 DATA(insert OID = 773 (  "@"	   PGNSP PGUID l f f	 0	23	23	 0	 0 int4abs - - ));
 
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index aa93df8eca2..5db9cb6f68b 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.13 2010/01/05 01:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.14 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTES
  *	  the genbki.pl script reads this file and generates .bki
@@ -127,6 +127,7 @@ DATA(insert OID = 2235 (	405		aclitem_ops		PGNSP PGUID ));
 DATA(insert OID = 2593 (	783		box_ops			PGNSP PGUID ));
 DATA(insert OID = 2594 (	783		poly_ops		PGNSP PGUID ));
 DATA(insert OID = 2595 (	783		circle_ops		PGNSP PGUID ));
+DATA(insert OID = 1029 (	783		point_ops		PGNSP PGUID ));
 DATA(insert OID = 2745 (	2742	array_ops		PGNSP PGUID ));
 DATA(insert OID = 2968 (	403		uuid_ops		PGNSP PGUID ));
 DATA(insert OID = 2969 (	405		uuid_ops		PGNSP PGUID ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index b39c02f7f28..7a16e3faa73 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.560 2010/01/07 20:17:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.561 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTES
  *	  The script catalog/genbki.pl reads this file and generates .bki
@@ -396,6 +396,8 @@ DATA(insert OID = 191 (  box_right		   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "
 DESCR("is right of");
 DATA(insert OID = 192 (  box_contained	   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_contained _null_ _null_ _null_ ));
 DESCR("is contained by?");
+DATA(insert OID = 193 (  box_contain_pt	   PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ ));
+DESCR("contains?");
 
 /* OIDS 200 - 299 */
 
@@ -4205,6 +4207,10 @@ DATA(insert OID = 2591 (  gist_circle_consistent PGNSP PGUID 12 1 0 0 f f f t f
 DESCR("GiST support");
 DATA(insert OID = 2592 (  gist_circle_compress	PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_circle_compress _null_ _null_ _null_ ));
 DESCR("GiST support");
+DATA(insert OID = 1030 (  gist_point_compress	PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_point_compress _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 2179 (  gist_point_consistent	PGNSP PGUID 12 1 0 0 f f f t f i 5 0 16 "2281 603 23 26 2281" _null_ _null_ _null_ _null_	gist_point_consistent _null_ _null_ _null_ ));
+DESCR("GiST support");
 
 /* GIN */
 DATA(insert OID = 2731 (  gingetbitmap	   PGNSP PGUID 12 1 0 0 f f f t f v 2 0 20 "2281 2281" _null_ _null_ _null_ _null_	gingetbitmap _null_ _null_ _null_ ));
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 7863f5e6199..f43d2d5fdcc 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.56 2010/01/02 16:58:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.57 2010/01/14 16:31:09 teodor Exp $
  *
  * NOTE
  *	  These routines do *not* use the float types from adt/.
@@ -290,6 +290,7 @@ 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_contain_pt(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);
@@ -420,6 +421,8 @@ extern Datum gist_poly_compress(PG_FUNCTION_ARGS);
 extern Datum gist_poly_consistent(PG_FUNCTION_ARGS);
 extern Datum gist_circle_compress(PG_FUNCTION_ARGS);
 extern Datum gist_circle_consistent(PG_FUNCTION_ARGS);
+extern Datum gist_point_compress(PG_FUNCTION_ARGS);
+extern Datum gist_point_consistent(PG_FUNCTION_ARGS);
 
 /* geo_selfuncs.c */
 extern Datum areasel(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index b67f4e06f39..22753437040 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -51,6 +51,7 @@ CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops)
 CREATE INDEX grect2ind ON fast_emp4000 USING gist (home_base);
 CREATE INDEX gpolygonind ON polygon_tbl USING gist (f1);
 CREATE INDEX gcircleind ON circle_tbl USING gist (f1);
+CREATE INDEX gpointind ON point_tbl USING gist (f1);
 CREATE TEMP TABLE gpolygon_tbl AS
     SELECT polygon(home_base) AS f1 FROM slow_emp4000;
 INSERT INTO gpolygon_tbl VALUES ( '(1000,0,0,1000)' ); 
@@ -112,6 +113,60 @@ SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle;
      2
 (1 row)
 
+SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)';
+ count 
+-------
+     3
+(1 row)
+
+SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
+ count 
+-------
+     3
+(1 row)
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
+ count 
+-------
+     3
+(1 row)
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
+ count 
+-------
+     1
+(1 row)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
+ count 
+-------
+     3
+(1 row)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
+ count 
+-------
+     2
+(1 row)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
+ count 
+-------
+     1
+(1 row)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
+ count 
+-------
+     3
+(1 row)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
+ count 
+-------
+     1
+(1 row)
+
 SET enable_seqscan = OFF;
 SET enable_indexscan = ON;
 SET enable_bitmapscan = ON;
@@ -245,6 +300,141 @@ SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle;
      2
 (1 row)
 
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)';
+                     QUERY PLAN                     
+----------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl
+         Index Cond: (f1 <@ '(100,100),(0,0)'::box)
+(3 rows)
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)';
+ count 
+-------
+     3
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
+                     QUERY PLAN                     
+----------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl
+         Index Cond: ('(100,100),(0,0)'::box @> f1)
+(3 rows)
+
+SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
+ count 
+-------
+     3
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
+                                       QUERY PLAN                                       
+----------------------------------------------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl
+         Index Cond: (f1 <@ '((0,0),(0,100),(100,100),(50,50),(100,0),(0,0))'::polygon)
+(3 rows)
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
+ count 
+-------
+     3
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
+                     QUERY PLAN                     
+----------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl
+         Index Cond: (f1 <@ '<(50,50),50>'::circle)
+(3 rows)
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
+ count 
+-------
+     1
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
+                   QUERY PLAN                    
+-------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl p
+         Index Cond: (f1 << '(0,0)'::point)
+(3 rows)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
+ count 
+-------
+     3
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
+                   QUERY PLAN                    
+-------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl p
+         Index Cond: (f1 >> '(0,0)'::point)
+(3 rows)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
+ count 
+-------
+     2
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
+                   QUERY PLAN                    
+-------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl p
+         Index Cond: (f1 <^ '(0,0)'::point)
+(3 rows)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
+ count 
+-------
+     1
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
+                   QUERY PLAN                    
+-------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl p
+         Index Cond: (f1 >^ '(0,0)'::point)
+(3 rows)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
+ count 
+-------
+     3
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
+                   QUERY PLAN                    
+-------------------------------------------------
+ Aggregate
+   ->  Index Scan using gpointind on point_tbl p
+         Index Cond: (f1 ~= '(-5,-12)'::point)
+(3 rows)
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
+ count 
+-------
+     1
+(1 row)
+
 RESET enable_seqscan;
 RESET enable_indexscan;
 RESET enable_bitmapscan;
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 24a2e8a8e63..5e36d481dfb 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -902,17 +902,25 @@ ORDER BY 1, 2, 3;
         783 |            8 | <@
         783 |            9 | &<|
         783 |           10 | <<|
+        783 |           10 | <^
+        783 |           11 | >^
         783 |           11 | |>>
         783 |           12 | |&>
         783 |           13 | ~
         783 |           14 | @
+        783 |           27 | @>
+        783 |           28 | <@
+        783 |           47 | @>
+        783 |           48 | <@
+        783 |           67 | @>
+        783 |           68 | <@
        2742 |            1 | &&
        2742 |            1 | @@
        2742 |            2 | @>
        2742 |            2 | @@@
        2742 |            3 | <@
        2742 |            4 | =
-(31 rows)
+(39 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/point.out b/src/test/regress/expected/point.out
index 9d1bd434e97..278837d091c 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -81,6 +81,15 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (10,10)
 (3 rows)
 
+SELECT '' AS three, p.* FROM POINT_TBL p
+   WHERE box '(0,0,100,100)' @> p.f1;
+ three |     f1     
+-------+------------
+       | (0,0)
+       | (5.1,34.5)
+       | (10,10)
+(3 rows)
+
 SELECT '' AS three, p.* FROM POINT_TBL p
    WHERE not p.f1 <@ box '(0,0,100,100)';
  three |    f1    
@@ -98,6 +107,15 @@ SELECT '' AS two, p.* FROM POINT_TBL p
      | (-10,0)
 (2 rows)
 
+SELECT '' AS three, p.* FROM POINT_TBL p
+   WHERE not box '(0,0,100,100)' @> p.f1;
+ three |    f1    
+-------+----------
+       | (-10,0)
+       | (-3,4)
+       | (-5,-12)
+(3 rows)
+
 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
    ORDER BY dist;
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 2a4dc4755d7..4dc59d9b5de 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -127,7 +127,7 @@ SELECT relname, relhasindex
  pg_ts_template          | t
  pg_type                 | t
  pg_user_mapping         | t
- point_tbl               | f
+ point_tbl               | t
  polygon_tbl             | t
  ramp                    | f
  real_city               | f
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 519c3181a84..a4261c0f5e2 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -76,6 +76,8 @@ CREATE INDEX gpolygonind ON polygon_tbl USING gist (f1);
 
 CREATE INDEX gcircleind ON circle_tbl USING gist (f1);
 
+CREATE INDEX gpointind ON point_tbl USING gist (f1);
+
 CREATE TEMP TABLE gpolygon_tbl AS
     SELECT polygon(home_base) AS f1 FROM slow_emp4000;
 INSERT INTO gpolygon_tbl VALUES ( '(1000,0,0,1000)' ); 
@@ -110,6 +112,24 @@ SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon;
 
 SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle;
 
+SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)';
+
+SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
+
+SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
+
+SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
+
 SET enable_seqscan = OFF;
 SET enable_indexscan = ON;
 SET enable_bitmapscan = ON;
@@ -150,6 +170,42 @@ EXPLAIN (COSTS OFF)
 SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle;
 SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle;
 
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)';
+SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
+SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
+SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
+SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
+SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
+SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
+SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
+SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
+SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
+
 RESET enable_seqscan;
 RESET enable_indexscan;
 RESET enable_bitmapscan;
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 8523c2ee9f8..40cd4ec022b 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -45,12 +45,18 @@ SELECT '' AS one, p.* FROM POINT_TBL p WHERE p.f1 ~= '(5.1, 34.5)';
 SELECT '' AS three, p.* FROM POINT_TBL p
    WHERE p.f1 <@ box '(0,0,100,100)';
 
+SELECT '' AS three, p.* FROM POINT_TBL p
+   WHERE box '(0,0,100,100)' @> p.f1;
+
 SELECT '' AS three, p.* FROM POINT_TBL p
    WHERE not p.f1 <@ box '(0,0,100,100)';
 
 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
 
+SELECT '' AS three, p.* FROM POINT_TBL p
+   WHERE not box '(0,0,100,100)' @> p.f1;
+
 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
    ORDER BY dist;
-- 
GitLab