diff -c -r -N src.orig/backend/access/gist/gistproc.c src/backend/access/gist/gistproc.c
*** src.orig/backend/access/gist/gistproc.c	2010-01-12 20:30:10.000000000 +0300
--- src/backend/access/gist/gistproc.c	2010-01-12 21:19:21.000000000 +0300
***************
*** 904,909 ****
--- 904,973 ----
  	PG_RETURN_POINTER(entry);
  }
  
+ #define	point_point_distance(p1,p2)	DatumGetFloat8(DirectFunctionCall2(point_distance, PointPGetDatum(p1), PointPGetDatum(p2))) 
+ static double
+ computeDistance(bool isLeaf, BOX *box, Point *point)
+ {
+ 	double			result;
+ 
+ 	if ( isLeaf ) 
+ 	{
+ 		/* point to point distance */
+ 		result = point_point_distance(point, &box->low);
+ 	}
+ 	else if (point->x <= box->high.x && point->x >= box->low.x &&
+ 			 point->y <= box->high.y && point->y >= box->low.y)
+ 	{
+ 		/* point inside the box */
+ 		result = 0.0;
+ 	}
+ 	else if (point->x <= box->high.x && point->x >= box->low.x)
+ 	{
+ 		/* point is over or below box */
+ 		Assert( box->low.y <= box->high.y );
+ 		if (point->y > box->high.y)
+ 			result = point->y - box->high.y;
+ 		else if (point->y < box->low.y)
+ 			result = box->low.y - point->y;
+ 		else 
+ 			elog(ERROR, "Should not be here 1");
+ 	}
+ 	else if (point->y <= box->high.y && point->y >= box->low.y)
+ 	{
+ 		/* point is lefter or rigther box */
+ 		Assert( box->low.x <= box->high.x );
+ 		if (point->x > box->high.x)
+ 			result = point->x - box->high.x;
+ 		else if (point->x < box->low.x)
+ 			result = box->low.x - point->x;
+ 		else
+ 			elog(ERROR, "Should not be here 2");
+ 	}
+ 	else
+ 	{
+ 		/* closest will be a vertix */
+ 		Point	p;
+ 		double	subresult;
+ 
+ 		result = point_point_distance(point, &box->low);
+ 
+ 		subresult = point_point_distance(point, &box->high);
+ 		if (result > subresult) result = subresult;
+ 
+ 		p.x = box->low.x;
+ 		p.y = box->high.y;
+ 		subresult = point_point_distance(point, &p);
+ 		if (result > subresult) result = subresult;
+ 
+ 		p.x = box->high.x;
+ 		p.y = box->low.y;
+ 		subresult = point_point_distance(point, &p);
+ 		if (result > subresult) result = subresult;
+ 	}
+ 
+ 	return result;
+ }
+ 
  static bool
  gist_point_consistent_internal(StrategyNumber strategy,
  										   bool isLeaf, BOX *key, Point *query)
***************
*** 943,1042 ****
  	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);
  }
--- 1007,1131 ----
  	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	   	   *recheck = (bool *) PG_GETARG_POINTER(4);
  	StrategyNumber	strategyGroup = strategy / GeoStrategyNumberOffset;
+ 	double			distance;
+ 	bool			result;
  
  	switch (strategyGroup)
  	{
! 		case	PointStrategyNumberGroup:
! 			if (strategy % GeoStrategyNumberOffset == KNNSearchStrategyNumber)
! 			{
! 				distance = computeDistance(GIST_LEAF(entry), 
! 											DatumGetBoxP(entry->key), 
! 											PG_GETARG_POINT_P(1));
! 				*recheck = false; /* distance computation should be exact! */  
! 			}
! 			else
! 			{
! 				result = gist_point_consistent_internal(strategy % GeoStrategyNumberOffset,
! 														GIST_LEAF(entry),
! 														DatumGetBoxP(entry->key),
! 														PG_GETARG_POINT_P(1));
! 				distance = (result) ? 0.0 : -1.0;
! 			}
  			*recheck = false;
  			break;
! 		case	BoxStrategyNumberGroup:
! 			result = DatumGetBool( DirectFunctionCall5(
  											gist_box_consistent,
  											PointerGetDatum(entry),
  											PG_GETARG_DATUM(1),
  											Int16GetDatum(RTOverlapStrategyNumber),
  											0, PointerGetDatum(recheck)));
+ 			distance = (result) ? 0.0 : -1.0;
  			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)));
  
! 				/* 
! 				 * gist_poly_consistent returns lossy result, but
! 				 * but with point we could do exact check on leaf page
! 				 */
! 				 
! 				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;
  				}
  			}
+ 			distance = (result) ? 0.0 : -1.0;
  			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)));
  
! 				/* 
! 				 * gist_circle_consistent returns lossy result, but
! 				 * but with point we could do exact check on leaf page
! 				 */
! 				 
! 				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;
  				}
  			}
+ 			distance = (result) ? 0.0 : -1.0;
  			break;
  		default:
  			elog(ERROR, "unknown strategy number: %d", strategy);
  	}
  
! 	PG_RETURN_FLOAT8(distance);
  }
+ 
diff -c -r -N src.orig/include/catalog/pg_amop.h src/include/catalog/pg_amop.h
*** src.orig/include/catalog/pg_amop.h	2010-01-12 20:30:13.000000000 +0300
--- src/include/catalog/pg_amop.h	2010-01-12 21:01:37.000000000 +0300
***************
*** 590,597 ****
  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 ));
