diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
new file mode 100644
index 31ce279..b265e9c
*** 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)
*** 760,766 ****
          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;
--- 768,774 ----
          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)
*** 779,784 ****
--- 787,793 ----
      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)
*** 791,801 ****
  </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
--- 800,815 ----
  </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 717cb85..f2dc301
*** 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 "lib/pairingheap.h"
*************** gistindex_keytest(IndexScanDesc scan,
*** 56,62 ****
  	GISTSTATE  *giststate = so->giststate;
  	ScanKey		key = scan->keyData;
  	int			keySize = scan->numberOfKeys;
! 	double	   *distance_p;
  	Relation	r = scan->indexRelation;
  
  	*recheck_p = false;
--- 57,63 ----
  	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,
*** 73,79 ****
  		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;
  	}
  
--- 74,83 ----
  		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,
*** 171,177 ****
  		if ((key->sk_flags & SK_ISNULL) || isNull)
  		{
  			/* Assume distance computes as null and sorts to the end */
! 			*distance_p = get_float8_infinity();
  		}
  		else
  		{
--- 175,182 ----
  		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,
*** 192,209 ****
  			 * 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++;
--- 197,216 ----
  			 * 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,
*** 235,241 ****
   * sibling will be processed next.
   */
  static void
! gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
  			 TIDBitmap *tbm, int64 *ntids)
  {
  	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
--- 242,248 ----
   * 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
*** 280,286 ****
  
  		/* Insert it into the queue using same distances as for this page */
  		memcpy(item->distances, myDistances,
! 			   sizeof(double) * scan->numberOfOrderBys);
  
  		pairingheap_add(so->queue, &item->phNode);
  
--- 287,293 ----
  
  		/* Insert it into the queue using same distances as for this page */
  		memcpy(item->distances, myDistances,
! 			   sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
  
  		pairingheap_add(so->queue, &item->phNode);
  
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 368,374 ****
  
  			/* Insert it into the queue using new distance data */
  			memcpy(item->distances, so->distances,
! 				   sizeof(double) * scan->numberOfOrderBys);
  
  			pairingheap_add(so->queue, &item->phNode);
  
--- 375,381 ----
  
  			/* Insert it into the queue using new distance data */
  			memcpy(item->distances, so->distances,
! 				   sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
  
  			pairingheap_add(so->queue, &item->phNode);
  
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 380,406 ****
  }
  
  /*
   * Extract next item (in order) from search queue
   *
   * Returns a GISTSearchItem or NULL.  Caller must pfree item when done with it.
   */
  static GISTSearchItem *
! getNextGISTSearchItem(GISTScanOpaque so)
  {
  	GISTSearchItem *item;
  
  	if (!pairingheap_is_empty(so->queue))
  	{
! 		item = (GISTSearchItem *) pairingheap_remove_first(so->queue);
  	}
  	else
  	{
! 		/* Done when both heaps are empty */
! 		item = NULL;
  	}
- 
- 	/* Return item; caller is responsible to pfree it */
- 	return item;
  }
  
  /*
--- 387,490 ----
  }
  
  /*
+  * Do this tree item distance values needs recheck?
+  */
+ static bool
+ searchTreeItemNeedDistanceRecheck(IndexScanDesc scan, GISTSearchItem *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, GISTSearchItem *item)
+ {
+ 	GISTScanOpaque		so = (GISTScanOpaque) scan->opaque;
+ 	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 */
+ 	for (i = 0; i < scan->numberOfOrderBys; i++)
+ 	{
+ 		if (item->distances[i].recheck)
+ 		{
+ 			/* Re-calculate lossy distance */
+ 			ScanKey	key = scan->orderByData + i;
+ 			float8 	newDistance;
+ 
+ 			item->distances[i].recheck = false;
+ 			if (isnull[key->sk_attno - 1])
+ 			{
+ 				item->distances[i].value = -get_float8_infinity();
+ 				continue;
+ 			}
+ 
+ 			newDistance = DatumGetFloat8(
+ 				FunctionCall2Coll(&so->orderByRechecks[i],
+ 					 key->sk_collation,
+ 					 values[key->sk_attno - 1],
+ 					 key->sk_argument));
+ 
+ 			item->distances[i].value = newDistance;
+ 
+ 		}
+ 	}
+ 
+ 	pairingheap_add(so->queue, item);
+ }
+ 
+ /*
   * Extract next item (in order) from search queue
   *
   * Returns a GISTSearchItem or NULL.  Caller must pfree item when done with it.
   */
  static GISTSearchItem *
! getNextGISTSearchItem(IndexScanDesc scan)
  {
+ 	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
  	GISTSearchItem *item;
  
  	if (!pairingheap_is_empty(so->queue))
  	{
! 		for (;;)
! 		{
! 			item = (GISTSearchItem *) pairingheap_remove_first(so->queue);
! 
! 			/* Recheck distance from heap tuple if needed */
! 			if (GISTSearchItemIsHeap(*item) &&
! 				searchTreeItemNeedDistanceRecheck(scan, item))
! 			{
! 				searchTreeItemDistanceRecheck(scan, item);
! 				continue;
! 			}
! 			return item;
! 		}
  	}
  	else
  	{
! 		return NULL;
  	}
  }
  
  /*
*************** getNextNearest(IndexScanDesc scan)
*** 414,420 ****
  
  	do
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(so);
  
  		if (!item)
  			break;
--- 498,504 ----
  
  	do
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(scan);
  
  		if (!item)
  			break;
*************** gistgettuple(PG_FUNCTION_ARGS)
*** 493,499 ****
  			/* find and process the next index page */
  			do
  			{
! 				GISTSearchItem *item = getNextGISTSearchItem(so);
  
  				if (!item)
  					PG_RETURN_BOOL(false);
--- 577,583 ----
  			/* find and process the next index page */
  			do
  			{
! 				GISTSearchItem *item = getNextGISTSearchItem(scan);
  
  				if (!item)
  					PG_RETURN_BOOL(false);
*************** gistgetbitmap(PG_FUNCTION_ARGS)
*** 544,550 ****
  	 */
  	for (;;)
  	{
! 		GISTSearchItem *item = getNextGISTSearchItem(so);
  
  		if (!item)
  			break;
--- 628,634 ----
  	 */
  	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 9fab6c8..c2692c3
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
*************** gist_poly_consistent(PG_FUNCTION_ARGS)
*** 1089,1094 ****
--- 1089,1095 ----
  	PG_RETURN_BOOL(result);
  }
  
+ 
  /**************************************************
   * Circle ops
   **************************************************/
*************** gist_point_distance(PG_FUNCTION_ARGS)
*** 1441,1443 ****
--- 1442,1478 ----
  
  	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 991858f..fab7237
*** 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"
  
*************** pairingheap_GISTSearchItem_cmp(const pai
*** 30,53 ****
  	const GISTSearchItem *sa = (const GISTSearchItem *) a;
  	const GISTSearchItem *sb = (const GISTSearchItem *) b;
  	IndexScanDesc scan = (IndexScanDesc) arg;
! 	int			i;
  
  	/* 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;
! 	}
  
! 	/* Heap items go before inner pages, to ensure a depth-first search */
! 	if (GISTSearchItemIsHeap(*sa) && !GISTSearchItemIsHeap(*sb))
! 		return 1;
! 	if (!GISTSearchItemIsHeap(*sa) && GISTSearchItemIsHeap(*sb))
! 		return -1;
  
! 	return 0;
! }
  
  
  /*
   * Index AM API functions for scanning GiST indexes
--- 33,65 ----
  	const GISTSearchItem *sa = (const GISTSearchItem *) a;
  	const GISTSearchItem *sb = (const GISTSearchItem *) b;
  	IndexScanDesc scan = (IndexScanDesc) arg;
! 	int			i, recheckCmp = 0;
  
  	/* 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;
  
! 		/* Heap items go before inner pages, to ensure a depth-first search */
! 		if (GISTSearchItemIsHeap(*sa) && !GISTSearchItemIsHeap(*sb))
! 			return 1;
! 		if (!GISTSearchItemIsHeap(*sa) && GISTSearchItemIsHeap(*sb))
! 			return -1;
  
+ 		/*
+ 		 * When all distance values are the same, items without recheck
+ 		 * can be immediately returned.  So they are placed first.
+ 		 */
+ 		if (recheckCmp == 0 && distance_a.recheck != distance_b.recheck)
+ 			recheckCmp = distance_b.recheck ? 1 : -1;
+ 	}
+ 
+ 	return recheckCmp;
+ }
  
  /*
   * Index AM API functions for scanning GiST indexes
*************** gistbeginscan(PG_FUNCTION_ARGS)
*** 83,91 ****
  	so->queueCxt = giststate->scanCxt;	/* see gistrescan */
  
  	/* workspaces with size dependent on numberOfOrderBys: */
! 	so->distances = palloc(sizeof(double) * scan->numberOfOrderBys);
  	so->qual_ok = true;			/* in case there are zero keys */
  
  	scan->opaque = so;
  
  	MemoryContextSwitchTo(oldCxt);
--- 95,111 ----
  	so->queueCxt = giststate->scanCxt;	/* see gistrescan */
  
  	/* workspaces with size dependent on 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)
*** 238,243 ****
--- 258,267 ----
  					 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 e6e4d28..90cf088
*** a/src/backend/access/index/genam.c
--- b/src/backend/access/index/genam.c
*************** RelationGetIndexScan(Relation indexRelat
*** 124,129 ****
--- 124,132 ----
  	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 00c1d69..9c57311
*** 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 6cb6be5..1b2a511
*** a/src/backend/utils/adt/geo_ops.c
--- b/src/backend/utils/adt/geo_ops.c
*************** static Point *interpt_sl(LSEG *lseg, LIN
*** 70,79 ****
  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 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);
- static double dist_ppoly_internal(Point *pt, POLYGON *poly);
  
  
  /*
--- 70,79 ----
  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 double 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)
*** 2623,2628 ****
--- 2623,2660 ----
  }
  
  /*
+  * 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_ppoly_internal(Point *pt, POLYGON *
*** 2701,2706 ****
--- 2733,2747 ----
  	return result;
  }
  
+ /*
+  * 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)));
+ }
  
  /*---------------------------------------------------------------------
   *		interpt_
*************** pt_contained_circle(PG_FUNCTION_ARGS)
*** 5057,5079 ****
  }
  
  
- /*		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
--- 5098,5103 ----
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
new file mode 100644
index d1d6247..359d488
*** 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 ce83042..27bd81c
*** a/src/include/access/gist_private.h
--- b/src/include/access/gist_private.h
***************
*** 17,24 ****
--- 17,26 ----
  #include "access/gist.h"
  #include "access/itup.h"
  #include "access/xlogreader.h"
+ #include "executor/tuptable.h"
  #include "fmgr.h"
  #include "lib/pairingheap.h"
+ #include "nodes/execnodes.h"
  #include "storage/bufmgr.h"
  #include "storage/buffile.h"
  #include "utils/hsearch.h"
*************** typedef struct GISTSearchHeapItem
*** 120,125 ****
--- 122,136 ----
  	bool		recheck;		/* T if quals must be rechecked */
  } GISTSearchHeapItem;
  
+ /*
+  * KNN distance item: distance which can be rechecked from heap tuple.
+  */
+ typedef struct GISTSearchTreeItemDistance
+ {
+ 	double	value;
+ 	bool	recheck;
+ } GISTSearchTreeItemDistance;
+ 
  /* Unvisited item, either index page or heap tuple */
  typedef struct GISTSearchItem
  {
*************** typedef struct GISTSearchItem
*** 131,143 ****
  		/* we must store parentlsn to detect whether a split occurred */
  		GISTSearchHeapItem heap;	/* heap info, if heap tuple */
  	}			data;
! 	double		distances[FLEXIBLE_ARRAY_MEMBER];		/* numberOfOrderBys
! 														 * entries */
  } GISTSearchItem;
  
  #define GISTSearchItemIsHeap(item)	((item).blkno == InvalidBlockNumber)
  
