diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
new file mode 100644
index 0158b17..2cfe9e8
*** a/doc/src/sgml/gist.sgml
--- b/doc/src/sgml/gist.sgml
***************
*** 105,110 ****
--- 105,111 ----
         <literal>~=</>
        </entry>
        <entry>
+        <literal>&lt;-&gt;</>
        </entry>
       </row>
       <row>
***************
*** 163,168 ****
--- 164,170 ----
         <literal>~=</>
        </entry>
        <entry>
+        <literal>&lt;-&gt;</>
        </entry>
       </row>
       <row>
***************
*** 207,212 ****
--- 209,220 ----
    </table>
  
   <para>
+   Currently, ordering by the distance operator <literal>&lt;-&gt;</>
+   is supported only with <literal>point</> by the operator classes
+   of the geometric types.
+  </para>
+ 
+  <para>
    For historical reasons, the <literal>inet_ops</> operator class is
    not the default class for types <type>inet</> and <type>cidr</>.
    To use it, mention the class name in <command>CREATE INDEX</>,
*************** my_same(PG_FUNCTION_ARGS)
*** 766,772 ****
          The <acronym>SQL</> declaration of the function must look like this:
  
  <programlisting>
! CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid)
  RETURNS float8
  AS 'MODULE_PATHNAME'
  LANGUAGE C STRICT;
--- 774,780 ----
          The <acronym>SQL</> declaration of the function must look like this:
  
  <programlisting>
! CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid, internal)
  RETURNS float8
  AS 'MODULE_PATHNAME'
  LANGUAGE C STRICT;
*************** my_distance(PG_FUNCTION_ARGS)
*** 785,790 ****
--- 793,799 ----
      data_type  *query = PG_GETARG_DATA_TYPE_P(1);
      StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
      /* Oid subtype = PG_GETARG_OID(3); */
+     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
      data_type  *key = DatumGetDataType(entry-&gt;key);
      double      retval;
  
*************** my_distance(PG_FUNCTION_ARGS)
*** 797,807 ****
  </programlisting>
  
         The arguments to the <function>distance</> function are identical to
