diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
new file mode 100644
index 31ce279..c354411
*** 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_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,804 ****
  </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
         minus infinity are used internally to handle cases such as nulls, so it
         is not recommended that <function>distance</> functions return these
         values.)
--- 800,821 ----
  </programlisting>
  
         The arguments to the <function>distance</> function are identical to
!        the arguments of the <function>consistent</> function.
!       </para>
! 
!       <para>
!        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. For
!        leaf nodes, the returned distance must be accurate, if the
!        <function>distance</> function returns *recheck == false for the tuple.
!        Otherwise the same approximation is allowed, and the executor will
!        re-order ambiguous cases after recalculating the actual distance.
!       </para>
! 
!       <para>
!        The result value can be any finite <type>float8</> value.  (Infinity and
         minus infinity are used internally to handle cases such as nulls, so it
         is not recommended that <function>distance</> functions return these
         values.)
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
new file mode 100644
index 717cb85..53c061d
*** a/src/backend/access/gist/gistget.c
--- b/src/backend/access/gist/gistget.c
*************** gistindex_keytest(IndexScanDesc scan,
*** 176,181 ****
--- 176,182 ----
  		else
  		{
  			Datum		dist;
+ 			bool		recheck;
  			GISTENTRY	de;
  
  			gistdentryinit(giststate, key->sk_attno - 1, &de,
*************** gistindex_keytest(IndexScanDesc scan,
*** 192,207 ****
  			 * 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);
  		}
--- 193,213 ----
  			 * always be zero, but might as well pass it for possible future
  			 * use.)
  			 *
! 			 * Distance functions get a recheck argument as well. In this
! 			 * case the returned distance is the lower bound of distance
! 			 * and needs to be rechecked. We return single recheck flag
! 			 * which means that both quals and distances are to be
! 			 * rechecked.
  			 */
! 			dist = FunctionCall5Coll(&key->sk_func,
  									 key->sk_collation,
  									 PointerGetDatum(&de),
  									 key->sk_argument,
  									 Int32GetDatum(key->sk_strategy),
! 									 ObjectIdGetDatum(key->sk_subtype),
! 									 PointerGetDatum(&recheck));
! 
! 			*recheck_p |= recheck;
  
  			*distance_p = DatumGetFloat8(dist);
  		}
*************** getNextNearest(IndexScanDesc scan)
*** 411,416 ****
--- 417,423 ----
  {
  	GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
  	bool		res = false;
+ 	int			i;
  
  	do
  	{
*************** getNextNearest(IndexScanDesc scan)
*** 424,429 ****
--- 431,441 ----
  			/* found a heap item at currently minimal distance */
  			scan->xs_ctup.t_self = item->data.heap.heapPtr;
  			scan->xs_recheck = item->data.heap.recheck;
+ 			for (i = 0; i < scan->numberOfOrderBys; i++)
+ 			{
+ 				scan->xs_distances[i] = Float8GetDatum(item->distances[i]);
+ 				scan->xs_distance_nulls[i] = false;
+ 			}
  			res = true;
  		}
  		else
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
new file mode 100644
index 9fab6c8..37bf5d5
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
*************** gist_point_distance(PG_FUNCTION_ARGS)
*** 1441,1443 ****
--- 1441,1480 ----
  
  	PG_RETURN_FLOAT8(distance);
  }
+ 
+ /*
+  * The inexact GiST distance method for geometric types that store bounding
+  * boxes.
+  *
+  * 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_bbox_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;
+ 
+ 	/* Bounding box distance is always inexact. */
+ 	*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..55c98b4
*** a/src/backend/access/gist/gistscan.c
--- b/src/backend/access/gist/gistscan.c
*************** gistbeginscan(PG_FUNCTION_ARGS)
*** 85,90 ****
--- 85,95 ----
  	/* workspaces with size dependent on numberOfOrderBys: */
  	so->distances = palloc(sizeof(double) * scan->numberOfOrderBys);
  	so->qual_ok = true;			/* in case there are zero keys */