! #define SizeOfGISTSearchItem(n_distances) (offsetof(GISTSearchItem, distances) + sizeof(double) * (n_distances))
  
  /*
   * GISTScanOpaqueData: private state for a scan of a GiST index
--- 142,154 ----
  		/* we must store parentlsn to detect whether a split occurred */
  		GISTSearchHeapItem heap;	/* heap info, if heap tuple */
  	}			data;
! 	GISTSearchTreeItemDistance	distances[FLEXIBLE_ARRAY_MEMBER];	/* array with numberOfOrderBys entries */
  } GISTSearchItem;
  
  #define GISTSearchItemIsHeap(item)	((item).blkno == InvalidBlockNumber)
  
! #define GSTIHDRSZ offsetof(GISTSearchTreeItem, distances)
! #define SizeOfGISTSearchItem(n_distances) (offsetof(GISTSearchItem, distances) + sizeof(GISTSearchTreeItemDistance) * (n_distances))
  
  /*
   * GISTScanOpaqueData: private state for a scan of a GiST index
*************** typedef struct GISTScanOpaqueData
*** 151,162 ****
  	bool		firstCall;		/* true until first gistgettuple call */
  
  	/* pre-allocated workspace arrays */
! 	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;
--- 162,176 ----
  	bool		firstCall;		/* true until first gistgettuple call */
  
  	/* pre-allocated workspace arrays */