!        the arguments of the <function>consistent</> function, except that no
!        recheck flag is used.  The distance to a leaf index entry must always
!        be determined exactly, since there is no way to re-order the tuples
!        once they are returned.  Some approximation is allowed when determining
!        the distance to an internal tree node, so long as the result is never
         greater than any child's actual distance.  Thus, for example, distance
         to a bounding box is usually sufficient in geometric applications.  The
         result value can be any finite <type>float8</> value.  (Infinity and
--- 806,821 ----
  </programlisting>
  
         The arguments to the <function>distance</> function are identical to
!        the arguments of the <function>consistent</> function.  When
!        <literal>recheck = true</> then value of distance will
!        be rechecked from heap tuple before tuple is returned.  If
!        <literal>recheck</> flag isn't set then it's true by default for
!        compatibility reasons.  The <literal>recheck</> flag can be used only
!        when ordering operator returns <type>float8</> value comparable with
!        result of <function>distance</> function.  Result of distance function
!        should be never greater than result of ordering operator.
!        Same approximation is allowed when determining the distance to an
!        internal tree node, so long as the result is never
         greater than any child's actual distance.  Thus, for example, distance
         to a bounding box is usually sufficient in geometric applications.  The
         result value can be any finite <type>float8</> value.  (Infinity and
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
new file mode 100644
index 7a8692b..e454ba2
*** a/src/backend/access/gist/gistget.c
--- b/src/backend/access/gist/gistget.c
***************
*** 16,21 ****
--- 16,22 ----
  
  #include "access/gist_private.h"
  #include "access/relscan.h"
+ #include "catalog/index.h"
  #include "miscadmin.h"
  #include "pgstat.h"
  #include "utils/builtins.h"
*************** gistindex_keytest(IndexScanDesc scan,
*** 55,61 ****
  	GISTSTATE  *giststate = so->giststate;
  	ScanKey		key = scan->keyData;
  	int			keySize = scan->numberOfKeys;
! 	double	   *distance_p;
  	Relation	r = scan->indexRelation;
  
  	*recheck_p = false;
--- 56,62 ----
  	GISTSTATE  *giststate = so->giststate;
  	ScanKey		key = scan->keyData;
  	int			keySize = scan->numberOfKeys;
! 	GISTSearchTreeItemDistance *distance_p;
  	Relation	r = scan->indexRelation;
  
  	*recheck_p = false;
*************** gistindex_keytest(IndexScanDesc scan,
*** 72,78 ****
  		if (GistPageIsLeaf(page))		/* shouldn't happen */
  			elog(ERROR, "invalid GiST tuple found on leaf page");
  		for (i = 0; i < scan->numberOfOrderBys; i++)
! 			so->distances[i] = -get_float8_infinity();
  		return true;
  	}
  
--- 73,82 ----
  		if (GistPageIsLeaf(page))		/* shouldn't happen */
  			elog(ERROR, "invalid GiST tuple found on leaf page");
  		for (i = 0; i < scan->numberOfOrderBys; i++)
! 		{
! 			so->distances[i].value = -get_float8_infinity();
! 			so->distances[i].recheck = false;
! 		}
  		return true;
  	}
  
*************** gistindex_keytest(IndexScanDesc scan,
*** 170,176 ****
  		if ((key->sk_flags & SK_ISNULL) || isNull)
  		{
  			/* Assume distance computes as null and sorts to the end */
! 			*distance_p = get_float8_infinity();
  		}
  		else
  		{
--- 174,181 ----
  		if ((key->sk_flags & SK_ISNULL) || isNull)
  		{
  			/* Assume distance computes as null and sorts to the end */
! 			distance_p->value = get_float8_infinity();
! 			distance_p->recheck = false;
  		}
  		else
  		{
*************** gistindex_keytest(IndexScanDesc scan,
*** 191,208 ****
  			 * always be zero, but might as well pass it for possible future
  			 * use.)
  			 *
! 			 * Note that Distance functions don't get a recheck argument. We
! 			 * can't tolerate lossy distance calculations on leaf tuples;
! 			 * there is no opportunity to re-sort the tuples afterwards.
  			 */
! 			dist = FunctionCall4Coll(&key->sk_func,
  									 key->sk_collation,
  									 PointerGetDatum(&de),
  									 key->sk_argument,
  									 Int32GetDatum(key->sk_strategy),
! 									 ObjectIdGetDatum(key->sk_subtype));
  
! 			*distance_p = DatumGetFloat8(dist);
  		}
  
  		key++;
--- 196,215 ----
  			 * always be zero, but might as well pass it for possible future
  			 * use.)
  			 *
! 			 * Distance function gets a recheck argument as well as consistent
! 			 * function.  Distance will be re-calculated from heap tuple when
! 			 * needed.
  			 */
! 			distance_p->recheck = false;
! 			dist = FunctionCall5Coll(&key->sk_func,
  									 key->sk_collation,
  									 PointerGetDatum(&de),
  									 key->sk_argument,
  									 Int32GetDatum(key->sk_strategy),
! 									 ObjectIdGetDatum(key->sk_subtype),
! 									 PointerGetDatum(&distance_p->recheck));
  
! 			distance_p->value = DatumGetFloat8(dist);
  		}
  
  		key++;
*************** gistindex_keytest(IndexScanDesc scan,
*** 234,240 ****
   * sibling will be processed next.
   */
  static void
! gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
  			 TIDBitmap *tbm, int64 *ntids)
  {
  	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
--- 241,247 ----
   * sibling will be processed next.
   */
  static void
! gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, GISTSearchTreeItemDistance *myDistances,
  			 TIDBitmap *tbm, int64 *ntids)
  {
  	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 284,290 ****
  		tmpItem->head = item;
  		tmpItem->lastHeap = NULL;
  		memcpy(tmpItem->distances, myDistances,
! 			   sizeof(double) * scan->numberOfOrderBys);
  
  		(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
  
--- 291,297 ----
  		tmpItem->head = item;
  		tmpItem->lastHeap = NULL;
  		memcpy(tmpItem->distances, myDistances,
! 			   sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
  
  		(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
  
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 375,381 ****
  			tmpItem->head = item;
  			tmpItem->lastHeap = GISTSearchItemIsHeap(*item) ? item : NULL;
  			memcpy(tmpItem->distances, so->distances,
! 				   sizeof(double) * scan->numberOfOrderBys);
  
  			(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
  
--- 382,388 ----
  			tmpItem->head = item;
  			tmpItem->lastHeap = GISTSearchItemIsHeap(*item) ? item : NULL;
  			memcpy(tmpItem->distances, so->distances,
! 				   sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
  
  			(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
  
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 387,392 ****
--- 394,473 ----
  }
  
  /*
+  * Do this tree item distance values needs recheck?
+  */
+ static bool
+ searchTreeItemNeedDistanceRecheck(IndexScanDesc scan, GISTSearchTreeItem *item)
+ {
+ 	int i;
+ 	for (i = 0; i < scan->numberOfOrderBys; i++)
+ 	{
+ 		if (item->distances[i].recheck)
+ 			return true;
+ 	}
+ 	return false;
+ }
+ 
+ /*
+  * Recheck distance values of item from heap and reinsert it into RB-tree.
+  */
+ static void
+ searchTreeItemDistanceRecheck(IndexScanDesc scan, GISTSearchTreeItem *treeItem,
+ 		GISTSearchItem *item)
+ {
+ 	GISTScanOpaque		so = (GISTScanOpaque) scan->opaque;
+ 	GISTSearchTreeItem *tmpItem = so->tmpTreeItem;
+ 	Datum				values[INDEX_MAX_KEYS];
+ 	bool				isnull[INDEX_MAX_KEYS];
+ 	bool				isNew;
+ 	int					i;
+ 
+ 	/* Get index values from heap */
+ 	if (!index_get_heap_values(scan, &item->data.heap.heapPtr, values, isnull))
+ 	{
+ 		/*
+ 		 * Tuple not found: it has been deleted from heap.  We don't have to
+ 		 * reinsert it into RB-tree.
+ 		 */
+ 		pfree(item);
+ 		return;
+ 	}
+ 
+ 	/* Prepare new tree item and reinsert it */
+ 	memcpy(tmpItem, treeItem, GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) *
+ 										  scan->numberOfOrderBys);
+ 	tmpItem->head = item;
+ 	tmpItem->lastHeap = item;
+ 	item->next = NULL;
+ 	for (i = 0; i < scan->numberOfOrderBys; i++)
+ 	{
+ 		if (tmpItem->distances[i].recheck)
+ 		{
+ 			/* Re-calculate lossy distance */
+ 			ScanKey	key = scan->orderByData + i;
+ 			float8 	newDistance;
+ 
+ 			tmpItem->distances[i].recheck = false;
+ 			if (isnull[key->sk_attno - 1])
+ 			{
+ 				tmpItem->distances[i].value = -get_float8_infinity();
+ 				continue;
+ 			}
+ 
+ 			newDistance = DatumGetFloat8(
+ 				FunctionCall2Coll(&so->orderByRechecks[i],
+ 					 key->sk_collation,
+ 					 values[key->sk_attno - 1],
+ 					 key->sk_argument));
+ 
+ 			tmpItem->distances[i].value = newDistance;
+ 
+ 		}
+ 	}
+ 	(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
+ }
+ 
+ /*
   * Extract next item (in order) from search queue
   *
   * Returns a GISTSearchItem or NULL.  Caller must pfree item when done with it.
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 396,403 ****
   * the distances value for the item.
   */
  static GISTSearchItem *
! getNextGISTSearchItem(GISTScanOpaque so)
  {
  	for (;;)
  	{
  		GISTSearchItem *item;
--- 477,486 ----
   * the distances value for the item.
   */
  static GISTSearchItem *
! getNextGISTSearchItem(IndexScanDesc scan)
  {
+ 	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
+ 
  	for (;;)
  	{
  		GISTSearchItem *item;
*************** getNextGISTSearchItem(GISTScanOpaque so)
*** 418,423 ****
--- 501,514 ----
  			so->curTreeItem->head = item->next;
  			if (item == so->curTreeItem->lastHeap)
  				so->curTreeItem->lastHeap = NULL;
+ 
+ 			/* Recheck distance from heap tuple if needed */
+ 			if (GISTSearchItemIsHeap(*item) &&
+ 				searchTreeItemNeedDistanceRecheck(scan, so->curTreeItem))
+ 			{
+ 				searchTreeItemDistanceRecheck(scan, so->curTreeItem, item);
+ 				continue;
+ 			}
  			/* Return item; caller is responsible to pfree it */
  			return item;
  		}
*************** getNextNearest(IndexScanDesc scan)
*** 441,447 ****
  
  	do
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(so);
  
  		if (!item)
  			break;
--- 532,538 ----
  
  	do
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(scan);
  
  		if (!item)
  			break;
*************** gistgettuple(PG_FUNCTION_ARGS)
*** 521,527 ****
  			/* find and process the next index page */
  			do
  			{
! 				GISTSearchItem *item = getNextGISTSearchItem(so);
  
  				if (!item)
  					PG_RETURN_BOOL(false);
--- 612,618 ----
  			/* find and process the next index page */
  			do
  			{
! 				GISTSearchItem *item = getNextGISTSearchItem(scan);
  
  				if (!item)
  					PG_RETURN_BOOL(false);
*************** gistgetbitmap(PG_FUNCTION_ARGS)
*** 573,579 ****
  	 */
  	for (;;)
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(so);
  
  		if (!item)
  			break;
--- 664,670 ----
  	 */
  	for (;;)
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(scan);
  
  		if (!item)
  			break;
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
new file mode 100644
index db0bec6..fd3546a
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
*************** gist_poly_consistent(PG_FUNCTION_ARGS)
*** 1098,1103 ****
--- 1098,1104 ----
  	PG_RETURN_BOOL(result);
  }
  
+ 
  /**************************************************
   * Circle ops
   **************************************************/
*************** gist_point_distance(PG_FUNCTION_ARGS)
*** 1459,1461 ****
--- 1460,1496 ----
  
  	PG_RETURN_FLOAT8(distance);
  }
+ 
+ /*
+  * The inexact GiST distance method for geometric types
+  *
+  * Compute lossy distance from point to index entries.  The result is inexact
+  * because index entries are bounding boxes, not the exact shapes of the
+  * indexed geometric types.  We use distance from point to MBR of index entry.
+  * This is correct lower bound estimate of distance from point to indexed
+  * geometric type.
+  */
+ Datum
+ gist_inexact_distance(PG_FUNCTION_ARGS)
+ {
+ 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ 	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+ 	bool 	   *recheck = (bool *) PG_GETARG_POINTER(4);
+ 	double		distance;
+ 	StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
+ 	*recheck = true;
+ 
+ 	switch (strategyGroup)
+ 	{
+ 		case PointStrategyNumberGroup:
+ 			distance = computeDistance(false,
+ 									   DatumGetBoxP(entry->key),
+ 									   PG_GETARG_POINT_P(1));
+ 			break;
+ 		default:
+ 			elog(ERROR, "unknown strategy number: %d", strategy);
+ 			distance = 0.0;		/* keep compiler quiet */
+ 	}
+ 
+ 	PG_RETURN_FLOAT8(distance);
+ }
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
new file mode 100644
index 8360b16..5832087
*** a/src/backend/access/gist/gistscan.c
--- b/src/backend/access/gist/gistscan.c
***************
*** 17,22 ****
--- 17,25 ----
  #include "access/gist_private.h"
  #include "access/gistscan.h"
  #include "access/relscan.h"
+ #include "catalog/index.h"
+ #include "executor/executor.h"
+ #include "executor/tuptable.h"
  #include "utils/memutils.h"
  #include "utils/rel.h"
  
*************** GISTSearchTreeItemComparator(const RBNod
*** 36,43 ****
  	/* Order according to distance comparison */
  	for (i = 0; i < scan->numberOfOrderBys; i++)
  	{
! 		if (sa->distances[i] != sb->distances[i])
! 			return (sa->distances[i] > sb->distances[i]) ? 1 : -1;
  	}
  
  	return 0;
--- 39,56 ----
  	/* Order according to distance comparison */
  	for (i = 0; i < scan->numberOfOrderBys; i++)
  	{
! 		const GISTSearchTreeItemDistance distance_a = sa->distances[i];
! 		const GISTSearchTreeItemDistance distance_b = sb->distances[i];
! 
! 		if (distance_a.value != distance_b.value)
! 			return (distance_a.value > distance_b.value) ? 1 : -1;
! 
! 		/*
! 		 * Items without recheck can be immediately returned.  So they are
! 		 * placed first.
! 		 */
! 		if (distance_a.recheck != distance_b.recheck)
! 			return distance_a.recheck ? 1 : -1;
  	}
  
  	return 0;
*************** GISTSearchTreeItemAllocator(void *arg)
*** 83,89 ****
  {
  	IndexScanDesc scan = (IndexScanDesc) arg;
  
! 	return palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys);
  }
  
  static void
--- 96,102 ----
  {
  	IndexScanDesc scan = (IndexScanDesc) arg;
  
! 	return palloc(GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
  }
  
  static void
*************** gistbeginscan(PG_FUNCTION_ARGS)
*** 127,136 ****
  	so->queueCxt = giststate->scanCxt;	/* see gistrescan */
  
  	/* workspaces with size dependent on numberOfOrderBys: */
! 	so->tmpTreeItem = palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys);
! 	so->distances = palloc(sizeof(double) * scan->numberOfOrderBys);
  	so->qual_ok = true;			/* in case there are zero keys */
  
  	scan->opaque = so;
  
  	MemoryContextSwitchTo(oldCxt);
--- 140,158 ----
  	so->queueCxt = giststate->scanCxt;	/* see gistrescan */
  
  	/* workspaces with size dependent on numberOfOrderBys: */
! 	so->tmpTreeItem = palloc(GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) *
! 										 scan->numberOfOrderBys);
! 	so->distances = palloc(sizeof(GISTSearchTreeItemDistance) *
! 						   scan->numberOfOrderBys);
  	so->qual_ok = true;			/* in case there are zero keys */
  
+ 	if (scan->numberOfOrderBys > 0)
+ 	{
+ 		/* Functions for distance recheck from heap tuple */
+ 		so->orderByRechecks = (FmgrInfo *)palloc(sizeof(FmgrInfo)
+ 													* scan->numberOfOrderBys);
+ 	}
+ 
  	scan->opaque = so;
  
  	MemoryContextSwitchTo(oldCxt);
*************** gistrescan(PG_FUNCTION_ARGS)
*** 188,194 ****
  
  	/* create new, empty RBTree for search queue */
  	oldCxt = MemoryContextSwitchTo(so->queueCxt);
! 	so->queue = rb_create(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys,
  						  GISTSearchTreeItemComparator,
  						  GISTSearchTreeItemCombiner,
  						  GISTSearchTreeItemAllocator,
--- 210,217 ----
  
  	/* create new, empty RBTree for search queue */
  	oldCxt = MemoryContextSwitchTo(so->queueCxt);
! 	so->queue = rb_create(GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) *
! 									  scan->numberOfOrderBys,
  						  GISTSearchTreeItemComparator,
  						  GISTSearchTreeItemCombiner,
  						  GISTSearchTreeItemAllocator,
*************** gistrescan(PG_FUNCTION_ARGS)
*** 289,294 ****
--- 312,321 ----
  					 GIST_DISTANCE_PROC, skey->sk_attno,
  					 RelationGetRelationName(scan->indexRelation));
  
+ 			/* Copy original sk_func for distance recheck from heap tuple */
+ 			fmgr_info_copy(&so->orderByRechecks[i], &(skey->sk_func),
+ 						   so->giststate->scanCxt);
+ 
  			fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
  
  			/* Restore prior fn_extra pointers, if not first time */
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
new file mode 100644
index 850008b..18cd20b
*** a/src/backend/access/index/genam.c
--- b/src/backend/access/index/genam.c
*************** RelationGetIndexScan(Relation indexRelat
*** 120,125 ****
--- 120,128 ----
  	scan->xs_ctup.t_data = NULL;
  	scan->xs_cbuf = InvalidBuffer;
  	scan->xs_continue_hot = false;
+ 	scan->indexInfo = NULL;
+ 	scan->estate = NULL;
+ 	scan->slot = NULL;
  
  	return scan;
  }
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
new file mode 100644
index 53cf96f..5b526c6
*** a/src/backend/access/index/indexam.c
--- b/src/backend/access/index/indexam.c
***************
*** 69,74 ****
--- 69,75 ----
  #include "access/transam.h"
  #include "access/xlog.h"
  
+ #include "executor/executor.h"
  #include "catalog/index.h"
  #include "catalog/catalog.h"
  #include "pgstat.h"
*************** index_beginscan(Relation heapRelation,
*** 254,259 ****
--- 255,265 ----
  	scan->heapRelation = heapRelation;
  	scan->xs_snapshot = snapshot;
  
+ 	/* Prepare data structures for getting original indexed values from heap */
+ 	scan->indexInfo = BuildIndexInfo(scan->indexRelation);
+ 	scan->estate = CreateExecutorState();
+ 	scan->slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+ 
  	return scan;
  }
  
*************** index_endscan(IndexScanDesc scan)
*** 377,382 ****
--- 383,393 ----
  		scan->xs_cbuf = InvalidBuffer;
  	}
  
+ 	if (scan->slot)
+ 		ExecDropSingleTupleTableSlot(scan->slot);
+ 	if (scan->estate)
+ 		FreeExecutorState(scan->estate);
+ 
  	/* End the AM's scan */
  	FunctionCall1(procedure, PointerGetDatum(scan));
  
*************** index_fetch_heap(IndexScanDesc scan)
*** 564,569 ****
--- 575,623 ----
  }
  
  /* ----------------
+  *		index_get_heap_values - get original indexed values from heap
+  *
+  * Fetches heap tuple of heapPtr and calculated original indexed values.
+  * Returns true on success. Returns false when heap tuple wasn't found.
+  * Useful for indexes with lossy representation of keys.
+  * ----------------
+  */
+ bool
+ index_get_heap_values(IndexScanDesc scan, ItemPointer heapPtr,
+ 					Datum values[INDEX_MAX_KEYS], bool isnull[INDEX_MAX_KEYS])
+ {
+ 	Buffer			buffer;
+ 	bool			got_heap_tuple, all_dead;
+ 	HeapTupleData	tup;
+ 
+ 	/* Get tuple from heap */
+ 	buffer = ReadBuffer(scan->heapRelation,
+ 											ItemPointerGetBlockNumber(heapPtr));
+ 	LockBuffer(buffer, BUFFER_LOCK_SHARE);
+ 	got_heap_tuple = heap_hot_search_buffer(heapPtr,
+ 											scan->heapRelation,
+ 											buffer,
+ 											scan->xs_snapshot,
+ 											&tup,
+ 											&all_dead,
+ 											true);
+ 	if (!got_heap_tuple)
+ 	{
+ 		/* Tuple not found: it has been deleted from heap. */
+ 		UnlockReleaseBuffer(buffer);
+ 		return false;
+ 	}
+ 
+ 	/* Calculate index datums */
+ 	ExecStoreTuple(heap_copytuple(&tup), scan->slot, InvalidBuffer, true);
+ 	FormIndexDatum(scan->indexInfo, scan->slot, scan->estate, values, isnull);
+ 
+ 	UnlockReleaseBuffer(buffer);
+ 
+ 	return true;
+ }
+ 
+ /* ----------------
   *		index_getnext - get the next heap tuple from a scan
   *
   * The result is the next heap tuple satisfying the scan keys and the
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
new file mode 100644
index 402ea40..c9788e4
*** a/src/backend/utils/adt/geo_ops.c
--- b/src/backend/utils/adt/geo_ops.c
*************** static Point *interpt_sl(LSEG *lseg, LIN
*** 70,75 ****
--- 70,76 ----
  static bool has_interpt_sl(LSEG *lseg, LINE *line);
  static double dist_pl_internal(Point *pt, LINE *line);
  static double dist_ps_internal(Point *pt, LSEG *lseg);
+ static float8 dist_ppoly_internal(Point *point, POLYGON *poly);
  static Point *line_interpt_internal(LINE *l1, LINE *l2);
  static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
  static Point *lseg_interpt_internal(LSEG *l1, LSEG *l2);
*************** dist_lb(PG_FUNCTION_ARGS)
*** 2641,2646 ****
--- 2642,2679 ----
  }
  
  /*
+  * Distance from a point to a circle
+  */
+ Datum
+ dist_pc(PG_FUNCTION_ARGS)
+ {
+ 	Point	   *point = PG_GETARG_POINT_P(0);
+ 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(1);
+ 	float8		result;
+ 
+ 	result = point_dt(point, &circle->center) - circle->radius;
+ 	if (result < 0)
+ 		result = 0;
+ 	PG_RETURN_FLOAT8(result);
+ }
+ 
+ /*
+  * Distance from a circle to a point
+  */
+ Datum
+ dist_cpoint(PG_FUNCTION_ARGS)
+ {
+ 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
+ 	Point	   *point = PG_GETARG_POINT_P(1);
+ 	float8		result;
+ 
+ 	result = point_dt(point, &circle->center) - circle->radius;
+ 	if (result < 0)
+ 		result = 0;
+ 	PG_RETURN_FLOAT8(result);
+ }
+ 
+ /*
   * Distance from a circle to a polygon
   */
  Datum
*************** dist_cpoly(PG_FUNCTION_ARGS)
*** 2699,2706 ****
  Datum
  dist_ppoly(PG_FUNCTION_ARGS)
  {
! 	Point	   *point = PG_GETARG_POINT_P(0);
! 	POLYGON    *poly = PG_GETARG_POLYGON_P(1);
  	float8		result;
  	float8		distance;
  	int			i;
--- 2732,2754 ----
  Datum
  dist_ppoly(PG_FUNCTION_ARGS)
  {
! 	PG_RETURN_FLOAT8(dist_ppoly_internal(PG_GETARG_POINT_P(0),
! 										 PG_GETARG_POLYGON_P(1)));
! }
! 
! /*
!  * Distance from a polygon to a point
!  */
! Datum
! dist_polyp(PG_FUNCTION_ARGS)
! {
! 	PG_RETURN_FLOAT8(dist_ppoly_internal(PG_GETARG_POINT_P(1),
! 										 PG_GETARG_POLYGON_P(0)));
! }
! 
! static float8
! dist_ppoly_internal(Point *point, POLYGON *poly)
! {
  	float8		result;
  	float8		distance;
  	int			i;
*************** dist_ppoly(PG_FUNCTION_ARGS)
*** 2711,2717 ****
  #ifdef GEODEBUG
  		printf("dist_ppoly- point inside of polygon\n");
  #endif
! 		PG_RETURN_FLOAT8(0.0);
  	}
  
  	/* initialize distance with segment between first and last points */
--- 2759,2765 ----
  #ifdef GEODEBUG
  		printf("dist_ppoly- point inside of polygon\n");
  #endif
! 		return 0.0;
  	}
  
  	/* initialize distance with segment between first and last points */
*************** dist_ppoly(PG_FUNCTION_ARGS)
*** 2739,2745 ****
  			result = distance;
  	}
  
! 	PG_RETURN_FLOAT8(result);
  }
  
  
--- 2787,2793 ----
  			result = distance;
  	}
  
! 	return result;
  }
  
  
*************** pt_contained_circle(PG_FUNCTION_ARGS)
*** 5098,5120 ****
  }
  
  
- /*		dist_pc -		returns the distance between
-  *						  a point and a circle.
-  */
- Datum
- dist_pc(PG_FUNCTION_ARGS)
- {
- 	Point	   *point = PG_GETARG_POINT_P(0);
- 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(1);
- 	float8		result;
- 
- 	result = point_dt(point, &circle->center) - circle->radius;
- 	if (result < 0)
- 		result = 0;
- 	PG_RETURN_FLOAT8(result);
- }
- 
- 
  /*		circle_center	-		returns the center point of the circle.
   */
  Datum
--- 5146,5151 ----
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
new file mode 100644
index d99158f..170069e
*** a/src/include/access/genam.h
--- b/src/include/access/genam.h
*************** extern void index_restrpos(IndexScanDesc
*** 147,153 ****
--- 147,156 ----
  extern ItemPointer index_getnext_tid(IndexScanDesc scan,
  				  ScanDirection direction);
  extern HeapTuple index_fetch_heap(IndexScanDesc scan);
+ extern bool index_get_heap_values(IndexScanDesc scan, ItemPointer heapPtr,
+ 					Datum values[INDEX_MAX_KEYS], bool isnull[INDEX_MAX_KEYS]);
  extern HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction);
+ 
  extern int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap);
  
  extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info,
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
new file mode 100644
index 03e9903..f7b7aeb
*** a/src/include/access/gist_private.h
--- b/src/include/access/gist_private.h
***************
*** 16,22 ****
--- 16,24 ----
  
  #include "access/gist.h"
  #include "access/itup.h"
+ #include "executor/tuptable.h"
  #include "fmgr.h"
+ #include "nodes/execnodes.h"
  #include "storage/bufmgr.h"
  #include "storage/buffile.h"
  #include "utils/rbtree.h"
*************** typedef struct GISTSearchItem
*** 135,140 ****
--- 137,151 ----
  #define GISTSearchItemIsHeap(item)	((item).blkno == InvalidBlockNumber)
  
  /*
+  * KNN distance item: distance which can be rechecked from heap tuple.
+  */
+ typedef struct GISTSearchTreeItemDistance
+ {
+ 	double	value;
+ 	bool	recheck;
+ } GISTSearchTreeItemDistance;
+ 
+ /*
   * Within a GISTSearchTreeItem's chain, heap items always appear before
   * index-page items, since we want to visit heap items first.  lastHeap points
   * to the last heap item in the chain, or is NULL if there are none.
*************** typedef struct GISTSearchTreeItem
*** 144,150 ****
  	RBNode		rbnode;			/* this is an RBTree item */
  	GISTSearchItem *head;		/* first chain member */
  	GISTSearchItem *lastHeap;	/* last heap-tuple member, if any */
! 	double		distances[1];	/* array with numberOfOrderBys entries */
  } GISTSearchTreeItem;
  
  #define GSTIHDRSZ offsetof(GISTSearchTreeItem, distances)
--- 155,161 ----
  	RBNode		rbnode;			/* this is an RBTree item */
  	GISTSearchItem *head;		/* first chain member */
  	GISTSearchItem *lastHeap;	/* last heap-tuple member, if any */
! 	GISTSearchTreeItemDistance	distances[1];	/* array with numberOfOrderBys entries */
  } GISTSearchTreeItem;
  
  #define GSTIHDRSZ offsetof(GISTSearchTreeItem, distances)