--- 590,598 ----
  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   600 600 15 517 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 ));
diff -c -r -N src.orig/include/catalog/pg_proc.h src/include/catalog/pg_proc.h
*** src.orig/include/catalog/pg_proc.h	2010-01-12 20:30:13.000000000 +0300
--- src/include/catalog/pg_proc.h	2010-01-12 21:01:37.000000000 +0300
***************
*** 4209,4215 ****
  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 */
--- 4209,4215 ----
  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 701 "2281 603 23 26 2281" _null_ _null_ _null_ _null_	gist_point_consistent _null_ _null_ _null_ ));
  DESCR("GiST support");
  
  /* GIN */
diff -c -r -N src.orig/test/regress/expected/opr_sanity.out src/test/regress/expected/opr_sanity.out
*** src.orig/test/regress/expected/opr_sanity.out	2010-01-12 20:30:15.000000000 +0300
--- src/test/regress/expected/opr_sanity.out	2010-01-12 21:31:46.000000000 +0300
***************
*** 865,873 ****
  -- Check that amopopr points at a reasonable-looking operator, ie a binary
  -- operator yielding boolean.
  SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
! FROM pg_amop AS p1, pg_operator AS p2
  WHERE p1.amopopr = p2.oid AND
!     (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype);
   amopfamily | amopopr | oid | oprname 
  ------------+---------+-----+---------
  (0 rows)
--- 865,885 ----
  -- Check that amopopr points at a reasonable-looking operator, ie a binary
  -- operator yielding boolean.
  SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
! FROM pg_amop AS p1, pg_operator AS p2, pg_am am
  WHERE p1.amopopr = p2.oid AND
! 	  am.oid = p1.amopmethod AND
! 	  ( 
!     	(p2.oprkind != 'b' OR NOT (
! 			p2.oprresult = 'bool'::regtype OR (am.amcanorderbyop='t' AND 
! 			EXISTS( 
! 				SELECT * FROM pg_opclass oc, pg_am am 
! 				WHERE oc.opcintype = p2.oprresult AND 
! 					oc.opcdefault='t' AND
! 					am.amname = 'btree' AND
! 					oc.opcmethod = am.oid 
! 				)
! 		)))
! 	  );
   amopfamily | amopopr | oid | oprname 
  ------------+---------+-----+---------
  (0 rows)
***************
*** 908,913 ****
--- 920,926 ----
          783 |           12 | |&>
          783 |           13 | ~
          783 |           14 | @
+         783 |           15 | <->
          783 |           27 | @>
          783 |           28 | <@
          783 |           47 | @>
***************
*** 920,926 ****
         2742 |            2 | @@@
         2742 |            3 | <@
         2742 |            4 | =
! (39 rows)
  
  -- Check that all operators linked to by opclass entries have selectivity
  -- estimators.  This is not absolutely required, but it seems a reasonable
--- 933,939 ----
         2742 |            2 | @@@
         2742 |            3 | <@
         2742 |            4 | =
! (40 rows)
  
  -- Check that all operators linked to by opclass entries have selectivity
  -- estimators.  This is not absolutely required, but it seems a reasonable
***************
*** 931,937 ****
      (p2.oprrest = 0 OR p2.oprjoin = 0);
   amopfamily | amopopr | oid | oprname 
  ------------+---------+-----+---------
! (0 rows)
  
  -- Check that each opclass in an opfamily has associated operators, that is
  -- ones whose oprleft matches opcintype (possibly by coercion).
--- 944,951 ----
      (p2.oprrest = 0 OR p2.oprjoin = 0);
   amopfamily | amopopr | oid | oprname 
  ------------+---------+-----+---------
!        1029 |     517 | 517 | <->
! (1 row)
  
  -- Check that each opclass in an opfamily has associated operators, that is
  -- ones whose oprleft matches opcintype (possibly by coercion).
diff -c -r -N src.orig/test/regress/sql/opr_sanity.sql src/test/regress/sql/opr_sanity.sql
*** src.orig/test/regress/sql/opr_sanity.sql	2010-01-12 20:30:15.000000000 +0300
--- src/test/regress/sql/opr_sanity.sql	2010-01-12 21:31:20.000000000 +0300
***************
*** 699,707 ****
  -- operator yielding boolean.
  
  SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
! FROM pg_amop AS p1, pg_operator AS p2
  WHERE p1.amopopr = p2.oid AND
!     (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype);
  
  -- Make a list of all the distinct operator names being used in particular
  -- strategy slots.  This is a bit hokey, since the list might need to change
--- 699,719 ----
  -- operator yielding boolean.
  
  SELECT p1.amopfamily, p1.amopopr, p2.oid, p2.oprname
! FROM pg_amop AS p1, pg_operator AS p2, pg_am am
  WHERE p1.amopopr = p2.oid AND
! 	  am.oid = p1.amopmethod AND
! 	  ( 
!     	(p2.oprkind != 'b' OR NOT (
! 			p2.oprresult = 'bool'::regtype OR (am.amcanorderbyop='t' AND 
! 			EXISTS( 
! 				SELECT * FROM pg_opclass oc, pg_am am 
! 				WHERE oc.opcintype = p2.oprresult AND 
! 					oc.opcdefault='t' AND
! 					am.amname = 'btree' AND
! 					oc.opcmethod = am.oid 
! 				)
! 		)))
! 	  );
  
  -- Make a list of all the distinct operator names being used in particular
  -- strategy slots.  This is a bit hokey, since the list might need to change