! 	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 9bb6362..b1be157
*** 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 5aab896..4a6fa7f
*** 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 49d3d13..43f77ed
*** a/src/include/catalog/pg_amproc.h
--- b/src/include/catalog/pg_amproc.h
*************** DATA(insert (	2594   604 604 4 2580 ));
*** 205,210 ****
--- 205,211 ----
  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 ));
*** 212,217 ****
--- 213,219 ----
  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 af991d3..b375215
*** 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 = 3276 (  "<->"	  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 = 3276 (  "<->"	  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   3276	   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 4268b99..7cbcc70
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID = 727 (  dist_sl		   PGN
*** 845,850 ****
--- 845,852 ----
  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 = 3275 (  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
*** 4076,4081 ****
--- 4078,4085 ----
  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 8da6c6c..4632f64
*** a/src/include/utils/geo_decls.h
--- b/src/include/utils/geo_decls.h
*************** extern Datum circle_diameter(PG_FUNCTION
*** 392,399 ****
--- 392,401 ----
  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
*** 417,422 ****
--- 419,425 ----
  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 5603817..cb18986
*** a/src/test/regress/expected/create_index.out
--- b/src/test/regress/expected/create_index.out
*************** SELECT count(*) FROM radix_text_tbl WHER
*** 372,377 ****
--- 372,407 ----
      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
*** 1152,1157 ****
--- 1182,1235 ----
      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 f779fa0..5df9008
*** a/src/test/regress/sql/create_index.sql
--- b/src/test/regress/sql/create_index.sql
*************** SELECT count(*) FROM radix_text_tbl WHER
*** 224,229 ****
--- 224,233 ----
  
  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)
*** 437,442 ****
--- 441,454 ----
  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;