+ 	if (scan->numberOfOrderBys > 0)
+ 	{
+ 		scan->xs_distances = palloc(sizeof(Datum) * scan->numberOfOrderBys);
+ 		scan->xs_distance_nulls = palloc(sizeof(bool) * scan->numberOfOrderBys);
+ 	}
  
  	scan->opaque = so;
  
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
new file mode 100644
index 48fa919..430abd0
*** a/src/backend/executor/nodeIndexscan.c
--- b/src/backend/executor/nodeIndexscan.c
***************
*** 28,41 ****
--- 28,117 ----
  #include "access/relscan.h"
  #include "executor/execdebug.h"
  #include "executor/nodeIndexscan.h"
+ #include "lib/pairingheap.h"
  #include "optimizer/clauses.h"
  #include "utils/array.h"
+ #include "utils/datum.h"
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/rel.h"
  
+ /*
+  * When an ordering operator is used, tuples fetched from the index that
+  * need to be reordered are queued in a pairing heap, as ReorderTuples.
+  */
+ typedef struct
+ {
+ 	pairingheap_node ph_node;
+ 	HeapTuple	htup;
+ 	Datum	   *distances;
+ 	bool	   *distance_nulls;
+ } ReorderTuple;
+ 
+ static int
+ cmp_distances(const Datum *adist, const bool *anulls,
+ 			  const Datum *bdist, const bool *bnulls,
+ 			  IndexScanState *node)
+ {
+ 	int			i;
+ 	int			result;
+ 
+ 	for (i = 0; i < node->iss_NumOrderByKeys; i++)
+ 	{
+ 		SortSupport ssup = &node->iss_SortSupport[i];
+ 
+ 		/* Handle nulls. We only support NULLS LAST */
+ 		if (anulls[i] && !bnulls[i])
+ 			return 1;
+ 		else if (!anulls[i] && bnulls[i])
+ 			return -1;
+ 		else if (anulls[i] && bnulls[i])
+ 			return 0;
+ 
+ 		result = ssup->comparator(adist[i], bdist[i], ssup);
+ 		if (result != 0)
+ 			return result;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ /*
+  * Pairing heap provides getting topmost (greatest) element while KNN provides
+  * ascending sort. That's why we inverse sort order.
+  */
+ static int
+ reorderbuffer_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
+ {
+ 	ReorderTuple *rta = (ReorderTuple *) a;
+ 	ReorderTuple *rtb = (ReorderTuple *) b;
+ 	IndexScanState *node = (IndexScanState *) arg;
+ 
+ 	return -cmp_distances(rta->distances, rta->distance_nulls,
+ 						  rtb->distances, rtb->distance_nulls,
+ 						  node);
+ }
+ 
+ static void
+ copyDistances(IndexScanState *node, const Datum *src_datums, const bool *src_nulls,
+ 			  Datum *dst_datums, bool *dst_nulls)
+ {
+ 	int			i;
+ 
+ 	for (i = 0; i < node->iss_NumOrderByKeys; i++)
+ 	{
+ 		if (!src_nulls[i])
+ 			dst_datums[i] =	datumCopy(src_datums[i],
+ 									  node->iss_DistanceTypByVals[i],
+ 									  node->iss_DistanceTypLens[i]);
+ 		else
+ 			dst_datums[i] = (Datum) 0;
+ 		dst_nulls[i] = src_nulls[i];
+ 	}
+ }
  
  static TupleTableSlot *IndexNext(IndexScanState *node);
+ static void RecheckOrderBys(IndexScanState *node, TupleTableSlot *slot);
  
  
  /* ----------------------------------------------------------------
*************** IndexNext(IndexScanState *node)
*** 54,59 ****
--- 130,137 ----
  	IndexScanDesc scandesc;
  	HeapTuple	tuple;
  	TupleTableSlot *slot;
+ 	MemoryContext oldContext;
+ 	ReorderTuple *reordertuple;
  
  	/*
  	 * extract necessary information from index scan node
*************** IndexNext(IndexScanState *node)
*** 72,82 ****
  	econtext = node->ss.ps.ps_ExprContext;
  	slot = node->ss.ss_ScanTupleSlot;
  
! 	/*
! 	 * ok, now that we have what we need, fetch the next tuple.
! 	 */
! 	while ((tuple = index_getnext(scandesc, direction)) != NULL)
  	{
  		/*
  		 * Store the scanned tuple in the scan tuple slot of the scan state.
  		 * Note: we pass 'false' because tuples returned by amgetnext are
--- 150,209 ----
  	econtext = node->ss.ps.ps_ExprContext;
  	slot = node->ss.ss_ScanTupleSlot;
  
! 	for (;;)
  	{
+ 		/* Check the reorder queue first */
+ 		if (node->iss_ReorderQueue)
+ 		{
+ 			if (pairingheap_is_empty(node->iss_ReorderQueue))
+ 			{
+ 				if (node->iss_ReachedEnd)
+ 					break;
+ 			}
+ 			else
+ 			{
+ 				reordertuple = (ReorderTuple *) pairingheap_first(node->iss_ReorderQueue);
+ 
+ 				/* Check if we can return this tuple */
+ 				if (node->iss_ReachedEnd ||
+ 					cmp_distances(reordertuple->distances,
+ 								  reordertuple->distance_nulls,
+ 								  scandesc->xs_distances,
+ 								  scandesc->xs_distance_nulls,
+ 								  node) < 0)
+ 				{
+ 					(void) pairingheap_remove_first(node->iss_ReorderQueue);
+ 
+ 					tuple = reordertuple->htup;
+ 					pfree(reordertuple);
+ 
+ 					/*
+ 					 * Store the buffered tuple in the scan tuple slot of the
+ 					 * scan state.
+ 					 */
+ 					ExecStoreTuple(tuple, slot, InvalidBuffer, true);
+ 					return slot;
+ 				}
+ 			}
+ 		}
+ 
+ 		/* Fetch next tuple from the index */
+ 		tuple = index_getnext(scandesc, direction);
+ 
+ 		if (!tuple)
+ 		{
+ 			/*
+ 			 * No more tuples from the index. If we have a reorder queue,
+ 			 * we still need to drain all the remaining tuples in the queue
+ 			 * before we're done.
+ 			 */
+ 			node->iss_ReachedEnd = true;
+ 			if (node->iss_ReorderQueue)
+ 				continue;
+ 			else
+ 				break;
+ 		}
+ 
  		/*
  		 * Store the scanned tuple in the scan tuple slot of the scan state.
  		 * Note: we pass 'false' because tuples returned by amgetnext are
*************** IndexNext(IndexScanState *node)
*** 103,108 ****
--- 230,300 ----
  			}
  		}
  
+ 		/*
+ 		 * Re-check the ordering.
+ 		 */
+ 		if (node->iss_ReorderQueue)
+ 		{
+ 			/*
+ 			 * The index returned the distance, as calculated by the indexam,
+ 			 * in scandesc->xs_distances.  If the index was lossy, we have to
+ 			 * recheck the ordering expression too. Otherwise we take the
+ 			 * indexam's values as is.
+ 			 */
+ 			if (scandesc->xs_recheck)
+ 				RecheckOrderBys(node, slot);
+ 			else
+ 				copyDistances(node,
+ 							  scandesc->xs_distances,
+ 							  scandesc->xs_distance_nulls,
+ 							  node->iss_Distances,
+ 							  node->iss_DistanceNulls);
+ 
+ 			/*
+ 			 * Can we return this tuple immediately, or does it need to be
+ 			 * pushed to the reorder queue? If this tuple's distance was
+ 			 * inaccurate, we can't return it yet, because the next tuple
+ 			 * from the index might need to come before this one. Also,
+ 			 * we can't return it yet if there are any smaller tuples in the
+ 			 * queue already.
+ 			 */
+ 			if (!pairingheap_is_empty(node->iss_ReorderQueue))
+ 				reordertuple = (ReorderTuple *) pairingheap_first(node->iss_ReorderQueue);
+ 			else
+ 				reordertuple = NULL;
+ 
+ 			if ((cmp_distances(node->iss_Distances,
+ 							   node->iss_DistanceNulls,
+ 							   scandesc->xs_distances,
+ 							   scandesc->xs_distance_nulls,
+ 							   node) > 0) ||
+ 				(reordertuple && cmp_distances(node->iss_Distances,
+ 											   node->iss_DistanceNulls,
+ 											   reordertuple->distances,
+ 											   reordertuple->distance_nulls,
+ 											   node) > 0))
+ 			{
+ 				/* Need to put this to the queue */
+ 				oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
+ 				reordertuple = (ReorderTuple *) palloc(sizeof(ReorderTuple));
+ 				reordertuple->htup = heap_copytuple(tuple);
+ 				reordertuple->distances = (Datum *) palloc(sizeof(Datum) * scandesc->numberOfOrderBys);
+ 				reordertuple->distance_nulls = (bool *) palloc(sizeof(bool) * scandesc->numberOfOrderBys);
+ 				copyDistances(node,
+ 							  node->iss_Distances,
+ 							  node->iss_DistanceNulls,
+ 							  reordertuple->distances,
+ 							  reordertuple->distance_nulls);
+ 
+ 				pairingheap_add(node->iss_ReorderQueue, &reordertuple->ph_node);
+ 
+ 				MemoryContextSwitchTo(oldContext);
+ 
+ 				continue;
+ 			}
+ 		}
+ 
+ 		/* Ok, got a tuple to return */
  		return slot;
  	}
  
*************** IndexNext(IndexScanState *node)
*** 114,119 ****
--- 306,346 ----
  }
  
  /*
+  * Calculate the expressions in the ORDER BY clause, based on the heap tuple.
+  */
+ static void
+ RecheckOrderBys(IndexScanState *node, TupleTableSlot *slot)
+ {
+ 	IndexScanDesc scandesc;
+ 	ExprContext *econtext;
+ 	int			i;
+ 	ListCell   *l;
+ 	MemoryContext oldContext;
+ 
+ 	scandesc = node->iss_ScanDesc;
+ 	econtext = node->ss.ps.ps_ExprContext;
+ 	econtext->ecxt_scantuple = slot;
+ 	ResetExprContext(econtext);
+ 
+ 	oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
+ 
+ 	i = 0;
+ 	foreach(l, node->indexorderbyorig)
+ 	{
+ 		ExprState *orderby = (ExprState *) lfirst(l);
+ 
+ 		Assert(i < scandesc->numberOfOrderBys);
+ 
+ 		node->iss_Distances[i] = ExecEvalExpr(orderby,
+ 											  econtext,
+ 											  &node->iss_DistanceNulls[i],
+ 											  NULL);
+ 	}
+ 
+ 	MemoryContextSwitchTo(oldContext);
+ }
+ 
+ /*
   * IndexRecheck -- access method routine to recheck a tuple in EvalPlanQual
   */
  static bool
*************** ExecInitIndexScan(IndexScan *node, EStat
*** 465,470 ****
--- 692,698 ----
  	IndexScanState *indexstate;
  	Relation	currentRelation;
  	bool		relistarget;
+ 	int			i;
  
  	/*
  	 * create state structure
*************** ExecInitIndexScan(IndexScan *node, EStat
*** 501,506 ****
--- 729,737 ----
  	indexstate->indexqualorig = (List *)
  		ExecInitExpr((Expr *) node->indexqualorig,
  					 (PlanState *) indexstate);
+ 	indexstate->indexorderbyorig = (List *)
+ 		ExecInitExpr((Expr *) node->indexorderbyorig,
+ 					 (PlanState *) indexstate);
  
  	/*
  	 * tuple table initialization
*************** ExecInitIndexScan(IndexScan *node, EStat
*** 581,586 ****
--- 812,863 ----
  						   NULL,	/* no ArrayKeys */
  						   NULL);
  
+ 	/* Initialize sort support, if we need to re-check ORDER BY exprs */
+ 	if (indexstate->iss_NumOrderByKeys > 0)
+ 	{
+ 		int			numOrderByKeys = indexstate->iss_NumOrderByKeys;
+ 
+ 		/*
+ 		 * Prepare sort support, and look up the distance type for each
+ 		 * ORDER BY expression.
+ 		 */
+ 		indexstate->iss_SortSupport =
+ 			palloc0(numOrderByKeys * sizeof(SortSupportData));
+ 		indexstate->iss_DistanceTypByVals =
+ 			palloc(numOrderByKeys * sizeof(bool));
+ 		indexstate->iss_DistanceTypLens =
+ 			palloc(numOrderByKeys * sizeof(int16));
+ 		for (i = 0; i < indexstate->iss_NumOrderByKeys; i++)
+ 		{
+ 			Oid		distanceType;
+ 			Oid		opfamily;
+ 			int16	strategy;
+ 
+ 			PrepareSortSupportFromOrderingOp(node->indexsortops[i],
+ 											 &indexstate->iss_SortSupport[i]);
+ 
+ 			if (!get_ordering_op_properties(node->indexsortops[i],
+ 										 &opfamily, &distanceType, &strategy))
+ 			{
+ 				elog(LOG, "operator %u is not a valid ordering operator",
+ 					 node->indexsortops[i]);
+ 			}
+ 			get_typlenbyval(distanceType,
+ 							&indexstate->iss_DistanceTypLens[i],
+ 							&indexstate->iss_DistanceTypByVals[i]);
+ 		}
+ 
+ 		/* allocate arrays to hold the re-calculated distances */
+ 		indexstate->iss_Distances =
+ 			palloc(indexstate->iss_NumOrderByKeys * sizeof(Datum));
+ 		indexstate->iss_DistanceNulls =
+ 			palloc(indexstate->iss_NumOrderByKeys * sizeof(bool));
+ 
+ 		/* and initialize the reorder queue */
+ 		indexstate->iss_ReorderQueue = pairingheap_allocate(reorderbuffer_cmp,
+ 															indexstate);
+ 	}
+ 
  	/*
  	 * If we have runtime keys, we need an ExprContext to evaluate them. The
  	 * node's standard context won't do because we want to reset that context
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
new file mode 100644
index 76ba1bf..7daaadf
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
***************
*** 22,27 ****
--- 22,28 ----
  #include "access/skey.h"
  #include "access/sysattr.h"
  #include "catalog/pg_class.h"
+ #include "catalog/pg_operator.h"
  #include "foreign/fdwapi.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
*************** static void copy_plan_costsize(Plan *des
*** 102,108 ****
  static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
  static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
  			   Oid indexid, List *indexqual, List *indexqualorig,
! 			   List *indexorderby, List *indexorderbyorig,
  			   ScanDirection indexscandir);
  static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
  				   Index scanrelid, Oid indexid,
--- 103,109 ----
  static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
  static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
  			   Oid indexid, List *indexqual, List *indexqualorig,
! 			   List *indexorderby, List *indexorderbyorig, Oid *sortOperators,
  			   ScanDirection indexscandir);
  static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
  				   Index scanrelid, Oid indexid,
*************** static Plan *prepare_sort_from_pathkeys(
*** 168,174 ****
  						   Oid **p_collations,
  						   bool **p_nullsFirst);
  static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec,
! 					   TargetEntry *tle,
  					   Relids relids);
  static Material *make_material(Plan *lefttree);
  
--- 169,175 ----
  						   Oid **p_collations,
  						   bool **p_nullsFirst);
  static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec,
! 					   Expr *tlexpr,
  					   Relids relids);
  static Material *make_material(Plan *lefttree);
  
*************** create_indexscan_plan(PlannerInfo *root,
*** 1158,1163 ****
--- 1159,1165 ----
  	List	   *stripped_indexquals;
  	List	   *fixed_indexquals;
  	List	   *fixed_indexorderbys;
+ 	Oid		   *sortOperators = NULL;
  	ListCell   *l;
  
  	/* it should be a base rel... */
*************** create_indexscan_plan(PlannerInfo *root,
*** 1266,1271 ****
--- 1268,1309 ----
  			replace_nestloop_params(root, (Node *) indexorderbys);
  	}
  
+ 	if (best_path->path.pathkeys && indexorderbys)
+ 	{
+ 		int			numOrderBys = list_length(indexorderbys);
+ 		int			i;
+ 		ListCell   *pathkeyCell,
+ 				   *exprCell;
+ 		PathKey	   *pathkey;
+ 		Expr	   *expr;
+ 
+ 		sortOperators = (Oid *) palloc(numOrderBys * sizeof(Oid));
+ 
+ 		/*
+ 		 * Get ordering operator for each pathkey. Pathkey contains pointer
+ 		 * to equivalence class. But it's not enough because we need the
+ 		 * expression datatype to lookup opfamily member. That's why we've
+ 		 * to dig and equivalence member.
+ 		 */
+ 		i = 0;
+ 		forboth (pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
+ 		{
+ 			EquivalenceMember *em;
+ 			pathkey = (PathKey *) lfirst(pathkeyCell);
+ 			expr = (Expr *) lfirst(exprCell);
+ 
+ 			/* Find equivalence member by order by expression */
+ 			em = find_ec_member_for_tle(pathkey->pk_eclass, expr, NULL);
+ 
+ 			/* Get sort operator from opfamily */
+ 			sortOperators[i] = get_opfamily_member(pathkey->pk_opfamily,
+ 												   em->em_datatype,
+ 												   em->em_datatype,
+ 												   pathkey->pk_strategy);
+ 			i++;
+ 		}
+ 	}
+ 
  	/* Finally ready to build the plan node */
  	if (indexonly)
  		scan_plan = (Scan *) make_indexonlyscan(tlist,
*************** create_indexscan_plan(PlannerInfo *root,
*** 1285,1290 ****
--- 1323,1329 ----
  											stripped_indexquals,
  											fixed_indexorderbys,
  											indexorderbys,
+ 											sortOperators,
  											best_path->indexscandir);
  
  	copy_path_costsize(&scan_plan->plan, &best_path->path);
*************** make_indexscan(List *qptlist,
*** 3327,3332 ****
--- 3366,3372 ----
  			   List *indexqualorig,
  			   List *indexorderby,
  			   List *indexorderbyorig,
+ 			   Oid *sortOperators,
  			   ScanDirection indexscandir)
  {
  	IndexScan  *node = makeNode(IndexScan);
*************** make_indexscan(List *qptlist,
*** 3344,3349 ****
--- 3384,3390 ----
  	node->indexorderby = indexorderby;
  	node->indexorderbyorig = indexorderbyorig;
  	node->indexorderdir = indexscandir;
+ 	node->indexsortops = sortOperators;
  
  	return node;
  }
*************** prepare_sort_from_pathkeys(PlannerInfo *
*** 3967,3973 ****
  			tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
  			if (tle)
  			{
! 				em = find_ec_member_for_tle(ec, tle, relids);
  				if (em)
  				{
  					/* found expr at right place in tlist */
--- 4008,4014 ----
  			tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
  			if (tle)
  			{
! 				em = find_ec_member_for_tle(ec, tle->expr, relids);
  				if (em)
  				{
  					/* found expr at right place in tlist */
*************** prepare_sort_from_pathkeys(PlannerInfo *
*** 3998,4004 ****
  			foreach(j, tlist)
  			{
  				tle = (TargetEntry *) lfirst(j);
! 				em = find_ec_member_for_tle(ec, tle, relids);
  				if (em)
  				{
  					/* found expr already in tlist */
--- 4039,4045 ----
  			foreach(j, tlist)
  			{
  				tle = (TargetEntry *) lfirst(j);
! 				em = find_ec_member_for_tle(ec, tle->expr, relids);
  				if (em)
  				{
  					/* found expr already in tlist */
*************** prepare_sort_from_pathkeys(PlannerInfo *
*** 4126,4139 ****
   */
  static EquivalenceMember *
  find_ec_member_for_tle(EquivalenceClass *ec,
! 					   TargetEntry *tle,
  					   Relids relids)
  {
- 	Expr	   *tlexpr;
  	ListCell   *lc;
  
  	/* We ignore binary-compatible relabeling on both ends */
- 	tlexpr = tle->expr;
  	while (tlexpr && IsA(tlexpr, RelabelType))
  		tlexpr = ((RelabelType *) tlexpr)->arg;
  
--- 4167,4178 ----
   */
  static EquivalenceMember *
  find_ec_member_for_tle(EquivalenceClass *ec,
! 					   Expr *tlexpr,
  					   Relids relids)
  {
  	ListCell   *lc;
  
  	/* We ignore binary-compatible relabeling on both ends */
  	while (tlexpr && IsA(tlexpr, RelabelType))
  		tlexpr = ((RelabelType *) tlexpr)->arg;
  
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
new file mode 100644
index 6cb6be5..29a7e75
*** a/src/backend/utils/adt/geo_ops.c
--- b/src/backend/utils/adt/geo_ops.c
*************** dist_ppoly(PG_FUNCTION_ARGS)
*** 2657,2662 ****
--- 2657,2674 ----
  	PG_RETURN_FLOAT8(result);
  }
  
+ Datum
+ dist_polyp(PG_FUNCTION_ARGS)
+ {
+ 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
+ 	Point	   *point = PG_GETARG_POINT_P(1);
+ 	float8		result;
+ 
+ 	result = dist_ppoly_internal(point, poly);
+ 
+ 	PG_RETURN_FLOAT8(result);
+ }
+ 
  static double
  dist_ppoly_internal(Point *pt, POLYGON *poly)
  {
*************** dist_pc(PG_FUNCTION_ARGS)
*** 5073,5078 ****
--- 5085,5105 ----
  	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);
+ }
  
  /*		circle_center	-		returns the center point of the circle.
   */
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/relscan.h b/src/include/access/relscan.h
new file mode 100644
index 9bb6362..e1f2031
*** a/src/include/access/relscan.h
--- b/src/include/access/relscan.h
*************** typedef struct IndexScanDescData
*** 91,96 ****
--- 91,105 ----
  	/* NB: if xs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
  	bool		xs_recheck;		/* T means scan keys must be rechecked */
  
+ 	/*
+ 	 * If fetching with an ordering operator, the "distance" of the last
+ 	 * returned heap tuple according to the index. If xs_recheck is true,
+ 	 * this needs to be rechecked just like the scan keys, and the value
+ 	 * returned here is a lower-bound on the actual distance.
+ 	 */
+ 	Datum	   *xs_distances;
+ 	bool	   *xs_distance_nulls;
+ 
  	/* state data for traversing HOT chains in index_getnext */
  	bool		xs_continue_hot;	/* T if must keep walking HOT chain */
  }	IndexScanDescData;
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..6e0df88
*** 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..5ecea7c
*** 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 = 2179 (  gist_point_con
*** 4086,4091 ****
--- 4088,4095 ----
  DESCR("GiST support");
  DATA(insert OID = 3064 (  gist_point_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_point_distance _null_ _null_ _null_ ));
  DESCR("GiST support");
+ DATA(insert OID = 3589 (  gist_bbox_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_bbox_distance _null_ _null_ _null_ ));
+ DESCR("GiST support");
  
  /* GIN */
  DATA(insert OID = 2731 (  gingetbitmap	   PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 20 "2281 2281" _null_ _null_ _null_ _null_	gingetbitmap _null_ _null_ _null_ ));
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
new file mode 100644
index 41288ed..cc05fae
*** a/src/include/nodes/execnodes.h
--- b/src/include/nodes/execnodes.h
***************
*** 17,22 ****
--- 17,23 ----
  #include "access/genam.h"
  #include "access/heapam.h"
  #include "executor/instrument.h"
+ #include "lib/pairingheap.h"
  #include "nodes/params.h"
  #include "nodes/plannodes.h"
  #include "utils/reltrigger.h"
*************** typedef struct
*** 1237,1242 ****
--- 1238,1244 ----
   *	 IndexScanState information
   *
   *		indexqualorig	   execution state for indexqualorig expressions
+  *		indexorderbyorig   execution state for indexorderbyorig expressions
   *		ScanKeys		   Skey structures for index quals
   *		NumScanKeys		   number of ScanKeys
   *		OrderByKeys		   Skey structures for index ordering operators
*************** typedef struct
*** 1247,1258 ****
--- 1249,1268 ----
   *		RuntimeContext	   expr context for evaling runtime Skeys
   *		RelationDesc	   index relation descriptor
   *		ScanDesc		   index scan descriptor
+  *
+  *		ReorderQueue	   queue of re-check tuples that need reordering
+  *		Distances		   re-checked distances of last fetched tuple
+  *		SortSupport		   for re-ordering ORDER BY exprs
+  *		ReachedEnd		   have we fetched all tuples from index already?
+  *		DistanceTypByVals  is the datatype of order by expression pass-by-value?
+  *		DistanceTypLens	   typlens of the datatypes of order by expressions
   * ----------------
   */
  typedef struct IndexScanState
  {
  	ScanState	ss;				/* its first field is NodeTag */
  	List	   *indexqualorig;
+ 	List	   *indexorderbyorig;
  	ScanKey		iss_ScanKeys;
  	int			iss_NumScanKeys;
  	ScanKey		iss_OrderByKeys;
*************** typedef struct IndexScanState
*** 1263,1268 ****
--- 1273,1287 ----
  	ExprContext *iss_RuntimeContext;
  	Relation	iss_RelationDesc;
  	IndexScanDesc iss_ScanDesc;
+ 
+ 	/* These are needed for re-checking ORDER BY expr ordering */
+ 	pairingheap *iss_ReorderQueue;
+ 	Datum	   *iss_Distances;
+ 	bool	   *iss_DistanceNulls;
+ 	SortSupport iss_SortSupport;
+ 	bool	   *iss_DistanceTypByVals;
+ 	int16	   *iss_DistanceTypLens;
+ 	bool		iss_ReachedEnd;
  } IndexScanState;
  
  /* ----------------
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
new file mode 100644
index f6683f0..2e34b59
*** a/src/include/nodes/plannodes.h
--- b/src/include/nodes/plannodes.h
*************** typedef Scan SeqScan;
*** 303,309 ****
   * index column order.  Only the expressions are provided, not the auxiliary
   * sort-order information from the ORDER BY SortGroupClauses; it's assumed
   * that the sort ordering is fully determinable from the top-level operators.
!  * indexorderbyorig is unused at run time, but is needed for EXPLAIN.
   * (Note these fields are used for amcanorderbyop cases, not amcanorder cases.)
   *
   * indexorderdir specifies the scan ordering, for indexscans on amcanorder
--- 303,313 ----
   * index column order.  Only the expressions are provided, not the auxiliary
   * sort-order information from the ORDER BY SortGroupClauses; it's assumed
   * that the sort ordering is fully determinable from the top-level operators.
!  * indexorderbyorig is used at run time to recheck the ordering, if the index
!  * does not calculate an accurate ordering. It is also needed for EXPLAIN.
!  *
!  * indexsortops is an array of operators used to sort the ORDER BY expressions,
!  * used together with indexorderbyorig to recheck ordering at run time.
   * (Note these fields are used for amcanorderbyop cases, not amcanorder cases.)
   *
   * indexorderdir specifies the scan ordering, for indexscans on amcanorder
*************** typedef struct IndexScan
*** 317,323 ****
  	List	   *indexqual;		/* list of index quals (usually OpExprs) */
  	List	   *indexqualorig;	/* the same in original form */
  	List	   *indexorderby;	/* list of index ORDER BY exprs */
! 	List	   *indexorderbyorig;		/* the same in original form */
  	ScanDirection indexorderdir;	/* forward or backward or don't care */
  } IndexScan;
  
--- 321,328 ----
  	List	   *indexqual;		/* list of index quals (usually OpExprs) */
  	List	   *indexqualorig;	/* the same in original form */
  	List	   *indexorderby;	/* list of index ORDER BY exprs */
! 	List	   *indexorderbyorig;	/* the same in original form */
! 	Oid		   *indexsortops;	/* OIDs of operators to sort ORDER BY exprs */
  	ScanDirection indexorderdir;	/* forward or backward or don't care */
  } IndexScan;
  
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
new file mode 100644
index 8da6c6c..b4e8252
*** 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_bbox_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;