*************** typedef struct GISTScanOpaqueData
*** 164,175 ****
  
  	/* pre-allocated workspace arrays */
  	GISTSearchTreeItem *tmpTreeItem;	/* workspace to pass to rb_insert */
! 	double	   *distances;		/* output area for gistindex_keytest */
  
  	/* In a non-ordered search, returnable heap items are stored here: */
  	GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
  	OffsetNumber nPageData;		/* number of valid items in array */
  	OffsetNumber curPageData;	/* next item to return */
  } GISTScanOpaqueData;
  
  typedef GISTScanOpaqueData *GISTScanOpaque;
--- 175,189 ----
  
  	/* pre-allocated workspace arrays */
  	GISTSearchTreeItem *tmpTreeItem;	/* workspace to pass to rb_insert */
! 	GISTSearchTreeItemDistance *distances; /* output area for gistindex_keytest */
  
  	/* In a non-ordered search, returnable heap items are stored here: */
  	GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
  	OffsetNumber nPageData;		/* number of valid items in array */
  	OffsetNumber curPageData;	/* next item to return */
+ 
+ 	/* Data structures for performing recheck of lossy knn distance */
+ 	FmgrInfo	*orderByRechecks;	/* functions for lossy knn distance recheck */
  } GISTScanOpaqueData;
  
  typedef GISTScanOpaqueData *GISTScanOpaque;
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
new file mode 100644
index 8a57698..5acf228
*** a/src/include/access/relscan.h
--- b/src/include/access/relscan.h
***************
*** 19,24 ****
--- 19,25 ----
  #include "access/htup_details.h"
  #include "access/itup.h"
  #include "access/tupdesc.h"
+ #include "nodes/execnodes.h"
  
  
  typedef struct HeapScanDescData
*************** typedef struct IndexScanDescData
*** 93,98 ****
--- 94,104 ----
  
  	/* state data for traversing HOT chains in index_getnext */
  	bool		xs_continue_hot;	/* T if must keep walking HOT chain */
+ 
+ 	/* Data structures for getting original indexed values from heap */
+ 	IndexInfo  *indexInfo;		/* index info for index tuple calculation */
+ 	TupleTableSlot *slot;		/* heap tuple slot */
+ 	EState	   *estate;		/* executor state for index tuple calculation */
  }	IndexScanDescData;
  
  /* Struct for heap-or-index scans of system tables */
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
new file mode 100644
index 3ef5a49..dd468f6
*** a/src/include/catalog/pg_amop.h
--- b/src/include/catalog/pg_amop.h
*************** DATA(insert (	2594   604 604 11 s 2577 7
*** 650,655 ****
--- 650,656 ----
  DATA(insert (	2594   604 604 12 s 2576 783 0 ));
  DATA(insert (	2594   604 604 13 s 2861 783 0 ));
  DATA(insert (	2594   604 604 14 s 2860 783 0 ));
+ DATA(insert (	2594   604 600 15 o 3588 783 1970 ));
  
  /*
   *	gist circle_ops
*************** DATA(insert (	2595   718 718 11 s 1514 7
*** 669,674 ****
--- 670,676 ----
  DATA(insert (	2595   718 718 12 s 2590 783 0 ));
  DATA(insert (	2595   718 718 13 s 2865 783 0 ));
  DATA(insert (	2595   718 718 14 s 2864 783 0 ));
+ DATA(insert (	2595   718 600 15 o 3586 783 1970 ));
  
  /*
   * gin array_ops (these anyarray operators are used with all the opclasses
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
new file mode 100644
index 10a47df..1149923
*** a/src/include/catalog/pg_amproc.h
--- b/src/include/catalog/pg_amproc.h
*************** DATA(insert (	2594   604 604 4 2580 ));
*** 204,209 ****
--- 204,210 ----
  DATA(insert (	2594   604 604 5 2581 ));
  DATA(insert (	2594   604 604 6 2582 ));
  DATA(insert (	2594   604 604 7 2584 ));
+ DATA(insert (	2594   604 604 8 3589 ));
  DATA(insert (	2595   718 718 1 2591 ));
  DATA(insert (	2595   718 718 2 2583 ));
  DATA(insert (	2595   718 718 3 2592 ));
*************** DATA(insert (	2595   718 718 4 2580 ));
*** 211,216 ****
--- 212,218 ----
  DATA(insert (	2595   718 718 5 2581 ));
  DATA(insert (	2595   718 718 6 2582 ));
  DATA(insert (	2595   718 718 7 2584 ));
+ DATA(insert (	2595   718 718 8 3589 ));
  DATA(insert (	3655   3614 3614 1 3654 ));
  DATA(insert (	3655   3614 3614 2 3651 ));
  DATA(insert (	3655   3614 3614 3 3648 ));
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
new file mode 100644
index c31b8a8..b633665
*** a/src/include/catalog/pg_operator.h
--- b/src/include/catalog/pg_operator.h
*************** DATA(insert OID = 1520 (  "<->"   PGNSP 
*** 1014,1022 ****
  DESCR("distance between");
  DATA(insert OID = 1521 (  "#"	  PGNSP PGUID l f f  0		604   23	  0    0 poly_npoints - - ));
  DESCR("number of points");
! DATA(insert OID = 1522 (  "<->"   PGNSP PGUID b f f  600	718  701	  0    0 dist_pc - - ));
  DESCR("distance between");
! DATA(insert OID = 3591 (  "<->"	  PGNSP PGUID b f f	 600	604	 701	  0	   0 dist_ppoly - - ));
  DESCR("distance between");
  DATA(insert OID = 1523 (  "<->"   PGNSP PGUID b f f  718	604  701	  0    0 dist_cpoly - - ));
  DESCR("distance between");
--- 1014,1026 ----
  DESCR("distance between");
  DATA(insert OID = 1521 (  "#"	  PGNSP PGUID l f f  0		604   23	  0    0 poly_npoints - - ));
  DESCR("number of points");
! DATA(insert OID = 1522 (  "<->"   PGNSP PGUID b f f  600	718  701   3586    0 dist_pc - - ));
  DESCR("distance between");
! DATA(insert OID = 3586 (  "<->"   PGNSP PGUID b f f  718	600  701   1522    0 dist_cpoint - - ));
! DESCR("distance between");
! DATA(insert OID = 3591 (  "<->"	  PGNSP PGUID b f f  600 	604  701   3588	   0 dist_ppoly - - ));
! DESCR("distance between");
! DATA(insert OID = 3588 (  "<->"	  PGNSP PGUID b f f  604 	600  701   3591	   0 dist_polyp - - ));
  DESCR("distance between");
  DATA(insert OID = 1523 (  "<->"   PGNSP PGUID b f f  718	604  701	  0    0 dist_cpoly - - ));
  DESCR("distance between");
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index 95f0b74..1b7664e
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID = 727 (  dist_sl		   PGN
*** 814,819 ****
--- 814,821 ----
  DATA(insert OID = 728 (  dist_cpoly		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "718 604" _null_ _null_ _null_ _null_	dist_cpoly _null_ _null_ _null_ ));
  DATA(insert OID = 729 (  poly_distance	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "604 604" _null_ _null_ _null_ _null_	poly_distance _null_ _null_ _null_ ));
  DATA(insert OID = 3590 (  dist_ppoly	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "600 604" _null_ _null_ _null_ _null_	dist_ppoly _null_ _null_ _null_ ));
+ DATA(insert OID = 3587 (  dist_polyp	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "604 600" _null_ _null_ _null_ _null_	dist_polyp _null_ _null_ _null_ ));
+ DATA(insert OID = 3585 (  dist_cpoint	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "718 600" _null_ _null_ _null_ _null_ 	dist_cpoint _null_ _null_ _null_ ));
  
  DATA(insert OID = 740 (  text_lt		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_lt _null_ _null_ _null_ ));
  DATA(insert OID = 741 (  text_le		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_le _null_ _null_ _null_ ));
*************** DATA(insert OID = 2585 (  gist_poly_cons
*** 4009,4014 ****
--- 4011,4018 ----
  DESCR("GiST support");
  DATA(insert OID = 2586 (  gist_poly_compress	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_poly_compress _null_ _null_ _null_ ));
  DESCR("GiST support");
+ DATA(insert OID = 3589 (  gist_inexact_distance	PGNSP PGUID 12 1 0 0 0 f f f f t f i 4 0 701 "2281 600 23 26" _null_ _null_ _null_ _null_	gist_inexact_distance _null_ _null_ _null_ ));
+ DESCR("GiST support");
  DATA(insert OID = 2591 (  gist_circle_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 5 0 16 "2281 718 23 26 2281" _null_ _null_ _null_ _null_	gist_circle_consistent _null_ _null_ _null_ ));
  DESCR("GiST support");
  DATA(insert OID = 2592 (  gist_circle_compress	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_circle_compress _null_ _null_ _null_ ));
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
new file mode 100644
index 91610d8..64f63b2
*** a/src/include/utils/geo_decls.h
--- b/src/include/utils/geo_decls.h
*************** extern Datum circle_diameter(PG_FUNCTION
*** 394,401 ****
--- 394,403 ----
  extern Datum circle_radius(PG_FUNCTION_ARGS);
  extern Datum circle_distance(PG_FUNCTION_ARGS);
  extern Datum dist_pc(PG_FUNCTION_ARGS);
+ extern Datum dist_cpoint(PG_FUNCTION_ARGS);
  extern Datum dist_cpoly(PG_FUNCTION_ARGS);
  extern Datum dist_ppoly(PG_FUNCTION_ARGS);
+ extern Datum dist_polyp(PG_FUNCTION_ARGS);
  extern Datum circle_center(PG_FUNCTION_ARGS);
  extern Datum cr_circle(PG_FUNCTION_ARGS);
  extern Datum box_circle(PG_FUNCTION_ARGS);
*************** extern Datum gist_circle_consistent(PG_F
*** 419,424 ****
--- 421,427 ----
  extern Datum gist_point_compress(PG_FUNCTION_ARGS);
  extern Datum gist_point_consistent(PG_FUNCTION_ARGS);
  extern Datum gist_point_distance(PG_FUNCTION_ARGS);
+ extern Datum gist_inexact_distance(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
new file mode 100644
index f6f5516..61082d8
*** a/src/test/regress/expected/create_index.out
--- b/src/test/regress/expected/create_index.out
*************** SELECT count(*) FROM radix_text_tbl WHER
*** 366,371 ****
--- 366,401 ----
      48
  (1 row)
  
+ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10;
+                        f1                        
+ -------------------------------------------------
+  ((240,359),(240,455),(337,455),(337,359))
+  ((662,163),(662,187),(759,187),(759,163))
+  ((1000,0),(0,1000))
+  ((0,1000),(1000,1000))
+  ((1346,344),(1346,403),(1444,403),(1444,344))
+  ((278,1409),(278,1457),(369,1457),(369,1409))
+  ((907,1156),(907,1201),(948,1201),(948,1156))
+  ((1517,971),(1517,1043),(1594,1043),(1594,971))
+  ((175,1820),(175,1850),(259,1850),(259,1820))
+  ((2424,81),(2424,160),(2424,160),(2424,81))
+ (10 rows)
+ 
+ SELECT * FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10;
+                 f1                 
+ -----------------------------------
+  <(288.5,407),68.2367203197809>
+  <(710.5,175),49.9624859269432>
+  <(323.5,1433),51.4417145903983>
+  <(927.5,1178.5),30.4384625104489>
+  <(1395,373.5),57.1948424248201>
+  <(1555.5,1007),52.7091073724456>
+  <(217,1835),44.5982062419555>
+  <(489,2421.5),22.3886131772381>
+  <(2424,120.5),39.5>
+  <(751.5,2655),20.4022057631032>
+ (10 rows)
+ 
  -- Now check the results from plain indexscan
  SET enable_seqscan = OFF;
  SET enable_indexscan = ON;
*************** SELECT count(*) FROM radix_text_tbl WHER
*** 1146,1151 ****
--- 1176,1229 ----
      48
  (1 row)
  
+ EXPLAIN (COSTS OFF)
+ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10;
+                      QUERY PLAN                      
+ -----------------------------------------------------
+  Limit
+    ->  Index Scan using ggpolygonind on gpolygon_tbl
+          Order By: (f1 <-> '(0,0)'::point)
+ (3 rows)
+ 
+ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10;
+                        f1                        
+ -------------------------------------------------
+  ((240,359),(240,455),(337,455),(337,359))
+  ((662,163),(662,187),(759,187),(759,163))
+  ((1000,0),(0,1000))
+  ((0,1000),(1000,1000))
+  ((1346,344),(1346,403),(1444,403),(1444,344))
+  ((278,1409),(278,1457),(369,1457),(369,1409))
+  ((907,1156),(907,1201),(948,1201),(948,1156))
+  ((1517,971),(1517,1043),(1594,1043),(1594,971))
+  ((175,1820),(175,1850),(259,1850),(259,1820))
+  ((2424,81),(2424,160),(2424,160),(2424,81))
+ (10 rows)
+ 
+ EXPLAIN (COSTS OFF)
+ SELECT * FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10;
+                     QUERY PLAN                     
+ ---------------------------------------------------
+  Limit
+    ->  Index Scan using ggcircleind on gcircle_tbl
+          Order By: (f1 <-> '(200,300)'::point)
+ (3 rows)
+ 
+ SELECT * FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10;
+                 f1                 
+ -----------------------------------
+  <(288.5,407),68.2367203197809>
+  <(710.5,175),49.9624859269432>
+  <(323.5,1433),51.4417145903983>
+  <(927.5,1178.5),30.4384625104489>
+  <(1395,373.5),57.1948424248201>
+  <(1555.5,1007),52.7091073724456>
+  <(217,1835),44.5982062419555>
+  <(489,2421.5),22.3886131772381>
+  <(2424,120.5),39.5>
+  <(751.5,2655),20.4022057631032>
+ (10 rows)
+ 
  -- Now check the results from bitmap indexscan
  SET enable_seqscan = OFF;
  SET enable_indexscan = OFF;
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
new file mode 100644
index d4d24ef..d9bce16
*** a/src/test/regress/sql/create_index.sql
--- b/src/test/regress/sql/create_index.sql
*************** SELECT count(*) FROM radix_text_tbl WHER
*** 220,225 ****
--- 220,229 ----
  
  SELECT count(*) FROM radix_text_tbl WHERE t ~>~  'Worth                         St  ';
  
+ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10;
+ 
+ SELECT * FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10;
+ 
  -- Now check the results from plain indexscan
  SET enable_seqscan = OFF;
  SET enable_indexscan = ON;
*************** EXPLAIN (COSTS OFF)
*** 433,438 ****
--- 437,450 ----
  SELECT count(*) FROM radix_text_tbl WHERE t ~>~  'Worth                         St  ';
  SELECT count(*) FROM radix_text_tbl WHERE t ~>~  'Worth                         St  ';
  
+ EXPLAIN (COSTS OFF)
+ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10;
+ SELECT * FROM gpolygon_tbl ORDER BY f1 <-> '(0,0)'::point LIMIT 10;
+ 
+ EXPLAIN (COSTS OFF)
+ SELECT * FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10;
+ SELECT * FROM gcircle_tbl ORDER BY f1 <-> '(200,300)'::point LIMIT 10;
+ 
  -- Now check the results from bitmap indexscan
  SET enable_seqscan = OFF;
  SET enable_indexscan = OFF;
