diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml
index 1998171..9203497 100644
--- a/doc/src/sgml/indices.sgml
+++ b/doc/src/sgml/indices.sgml
@@ -183,6 +183,24 @@ SELECT * FROM events ORDER BY event_date <-> date '2017-05-05' LIMIT 10;
 </programlisting>
    which finds the ten events closest to a given target date.  The ability
    to do this is again dependent on the particular operator class being used.
+   Built-in B-tree operator classes support distance ordering for the following
+   data types:
+   <simplelist>
+    <member><type>int2</type></member>
+    <member><type>int4</type></member>
+    <member><type>int8</type></member>
+    <member><type>float4</type></member>
+    <member><type>float8</type></member>
+    <member><type>numeric</type></member>
+    <member><type>timestamp with time zone</type></member>
+    <member><type>timestamp without time zone</type></member>
+    <member><type>time with time zone</type></member>
+    <member><type>time without time zone</type></member>
+    <member><type>date</type></member>
+    <member><type>interval</type></member>
+    <member><type>oid</type></member>
+    <member><type>money</type></member>
+   </simplelist>
   </para>
 
   <para>
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index c92e9d5..83073c4 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -30,6 +30,7 @@
 #include "utils/numeric.h"
 #include "utils/pg_locale.h"
 
+#define SAMESIGN(a,b)	(((a) < 0) == ((b) < 0))
 
 /*************************************************************************
  * Private routines
@@ -1157,3 +1158,22 @@ int8_cash(PG_FUNCTION_ARGS)
 
 	PG_RETURN_CASH(result);
 }
+
+Datum
+cash_distance(PG_FUNCTION_ARGS)
+{
+	Cash		a = PG_GETARG_CASH(0);
+	Cash		b = PG_GETARG_CASH(1);
+	Cash		r;
+	Cash		ra;
+
+	if (pg_sub_s64_overflow(a, b, &r) ||
+		r == PG_INT64_MIN)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("money out of range")));
+
+	ra = Abs(r);
+
+	PG_RETURN_CASH(ra);
+}
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index cf5a1c6..4492f69 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -563,6 +563,17 @@ date_mii(PG_FUNCTION_ARGS)
 	PG_RETURN_DATEADT(result);
 }
 
+Datum
+date_distance(PG_FUNCTION_ARGS)
+{
+	/* we assume the difference can't overflow */
+	Datum		diff = DirectFunctionCall2(date_mi,
+										   PG_GETARG_DATUM(0),
+										   PG_GETARG_DATUM(1));
+
+	PG_RETURN_INT32(Abs(DatumGetInt32(diff)));
+}
+
 /*
  * Internal routines for promoting date to timestamp and timestamp with
  * time zone
@@ -760,6 +771,29 @@ date_cmp_timestamp(PG_FUNCTION_ARGS)
 }
 
 Datum
+date_dist_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	if (DATE_NOT_FINITE(dateVal) || TIMESTAMP_NOT_FINITE(dt2))
+	{
+		Interval   *r = palloc(sizeof(Interval));
+
+		r->day = INT_MAX;
+		r->month = INT_MAX;
+		r->time = PG_INT64_MAX;
+
+		PG_RETURN_INTERVAL_P(r);
+	}
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_INTERVAL_P(timestamp_dist_internal(dt1, dt2));
+}
+
+Datum
 date_eq_timestamptz(PG_FUNCTION_ARGS)
 {
 	DateADT		dateVal = PG_GETARG_DATEADT(0);
@@ -844,6 +878,30 @@ date_cmp_timestamptz(PG_FUNCTION_ARGS)
 }
 
 Datum
+date_dist_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz dt1;
+
+	if (DATE_NOT_FINITE(dateVal) || TIMESTAMP_NOT_FINITE(dt2))
+	{
+		Interval   *r = palloc(sizeof(Interval));
+
+		r->day = INT_MAX;
+		r->month = INT_MAX;
+		r->time = PG_INT64_MAX;
+
+		PG_RETURN_INTERVAL_P(r);
+	}
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_INTERVAL_P(timestamptz_dist_internal(dt1, dt2));
+}
+
+
+Datum
 timestamp_eq_date(PG_FUNCTION_ARGS)
 {
 	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
@@ -928,6 +986,29 @@ timestamp_cmp_date(PG_FUNCTION_ARGS)
 }
 
 Datum
+timestamp_dist_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	if (DATE_NOT_FINITE(dateVal) || TIMESTAMP_NOT_FINITE(dt1))
+	{
+		Interval   *r = palloc(sizeof(Interval));
+
+		r->day = INT_MAX;
+		r->month = INT_MAX;
+		r->time = PG_INT64_MAX;
+
+		PG_RETURN_INTERVAL_P(r);
+	}
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_INTERVAL_P(timestamp_dist_internal(dt1, dt2));
+}
+
+Datum
 timestamptz_eq_date(PG_FUNCTION_ARGS)
 {
 	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
@@ -1039,6 +1120,28 @@ in_range_date_interval(PG_FUNCTION_ARGS)
 							   BoolGetDatum(less));
 }
 
+Datum
+timestamptz_dist_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz dt2;
+
+	if (DATE_NOT_FINITE(dateVal) || TIMESTAMP_NOT_FINITE(dt1))
+	{
+		Interval   *r = palloc(sizeof(Interval));
+
+		r->day = INT_MAX;
+		r->month = INT_MAX;
+		r->time = PG_INT64_MAX;
+
+		PG_RETURN_INTERVAL_P(r);
+	}
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_INTERVAL_P(timestamptz_dist_internal(dt1, dt2));
+}
 
 /* Add an interval to a date, giving a new date.
  * Must handle both positive and negative intervals.
@@ -1957,6 +2060,16 @@ time_part(PG_FUNCTION_ARGS)
 	PG_RETURN_FLOAT8(result);
 }
 
+Datum
+time_distance(PG_FUNCTION_ARGS)
+{
+	Datum		diff = DirectFunctionCall2(time_mi_time,
+										   PG_GETARG_DATUM(0),
+										   PG_GETARG_DATUM(1));
+
+	PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
+
 
 /*****************************************************************************
  *	 Time With Time Zone ADT
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 37c202d..d72fbef 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -3726,6 +3726,47 @@ width_bucket_float8(PG_FUNCTION_ARGS)
 	PG_RETURN_INT32(result);
 }
 
+Datum
+float4dist(PG_FUNCTION_ARGS)
+{
+	float4		a = PG_GETARG_FLOAT4(0);
+	float4		b = PG_GETARG_FLOAT4(1);
+	float4		r = float4_mi(a, b);
+
+	PG_RETURN_FLOAT4(Abs(r));
+}
+
+Datum
+float8dist(PG_FUNCTION_ARGS)
+{
+	float8		a = PG_GETARG_FLOAT8(0);
+	float8		b = PG_GETARG_FLOAT8(1);
+	float8		r = float8_mi(a, b);
+
+	PG_RETURN_FLOAT8(Abs(r));
+}
+
+
+Datum
+float48dist(PG_FUNCTION_ARGS)
+{
+	float4		a = PG_GETARG_FLOAT4(0);
+	float8		b = PG_GETARG_FLOAT8(1);
+	float8		r = float8_mi(a, b);
+
+	PG_RETURN_FLOAT8(Abs(r));
+}
+
+Datum
+float84dist(PG_FUNCTION_ARGS)
+{
+	float8		a = PG_GETARG_FLOAT8(0);
+	float4		b = PG_GETARG_FLOAT4(1);
+	float8		r = float8_mi(a, b);
+
+	PG_RETURN_FLOAT8(Abs(r));
+}
+
 /* ========== PRIVATE ROUTINES ========== */
 
 #ifndef HAVE_CBRT
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 04825fc..76e92ec 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -1501,3 +1501,54 @@ generate_series_int4_support(PG_FUNCTION_ARGS)
 
 	PG_RETURN_POINTER(ret);
 }
+
+Datum
+int2dist(PG_FUNCTION_ARGS)
+{
+	int16		a = PG_GETARG_INT16(0);
+	int16		b = PG_GETARG_INT16(1);
+	int16		r;
+	int16		ra;
+
+	if (pg_sub_s16_overflow(a, b, &r) ||
+		r == PG_INT16_MIN)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("smallint out of range")));
+
+	ra = Abs(r);
+
+	PG_RETURN_INT16(ra);
+}
+
+static int32
+int44_dist(int32 a, int32 b)
+{
+	int32		r;
+
+	if (pg_sub_s32_overflow(a, b, &r) ||
+		r == PG_INT32_MIN)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("integer out of range")));
+
+	return Abs(r);
+}
+
+Datum
+int4dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT32(int44_dist(PG_GETARG_INT32(0), PG_GETARG_INT32(1)));
+}
+
+Datum
+int24dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT32(int44_dist(PG_GETARG_INT16(0), PG_GETARG_INT32(1)));
+}
+
+Datum
+int42dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT32(int44_dist(PG_GETARG_INT32(0), PG_GETARG_INT16(1)));
+}
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 0ff9394..2ceb16b 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -1446,3 +1446,47 @@ generate_series_int8_support(PG_FUNCTION_ARGS)
 
 	PG_RETURN_POINTER(ret);
 }
+
+static int64
+int88_dist(int64 a, int64 b)
+{
+	int64		r;
+
+	if (pg_sub_s64_overflow(a, b, &r) ||
+		r == PG_INT64_MIN)
+		ereport(ERROR,
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+				 errmsg("bigint out of range")));
+
+	return Abs(r);
+}
+
+Datum
+int8dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(int88_dist(PG_GETARG_INT64(0), PG_GETARG_INT64(1)));
+}
+
+Datum
+int82dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(int88_dist(PG_GETARG_INT64(0), (int64) PG_GETARG_INT16(1)));
+}
+
+Datum
+int84dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(int88_dist(PG_GETARG_INT64(0), (int64) PG_GETARG_INT32(1)));
+}
+
+Datum
+int28dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(int88_dist((int64) PG_GETARG_INT16(0), PG_GETARG_INT64(1)));
+}
+
+Datum
+int48dist(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(int88_dist((int64) PG_GETARG_INT32(0), PG_GETARG_INT64(1)));
+}
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index bb67e01..b8f48d5 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -469,3 +469,17 @@ oidvectorgt(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(cmp > 0);
 }
+
+Datum
+oiddist(PG_FUNCTION_ARGS)
+{
+	Oid			a = PG_GETARG_OID(0);
+	Oid			b = PG_GETARG_OID(1);
+	Oid			res;
+
+	if (a < b)
+		res = b - a;
+	else
+		res = a - b;
+	PG_RETURN_OID(res);
+}
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index e0ef2f7..c5d1042 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -2694,6 +2694,86 @@ timestamp_mi(PG_FUNCTION_ARGS)
 	PG_RETURN_INTERVAL_P(result);
 }
 
+Datum
+timestamp_distance(PG_FUNCTION_ARGS)
+{
+	Timestamp	a = PG_GETARG_TIMESTAMP(0);
+	Timestamp	b = PG_GETARG_TIMESTAMP(1);
+	Interval   *r;
+
+	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+	{
+		Interval   *p = palloc(sizeof(Interval));
+
+		p->day = INT_MAX;
+		p->month = INT_MAX;
+		p->time = PG_INT64_MAX;
+		PG_RETURN_INTERVAL_P(p);
+	}
+	else
+		r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+												  PG_GETARG_DATUM(0),
+												  PG_GETARG_DATUM(1)));
+	PG_RETURN_INTERVAL_P(abs_interval(r));
+}
+
+Interval *
+timestamp_dist_internal(Timestamp a, Timestamp b)
+{
+	Interval   *r;
+
+	if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b))
+	{
+		r = palloc(sizeof(Interval));
+
+		r->day = INT_MAX;
+		r->month = INT_MAX;
+		r->time = PG_INT64_MAX;
+
+		return r;
+	}
+
+	r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi,
+											  TimestampGetDatum(a),
+											  TimestampGetDatum(b)));
+
+	return abs_interval(r);
+}
+
+Datum
+timestamptz_distance(PG_FUNCTION_ARGS)
+{
+	TimestampTz a = PG_GETARG_TIMESTAMPTZ(0);
+	TimestampTz b = PG_GETARG_TIMESTAMPTZ(1);
+
+	PG_RETURN_INTERVAL_P(timestamp_dist_internal(a, b));
+}
+
+Datum
+timestamp_dist_timestamptz(PG_FUNCTION_ARGS)
+{
+	Timestamp	ts1 = PG_GETARG_TIMESTAMP(0);
+	TimestampTz tstz2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz tstz1;
+
+	tstz1 = timestamp2timestamptz(ts1);
+
+	PG_RETURN_INTERVAL_P(timestamp_dist_internal(tstz1, tstz2));
+}
+
+Datum
+timestamptz_dist_timestamp(PG_FUNCTION_ARGS)
+{
+	TimestampTz tstz1 = PG_GETARG_TIMESTAMPTZ(0);
+	Timestamp	ts2 = PG_GETARG_TIMESTAMP(1);
+	TimestampTz tstz2;
+
+	tstz2 = timestamp2timestamptz(ts2);
+
+	PG_RETURN_INTERVAL_P(timestamp_dist_internal(tstz1, tstz2));
+}
+
+
 /*
  *	interval_justify_interval()
  *
@@ -3563,6 +3643,29 @@ interval_avg(PG_FUNCTION_ARGS)
 							   Float8GetDatum((double) N.time));
 }
 
+Interval *
+abs_interval(Interval *a)
+{
+	static Interval zero = {0, 0, 0};
+
+	if (DatumGetBool(DirectFunctionCall2(interval_lt,
+										 IntervalPGetDatum(a),
+										 IntervalPGetDatum(&zero))))
+		a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
+												  IntervalPGetDatum(a)));
+
+	return a;
+}
+
+Datum
+interval_distance(PG_FUNCTION_ARGS)
+{
+	Datum		diff = DirectFunctionCall2(interval_mi,
+										   PG_GETARG_DATUM(0),
+										   PG_GETARG_DATUM(1));
+
+	PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
 
 /* timestamp_age()
  * Calculate time difference while retaining year/month fields.
diff --git a/src/include/catalog/pg_amop.dat b/src/include/catalog/pg_amop.dat
index 0ab95d8..0e06b04 100644
--- a/src/include/catalog/pg_amop.dat
+++ b/src/include/catalog/pg_amop.dat
@@ -30,6 +30,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
   amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int2,int2)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+  amoprighttype => 'int2', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int2,int2)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators int24
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
@@ -47,6 +51,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
   amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int2,int4)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+  amoprighttype => 'int4', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int2,int4)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators int28
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
@@ -64,6 +72,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
   amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int2,int8)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int2',
+  amoprighttype => 'int8', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int2,int8)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # default operators int4
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
@@ -81,6 +93,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
   amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int4,int4)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+  amoprighttype => 'int4', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int4,int4)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators int42
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
@@ -98,6 +114,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
   amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int4,int2)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+  amoprighttype => 'int2', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int4,int2)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators int48
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
@@ -115,6 +135,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
   amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int4,int8)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int4',
+  amoprighttype => 'int8', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int4,int8)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # default operators int8
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
@@ -132,6 +156,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
   amoprighttype => 'int8', amopstrategy => '5', amopopr => '>(int8,int8)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+  amoprighttype => 'int8', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int8,int8)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators int82
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
@@ -149,6 +177,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
   amoprighttype => 'int2', amopstrategy => '5', amopopr => '>(int8,int2)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+  amoprighttype => 'int2', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int8,int2)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators int84
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
@@ -166,6 +198,10 @@
 { amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
   amoprighttype => 'int4', amopstrategy => '5', amopopr => '>(int8,int4)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/integer_ops', amoplefttype => 'int8',
+  amoprighttype => 'int4', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(int8,int4)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # btree oid_ops
 
@@ -179,6 +215,10 @@
   amopstrategy => '4', amopopr => '>=(oid,oid)', amopmethod => 'btree' },
 { amopfamily => 'btree/oid_ops', amoplefttype => 'oid', amoprighttype => 'oid',
   amopstrategy => '5', amopopr => '>(oid,oid)', amopmethod => 'btree' },
+{ amopfamily => 'btree/oid_ops', amoplefttype => 'oid',
+  amoprighttype => 'oid', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(oid,oid)', amopmethod => 'btree',
+  amopsortfamily => 'btree/oid_ops' },
 
 # btree tid_ops
 
@@ -229,6 +269,10 @@
 { amopfamily => 'btree/float_ops', amoplefttype => 'float4',
   amoprighttype => 'float4', amopstrategy => '5', amopopr => '>(float4,float4)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+  amoprighttype => 'float4', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(float4,float4)', amopmethod => 'btree',
+  amopsortfamily => 'btree/float_ops' },
 
 # crosstype operators float48
 { amopfamily => 'btree/float_ops', amoplefttype => 'float4',
@@ -246,6 +290,10 @@
 { amopfamily => 'btree/float_ops', amoplefttype => 'float4',
   amoprighttype => 'float8', amopstrategy => '5', amopopr => '>(float4,float8)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float4',
+  amoprighttype => 'float8', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(float4,float8)', amopmethod => 'btree',
+  amopsortfamily => 'btree/float_ops' },
 
 # default operators float8
 { amopfamily => 'btree/float_ops', amoplefttype => 'float8',
@@ -263,6 +311,10 @@
 { amopfamily => 'btree/float_ops', amoplefttype => 'float8',
   amoprighttype => 'float8', amopstrategy => '5', amopopr => '>(float8,float8)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+  amoprighttype => 'float8', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(float8,float8)', amopmethod => 'btree',
+  amopsortfamily => 'btree/float_ops' },
 
 # crosstype operators float84
 { amopfamily => 'btree/float_ops', amoplefttype => 'float8',
@@ -280,6 +332,10 @@
 { amopfamily => 'btree/float_ops', amoplefttype => 'float8',
   amoprighttype => 'float4', amopstrategy => '5', amopopr => '>(float8,float4)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/float_ops', amoplefttype => 'float8',
+  amoprighttype => 'float4', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(float8,float4)', amopmethod => 'btree',
+  amopsortfamily => 'btree/float_ops' },
 
 # btree char_ops
 
@@ -416,6 +472,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
   amoprighttype => 'date', amopstrategy => '5', amopopr => '>(date,date)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+  amoprighttype => 'date', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(date,date)', amopmethod => 'btree',
+  amopsortfamily => 'btree/integer_ops' },
 
 # crosstype operators vs timestamp
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
@@ -433,6 +493,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
   amoprighttype => 'timestamp', amopstrategy => '5',
   amopopr => '>(date,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+  amoprighttype => 'timestamp', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(date,timestamp)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # crosstype operators vs timestamptz
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
@@ -450,6 +514,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
   amoprighttype => 'timestamptz', amopstrategy => '5',
   amopopr => '>(date,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'date',
+  amoprighttype => 'timestamptz', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(date,timestamptz)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # default operators timestamp
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
@@ -467,6 +535,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
   amoprighttype => 'timestamp', amopstrategy => '5',
   amopopr => '>(timestamp,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+  amoprighttype => 'timestamp', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(timestamp,timestamp)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # crosstype operators vs date
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
@@ -484,6 +556,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
   amoprighttype => 'date', amopstrategy => '5', amopopr => '>(timestamp,date)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+  amoprighttype => 'date', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(timestamp,date)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # crosstype operators vs timestamptz
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
@@ -501,6 +577,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
   amoprighttype => 'timestamptz', amopstrategy => '5',
   amopopr => '>(timestamp,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamp',
+  amoprighttype => 'timestamptz', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(timestamp,timestamptz)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # default operators timestamptz
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
@@ -518,6 +598,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
   amoprighttype => 'timestamptz', amopstrategy => '5',
   amopopr => '>(timestamptz,timestamptz)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+  amoprighttype => 'timestamptz', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(timestamptz,timestamptz)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # crosstype operators vs date
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
@@ -535,6 +619,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
   amoprighttype => 'date', amopstrategy => '5',
   amopopr => '>(timestamptz,date)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+  amoprighttype => 'date', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(timestamptz,date)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # crosstype operators vs timestamp
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
@@ -552,6 +640,10 @@
 { amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
   amoprighttype => 'timestamp', amopstrategy => '5',
   amopopr => '>(timestamptz,timestamp)', amopmethod => 'btree' },
+{ amopfamily => 'btree/datetime_ops', amoplefttype => 'timestamptz',
+  amoprighttype => 'timestamp', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(timestamptz,timestamp)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # btree time_ops
 
@@ -570,6 +662,10 @@
 { amopfamily => 'btree/time_ops', amoplefttype => 'time',
   amoprighttype => 'time', amopstrategy => '5', amopopr => '>(time,time)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/time_ops', amoplefttype => 'time',
+  amoprighttype => 'time', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(time,time)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # btree timetz_ops
 
@@ -606,6 +702,10 @@
 { amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
   amoprighttype => 'interval', amopstrategy => '5',
   amopopr => '>(interval,interval)', amopmethod => 'btree' },
+{ amopfamily => 'btree/interval_ops', amoplefttype => 'interval',
+  amoprighttype => 'interval', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(interval,interval)', amopmethod => 'btree',
+  amopsortfamily => 'btree/interval_ops' },
 
 # btree macaddr
 
@@ -781,6 +881,10 @@
 { amopfamily => 'btree/money_ops', amoplefttype => 'money',
   amoprighttype => 'money', amopstrategy => '5', amopopr => '>(money,money)',
   amopmethod => 'btree' },
+{ amopfamily => 'btree/money_ops', amoplefttype => 'money',
+  amoprighttype => 'money', amopstrategy => '6', amoppurpose => 'o',
+  amopopr => '<->(money,money)', amopmethod => 'btree',
+  amopsortfamily => 'btree/money_ops' },
 
 # btree array_ops
 
diff --git a/src/include/catalog/pg_operator.dat b/src/include/catalog/pg_operator.dat
index 06aec07..914ca76 100644
--- a/src/include/catalog/pg_operator.dat
+++ b/src/include/catalog/pg_operator.dat
@@ -2851,6 +2851,114 @@
   oprname => '-', oprleft => 'pg_lsn', oprright => 'pg_lsn',
   oprresult => 'numeric', oprcode => 'pg_lsn_mi' },
 
+# distance operators
+{ oid => '4217', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int2',
+  oprright => 'int2', oprresult => 'int2', oprcom => '<->(int2,int2)',
+  oprcode => 'int2dist'},
+{ oid => '4218', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int4',
+  oprright => 'int4', oprresult => 'int4', oprcom => '<->(int4,int4)',
+  oprcode => 'int4dist'},
+{ oid => '4219', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int8',
+  oprright => 'int8', oprresult => 'int8', oprcom => '<->(int8,int8)',
+  oprcode => 'int8dist'},
+{ oid => '4220', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'oid',
+  oprright => 'oid', oprresult => 'oid', oprcom => '<->(oid,oid)',
+  oprcode => 'oiddist'},
+{ oid => '4221', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'float4',
+  oprright => 'float4', oprresult => 'float4', oprcom => '<->(float4,float4)',
+  oprcode => 'float4dist'},
+{ oid => '4222', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'float8',
+  oprright => 'float8', oprresult => 'float8', oprcom => '<->(float8,float8)',
+  oprcode => 'float8dist'},
+{ oid => '4223', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'money',
+  oprright => 'money', oprresult => 'money', oprcom => '<->(money,money)',
+  oprcode => 'cash_distance'},
+{ oid => '4224', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'date',
+  oprright => 'date', oprresult => 'int4', oprcom => '<->(date,date)',
+  oprcode => 'date_distance'},
+{ oid => '4225', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'time',
+  oprright => 'time', oprresult => 'interval', oprcom => '<->(time,time)',
+  oprcode => 'time_distance'},
+{ oid => '4226', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'timestamp',
+  oprright => 'timestamp', oprresult => 'interval', oprcom => '<->(timestamp,timestamp)',
+  oprcode => 'timestamp_distance'},
+{ oid => '4227', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'timestamptz',
+  oprright => 'timestamptz', oprresult => 'interval', oprcom => '<->(timestamptz,timestamptz)',
+  oprcode => 'timestamptz_distance'},
+{ oid => '4228', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'interval',
+  oprright => 'interval', oprresult => 'interval', oprcom => '<->(interval,interval)',
+  oprcode => 'interval_distance'},
+
+# cross-type distance operators
+{ oid => '4229', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int2',
+  oprright => 'int4', oprresult => 'int4', oprcom => '<->(int4,int2)',
+  oprcode => 'int24dist'},
+{ oid => '4230', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int4',
+  oprright => 'int2', oprresult => 'int4', oprcom => '<->(int2,int4)',
+  oprcode => 'int42dist'},
+{ oid => '4231', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int2',
+  oprright => 'int8', oprresult => 'int8', oprcom => '<->(int8,int2)',
+  oprcode => 'int28dist'},
+{ oid => '4232', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int8',
+  oprright => 'int2', oprresult => 'int8', oprcom => '<->(int2,int8)',
+  oprcode => 'int82dist'},
+{ oid => '4233', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int4',
+  oprright => 'int8', oprresult => 'int8', oprcom => '<->(int8,int4)',
+  oprcode => 'int48dist'},
+{ oid => '4234', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'int8',
+  oprright => 'int4', oprresult => 'int8', oprcom => '<->(int4,int8)',
+  oprcode => 'int84dist'},
+{ oid => '4235', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'float4',
+  oprright => 'float8', oprresult => 'float8', oprcom => '<->(float8,float4)',
+  oprcode => 'float48dist'},
+{ oid => '4236', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'float8',
+  oprright => 'float4', oprresult => 'float8', oprcom => '<->(float4,float8)',
+  oprcode => 'float84dist'},
+{ oid => '4237', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'date',
+  oprright => 'timestamp', oprresult => 'interval', oprcom => '<->(timestamp,date)',
+  oprcode => 'date_dist_timestamp'},
+{ oid => '4238', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'timestamp',
+  oprright => 'date', oprresult => 'interval', oprcom => '<->(date,timestamp)',
+  oprcode => 'timestamp_dist_date'},
+{ oid => '4239', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'date',
+  oprright => 'timestamptz', oprresult => 'interval', oprcom => '<->(timestamptz,date)',
+  oprcode => 'date_dist_timestamptz'},
+{ oid => '4240', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'timestamptz',
+  oprright => 'date', oprresult => 'interval', oprcom => '<->(date,timestamptz)',
+  oprcode => 'timestamptz_dist_date'},
+{ oid => '4241', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'timestamp',
+  oprright => 'timestamptz', oprresult => 'interval', oprcom => '<->(timestamptz,timestamp)',
+  oprcode => 'timestamp_dist_timestamptz'},
+{ oid => '4242', descr => 'distance between',
+  oprname => '<->', oprcanmerge => 'f', oprcanhash => 'f', oprleft => 'timestamptz',
+  oprright => 'timestamp', oprresult => 'interval', oprcom => '<->(timestamp,timestamptz)',
+  oprcode => 'timestamptz_dist_timestamp'},
+
 # enum operators
 { oid => '3516', descr => 'equal',
   oprname => '=', oprcanmerge => 't', oprcanhash => 't', oprleft => 'anyenum',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index a4e173b..96d5db0 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -10534,4 +10534,90 @@
   proname => 'pg_partition_root', prorettype => 'regclass',
   proargtypes => 'regclass', prosrc => 'pg_partition_root' },
 
+# distance functions
+{ oid => '4243',
+  proname => 'int2dist', prorettype => 'int2',
+  proargtypes => 'int2 int2', prosrc => 'int2dist' },
+{ oid => '4244',
+  proname => 'int4dist', prorettype => 'int4',
+  proargtypes => 'int4 int4', prosrc => 'int4dist' },
+{ oid => '4245',
+  proname => 'int8dist', prorettype => 'int8',
+  proargtypes => 'int8 int8', prosrc => 'int8dist' },
+{ oid => '4246',
+  proname => 'oiddist', proleakproof => 't', prorettype => 'oid',
+  proargtypes => 'oid oid', prosrc => 'oiddist' },
+{ oid => '4247',
+  proname => 'float4dist', prorettype => 'float4',
+  proargtypes => 'float4 float4', prosrc => 'float4dist' },
+{ oid => '4248',
+  proname => 'float8dist', prorettype => 'float8',
+  proargtypes => 'float8 float8', prosrc => 'float8dist' },
+{ oid => '4249',
+  proname => 'cash_distance', prorettype => 'money',
+  proargtypes => 'money money', prosrc => 'cash_distance' },
+{ oid => '4250',
+  proname => 'date_distance', prorettype => 'int4',
+  proargtypes => 'date date', prosrc => 'date_distance' },
+{ oid => '4251',
+  proname => 'time_distance', prorettype => 'interval',
+  proargtypes => 'time time', prosrc => 'time_distance' },
+{ oid => '4252',
+  proname => 'timestamp_distance', prorettype => 'interval',
+  proargtypes => 'timestamp timestamp', prosrc => 'timestamp_distance' },
+{ oid => '4253',
+  proname => 'timestamptz_distance', prorettype => 'interval',
+  proargtypes => 'timestamptz timestamptz', prosrc => 'timestamptz_distance' },
+{ oid => '4254',
+  proname => 'interval_distance', prorettype => 'interval',
+  proargtypes => 'interval interval', prosrc => 'interval_distance' },
+
+# cross-type distance functions
+{ oid => '4255',
+  proname => 'int24dist', prorettype => 'int4',
+  proargtypes => 'int2 int4', prosrc => 'int24dist' },
+{ oid => '4256',
+  proname => 'int28dist', prorettype => 'int8',
+  proargtypes => 'int2 int8', prosrc => 'int28dist' },
+{ oid => '4257',
+  proname => 'int42dist', prorettype => 'int4',
+  proargtypes => 'int4 int2', prosrc => 'int42dist' },
+{ oid => '4258',
+  proname => 'int48dist', prorettype => 'int8',
+  proargtypes => 'int4 int8', prosrc => 'int48dist' },
+{ oid => '4259',
+  proname => 'int82dist', prorettype => 'int8',
+  proargtypes => 'int8 int2', prosrc => 'int82dist' },
+{ oid => '4260',
+  proname => 'int84dist', prorettype => 'int8',
+  proargtypes => 'int8 int4', prosrc => 'int84dist' },
+{ oid => '4261',
+  proname => 'float48dist', prorettype => 'float8',
+  proargtypes => 'float4 float8', prosrc => 'float48dist' },
+{ oid => '4262',
+  proname => 'float84dist', prorettype => 'float8',
+  proargtypes => 'float8 float4', prosrc => 'float84dist' },
+{ oid => '4263',
+  proname => 'date_dist_timestamp', prorettype => 'interval',
+  proargtypes => 'date timestamp', prosrc => 'date_dist_timestamp' },
+{ oid => '4264',
+  proname => 'date_dist_timestamptz', provolatile => 's',
+  prorettype => 'interval', proargtypes => 'date timestamptz',
+  prosrc => 'date_dist_timestamptz' },
+{ oid => '4265',
+  proname => 'timestamp_dist_date', prorettype => 'interval',
+  proargtypes => 'timestamp date', prosrc => 'timestamp_dist_date' },
+{ oid => '4266',
+  proname => 'timestamp_dist_timestamptz', provolatile => 's',
+  prorettype => 'interval', proargtypes => 'timestamp timestamptz',
+  prosrc => 'timestamp_dist_timestamptz' },
+{ oid => '4267',
+  proname => 'timestamptz_dist_date', provolatile => 's',
+  prorettype => 'interval', proargtypes => 'timestamptz date',
+  prosrc => 'timestamptz_dist_date' },
+{ oid => '4268',
+  proname => 'timestamptz_dist_timestamp', provolatile => 's',
+  prorettype => 'interval', proargtypes => 'timestamptz timestamp',
+  prosrc => 'timestamptz_dist_timestamp' },
+
 ]
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index 87f819e..01d2284 100644
--- a/src/include/utils/datetime.h
+++ b/src/include/utils/datetime.h
@@ -338,4 +338,6 @@ extern TimeZoneAbbrevTable *ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs,
 					   int n);
 extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);
 
+extern Interval *abs_interval(Interval *a);
+
 #endif							/* DATETIME_H */
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index aeb89dc..438a5eb 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -93,9 +93,11 @@ extern Timestamp SetEpochTimestamp(void);
 extern void GetEpochTime(struct pg_tm *tm);
 
 extern int	timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
+extern Interval *timestamp_dist_internal(Timestamp a, Timestamp b);
 
-/* timestamp comparison works for timestamptz also */
+/* timestamp comparison and distance works for timestamptz also */
 #define timestamptz_cmp_internal(dt1,dt2)	timestamp_cmp_internal(dt1, dt2)
+#define timestamptz_dist_internal(dt1,dt2)	timestamp_dist_internal(dt1, dt2)
 
 extern int	isoweek2j(int year, int week);
 extern void isoweek2date(int woy, int *year, int *mon, int *mday);
diff --git a/src/test/regress/expected/amutils.out b/src/test/regress/expected/amutils.out
index 4570a39..630dc6b 100644
--- a/src/test/regress/expected/amutils.out
+++ b/src/test/regress/expected/amutils.out
@@ -24,7 +24,7 @@ select prop,
  nulls_first        |    |       | f
  nulls_last         |    |       | t
  orderable          |    |       | t
- distance_orderable |    |       | f
+ distance_orderable |    |       | t
  returnable         |    |       | t
  search_array       |    |       | t
  search_nulls       |    |       | t
@@ -100,7 +100,7 @@ select prop,
  nulls_first        | f     | f    | f    | f            | f           | f   | f
  nulls_last         | t     | f    | f    | f            | f           | f   | f
  orderable          | t     | f    | f    | f            | f           | f   | f
- distance_orderable | f     | f    | t    | f            | t           | f   | f
+ distance_orderable | t     | f    | t    | f            | t           | f   | f
  returnable         | t     | f    | f    | t            | t           | f   | f
  search_array       | t     | f    | f    | f            | f           | f   | f
  search_nulls       | t     | f    | t    | t            | t           | f   | t
@@ -231,7 +231,7 @@ select col, prop, pg_index_column_has_property(o, col, prop)
    1 | desc               | f
    1 | nulls_first        | f
    1 | nulls_last         | t
-   1 | distance_orderable | f
+   1 | distance_orderable | t
    1 | returnable         | t
    1 | bogus              | 
    2 | orderable          | f
diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out
index 1bcc946..b9b819c 100644
--- a/src/test/regress/expected/date.out
+++ b/src/test/regress/expected/date.out
@@ -1477,3 +1477,64 @@ select make_time(10, 55, 100.1);
 ERROR:  time field value out of range: 10:55:100.1
 select make_time(24, 0, 2.1);
 ERROR:  time field value out of range: 24:00:2.1
+-- distance operators
+SELECT '' AS "Fifteen", f1 <-> date '2001-02-03' AS "Distance" FROM DATE_TBL;
+ Fifteen | Distance 
+---------+----------
+         |    16006
+         |    15941
+         |     1802
+         |     1801
+         |     1800
+         |     1799
+         |     1436
+         |     1435
+         |     1434
+         |      308
+         |      307
+         |      306
+         |    13578
+         |    13944
+         |    14311
+(15 rows)
+
+SELECT '' AS "Fifteen", f1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM DATE_TBL;
+ Fifteen |               Distance                
+---------+---------------------------------------
+         | @ 16006 days 1 hour 23 mins 45 secs
+         | @ 15941 days 1 hour 23 mins 45 secs
+         | @ 1802 days 1 hour 23 mins 45 secs
+         | @ 1801 days 1 hour 23 mins 45 secs
+         | @ 1800 days 1 hour 23 mins 45 secs
+         | @ 1799 days 1 hour 23 mins 45 secs
+         | @ 1436 days 1 hour 23 mins 45 secs
+         | @ 1435 days 1 hour 23 mins 45 secs
+         | @ 1434 days 1 hour 23 mins 45 secs
+         | @ 308 days 1 hour 23 mins 45 secs
+         | @ 307 days 1 hour 23 mins 45 secs
+         | @ 306 days 1 hour 23 mins 45 secs
+         | @ 13577 days 22 hours 36 mins 15 secs
+         | @ 13943 days 22 hours 36 mins 15 secs
+         | @ 14310 days 22 hours 36 mins 15 secs
+(15 rows)
+
+SELECT '' AS "Fifteen", f1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM DATE_TBL;
+ Fifteen |               Distance                
+---------+---------------------------------------
+         | @ 16005 days 14 hours 23 mins 45 secs
+         | @ 15940 days 14 hours 23 mins 45 secs
+         | @ 1801 days 14 hours 23 mins 45 secs
+         | @ 1800 days 14 hours 23 mins 45 secs
+         | @ 1799 days 14 hours 23 mins 45 secs
+         | @ 1798 days 14 hours 23 mins 45 secs
+         | @ 1435 days 14 hours 23 mins 45 secs
+         | @ 1434 days 14 hours 23 mins 45 secs
+         | @ 1433 days 14 hours 23 mins 45 secs
+         | @ 307 days 14 hours 23 mins 45 secs
+         | @ 306 days 14 hours 23 mins 45 secs
+         | @ 305 days 15 hours 23 mins 45 secs
+         | @ 13578 days 8 hours 36 mins 15 secs
+         | @ 13944 days 8 hours 36 mins 15 secs
+         | @ 14311 days 8 hours 36 mins 15 secs
+(15 rows)
+
diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out
index cf78277..ce29924e 100644
--- a/src/test/regress/expected/float4.out
+++ b/src/test/regress/expected/float4.out
@@ -273,6 +273,26 @@ SELECT '' AS five, * FROM FLOAT4_TBL;
       | -1.2345679e-20
 (5 rows)
 
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3' AS dist FROM FLOAT4_TBL f;
+ five |       f1       |     dist      
+------+----------------+---------------
+      |              0 |        1004.3
+      |         -34.84 |       1039.14
+      |        -1004.3 |        2008.6
+      | -1.2345679e+20 | 1.2345679e+20
+      | -1.2345679e-20 |        1004.3
+(5 rows)
+
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3'::float8 AS dist FROM FLOAT4_TBL f;
+ five |       f1       |          dist          
+------+----------------+------------------------
+      |              0 |                 1004.3
+      |         -34.84 |     1039.1400001525878
+      |        -1004.3 |     2008.5999877929687
+      | -1.2345679e+20 | 1.2345678955701443e+20
+      | -1.2345679e-20 |                 1004.3
+(5 rows)
+
 -- test edge-case coercions to integer
 SELECT '32767.4'::float4::int2;
  int2  
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index c3a6f53..5485c19 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -413,6 +413,27 @@ SELECT '' AS five, f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f;
       | 1.2345678901234e-200 |  2.3112042409018e-67
 (5 rows)
 
+-- distance
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3'::float8 AS dist FROM FLOAT8_TBL f;
+ five |          f1          |         dist         
+------+----------------------+----------------------
+      |                    0 |               1004.3
+      |               1004.3 |                    0
+      |               -34.84 |              1039.14
+      | 1.2345678901234e+200 | 1.2345678901234e+200
+      | 1.2345678901234e-200 |               1004.3
+(5 rows)
+
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3'::float4 AS dist FROM FLOAT8_TBL f;
+ five |          f1          |         dist         
+------+----------------------+----------------------
+      |                    0 |     1004.29998779297
+      |               1004.3 | 1.22070312045253e-05
+      |               -34.84 |     1039.13998779297
+      | 1.2345678901234e+200 | 1.2345678901234e+200
+      | 1.2345678901234e-200 |     1004.29998779297
+(5 rows)
+
 SELECT '' AS five, * FROM FLOAT8_TBL;
  five |          f1          
 ------+----------------------
diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out
index 8c255b9..0edc57e 100644
--- a/src/test/regress/expected/int2.out
+++ b/src/test/regress/expected/int2.out
@@ -242,6 +242,39 @@ SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT2_TBL i;
       | -32767 | -16383
 (5 rows)
 
+-- distance
+SELECT '' AS five, i.f1, i.f1 <-> int2 '2' AS x FROM INT2_TBL i;
+ERROR:  smallint out of range
+SELECT '' AS four, i.f1, i.f1 <-> int2 '2' AS x FROM INT2_TBL i
+WHERE f1 > -32767;
+ four |  f1   |   x   
+------+-------+-------
+      |     0 |     2
+      |  1234 |  1232
+      | -1234 |  1236
+      | 32767 | 32765
+(4 rows)
+
+SELECT '' AS five, i.f1, i.f1 <-> int4 '2' AS x FROM INT2_TBL i;
+ five |   f1   |   x   
+------+--------+-------
+      |      0 |     2
+      |   1234 |  1232
+      |  -1234 |  1236
+      |  32767 | 32765
+      | -32767 | 32769
+(5 rows)
+
+SELECT '' AS five, i.f1, i.f1 <-> int8 '2' AS x FROM INT2_TBL i;
+ five |   f1   |   x   
+------+--------+-------
+      |      0 |     2
+      |   1234 |  1232
+      |  -1234 |  1236
+      |  32767 | 32765
+      | -32767 | 32769
+(5 rows)
+
 -- corner cases
 SELECT (-1::int2<<15)::text;
   text  
diff --git a/src/test/regress/expected/int4.out b/src/test/regress/expected/int4.out
index bda7a8d..3735dbc 100644
--- a/src/test/regress/expected/int4.out
+++ b/src/test/regress/expected/int4.out
@@ -247,6 +247,38 @@ SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i;
       | -2147483647 | -1073741823
 (5 rows)
 
+SELECT '' AS five, i.f1, i.f1 <-> int2 '2' AS x FROM INT4_TBL i;
+ERROR:  integer out of range
+SELECT '' AS four, i.f1, i.f1 <-> int2 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+ four |     f1     |     x      
+------+------------+------------
+      |          0 |          2
+      |     123456 |     123454
+      |    -123456 |     123458
+      | 2147483647 | 2147483645
+(4 rows)
+
+SELECT '' AS four, i.f1, i.f1 <-> int4 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+ four |     f1     |     x      
+------+------------+------------
+      |          0 |          2
+      |     123456 |     123454
+      |    -123456 |     123458
+      | 2147483647 | 2147483645
+(4 rows)
+
+SELECT '' AS five, i.f1, i.f1 <-> int8 '2' AS x FROM INT4_TBL i;
+ five |     f1      |     x      
+------+-------------+------------
+      |           0 |          2
+      |      123456 |     123454
+      |     -123456 |     123458
+      |  2147483647 | 2147483645
+      | -2147483647 | 2147483649
+(5 rows)
+
 --
 -- more complex expressions
 --
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index 8447a28..d56886a 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -432,6 +432,37 @@ SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 A
  4567890123457035 | -4567890123456543 | 1123700970370370094 |     0
 (5 rows)
 
+-- distance
+SELECT '' AS five, q2, q2 <-> int2 '123' AS dist FROM INT8_TBL i;
+ five |        q2         |       dist       
+------+-------------------+------------------
+      |               456 |              333
+      |  4567890123456789 | 4567890123456666
+      |               123 |                0
+      |  4567890123456789 | 4567890123456666
+      | -4567890123456789 | 4567890123456912
+(5 rows)
+
+SELECT '' AS five, q2, q2 <-> int4 '123' AS dist FROM INT8_TBL i;
+ five |        q2         |       dist       
+------+-------------------+------------------
+      |               456 |              333
+      |  4567890123456789 | 4567890123456666
+      |               123 |                0
+      |  4567890123456789 | 4567890123456666
+      | -4567890123456789 | 4567890123456912
+(5 rows)
+
+SELECT '' AS five, q2, q2 <-> int8 '123' AS dist FROM INT8_TBL i;
+ five |        q2         |       dist       
+------+-------------------+------------------
+      |               456 |              333
+      |  4567890123456789 | 4567890123456666
+      |               123 |                0
+      |  4567890123456789 | 4567890123456666
+      | -4567890123456789 | 4567890123456912
+(5 rows)
+
 SELECT q2, abs(q2) FROM INT8_TBL;
         q2         |       abs        
 -------------------+------------------
diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out
index f88f345..cb95adf 100644
--- a/src/test/regress/expected/interval.out
+++ b/src/test/regress/expected/interval.out
@@ -207,6 +207,21 @@ SELECT '' AS fortyfive, r1.*, r2.*
            | 34 years        | 6 years
 (45 rows)
 
+SELECT '' AS ten, f1 <-> interval '@ 2 day 3 hours' FROM INTERVAL_TBL;
+ ten |          ?column?          
+-----+----------------------------
+     | 2 days 02:59:00
+     | 2 days -02:00:00
+     | 8 days -03:00:00
+     | 34 years -2 days -03:00:00
+     | 3 mons -2 days -03:00:00
+     | 2 days 03:00:14
+     | 1 day 00:56:56
+     | 6 years -2 days -03:00:00
+     | 5 mons -2 days -03:00:00
+     | 5 mons -2 days +09:00:00
+(10 rows)
+
 -- Test intervals that are large enough to overflow 64 bits in comparisons
 CREATE TEMP TABLE INTERVAL_TBL_OF (f1 interval);
 INSERT INTO INTERVAL_TBL_OF (f1) VALUES
diff --git a/src/test/regress/expected/money.out b/src/test/regress/expected/money.out
index ab86595..fb2a489 100644
--- a/src/test/regress/expected/money.out
+++ b/src/test/regress/expected/money.out
@@ -123,6 +123,12 @@ SELECT m / 2::float4 FROM money_data;
    $61.50
 (1 row)
 
+SELECT m <-> '$123.45' FROM money_data;
+ ?column? 
+----------
+    $0.45
+(1 row)
+
 -- All true
 SELECT m = '$123.00' FROM money_data;
  ?column? 
diff --git a/src/test/regress/expected/oid.out b/src/test/regress/expected/oid.out
index 1eab9cc..5339a48 100644
--- a/src/test/regress/expected/oid.out
+++ b/src/test/regress/expected/oid.out
@@ -119,4 +119,17 @@ SELECT '' AS three, o.* FROM OID_TBL o WHERE o.f1 > '1234';
        |   99999999
 (3 rows)
 
+SELECT '' AS eight, f1, f1 <-> oid '123' FROM OID_TBL;
+ eight |     f1     |  ?column?  
+-------+------------+------------
+       |       1234 |       1111
+       |       1235 |       1112
+       |        987 |        864
+       | 4294966256 | 4294966133
+       |   99999999 |   99999876
+       |          5 |        118
+       |         10 |        113
+       |         15 |        108
+(8 rows)
+
 DROP TABLE OID_TBL;
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index ce25ee0..e637420 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -750,6 +750,7 @@ macaddr8_gt(macaddr8,macaddr8)
 macaddr8_ge(macaddr8,macaddr8)
 macaddr8_ne(macaddr8,macaddr8)
 macaddr8_cmp(macaddr8,macaddr8)
+oiddist(oid,oid)
 -- restore normal output mode
 \a\t
 -- List of functions used by libpq's fe-lobj.c
@@ -1332,7 +1333,7 @@ WHERE pp.oid = ap.amproc AND po.oid = o.oprcode AND o.oid = ao.amopopr AND
     ao.amoprighttype = ap.amprocrighttype AND
     ap.amprocnum = 1 AND
     (pp.provolatile != po.provolatile OR
-     pp.proleakproof != po.proleakproof)
+     (NOT pp.proleakproof AND po.proleakproof))
 ORDER BY 1;
                    proc                    | vp | lp |              opr              | vo | lo 
 -------------------------------------------+----+----+-------------------------------+----+----
@@ -1862,6 +1863,7 @@ ORDER BY 1, 2, 3;
         403 |            5 | *>
         403 |            5 | >
         403 |            5 | ~>~
+        403 |            6 | <->
         405 |            1 | =
         783 |            1 | <<
         783 |            1 | @@
@@ -1971,7 +1973,7 @@ ORDER BY 1, 2, 3;
        4000 |           26 | >>
        4000 |           27 | >>=
        4000 |           28 | ^@
-(123 rows)
+(124 rows)
 
 -- Check that all opclass search operators have selectivity estimators.
 -- This is not absolutely required, but it seems a reasonable thing
diff --git a/src/test/regress/expected/time.out b/src/test/regress/expected/time.out
index 8e0afe6..ee74faa 100644
--- a/src/test/regress/expected/time.out
+++ b/src/test/regress/expected/time.out
@@ -86,3 +86,19 @@ ERROR:  operator is not unique: time without time zone + time without time zone
 LINE 1: SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL;
                   ^
 HINT:  Could not choose a best candidate operator. You might need to add explicit type casts.
+-- distance
+SELECT f1 AS "Ten", f1 <-> time '01:23:45' AS "Distance" FROM TIME_TBL;
+     Ten     |           Distance            
+-------------+-------------------------------
+ 00:00:00    | @ 1 hour 23 mins 45 secs
+ 01:00:00    | @ 23 mins 45 secs
+ 02:03:00    | @ 39 mins 15 secs
+ 11:59:00    | @ 10 hours 35 mins 15 secs
+ 12:00:00    | @ 10 hours 36 mins 15 secs
+ 12:01:00    | @ 10 hours 37 mins 15 secs
+ 23:59:00    | @ 22 hours 35 mins 15 secs
+ 23:59:59.99 | @ 22 hours 36 mins 14.99 secs
+ 15:36:39    | @ 14 hours 12 mins 54 secs
+ 15:36:39    | @ 14 hours 12 mins 54 secs
+(10 rows)
+
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index 4a2fabd..dcb4205 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -1604,3 +1604,214 @@ SELECT make_timestamp(2014,12,28,6,30,45.887);
  Sun Dec 28 06:30:45.887 2014
 (1 row)
 
+-- distance operators
+SELECT '' AS  "0", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMP_TBL;
+ERROR:  interval out of range
+SELECT '' AS "63", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMP_TBL WHERE isfinite(d1);
+ 63 |               Distance                
+----+---------------------------------------
+    | @ 11356 days
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 58 secs
+    | @ 1453 days 6 hours 27 mins 58.6 secs
+    | @ 1453 days 6 hours 27 mins 58.5 secs
+    | @ 1453 days 6 hours 27 mins 58.4 secs
+    | @ 1493 days
+    | @ 1492 days 20 hours 55 mins 55 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1333 days 6 hours 27 mins 59 secs
+    | @ 231 days 18 hours 19 mins 20 secs
+    | @ 324 days 15 hours 45 mins 59 secs
+    | @ 324 days 10 hours 45 mins 58 secs
+    | @ 324 days 11 hours 45 mins 57 secs
+    | @ 324 days 20 hours 45 mins 56 secs
+    | @ 324 days 21 hours 45 mins 55 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 28 mins
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1333 days 5 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1452 days 6 hours 27 mins 59 secs
+    | @ 1451 days 6 hours 27 mins 59 secs
+    | @ 1450 days 6 hours 27 mins 59 secs
+    | @ 1449 days 6 hours 27 mins 59 secs
+    | @ 1448 days 6 hours 27 mins 59 secs
+    | @ 1447 days 6 hours 27 mins 59 secs
+    | @ 765901 days 6 hours 27 mins 59 secs
+    | @ 695407 days 6 hours 27 mins 59 secs
+    | @ 512786 days 6 hours 27 mins 59 secs
+    | @ 330165 days 6 hours 27 mins 59 secs
+    | @ 111019 days 6 hours 27 mins 59 secs
+    | @ 74495 days 6 hours 27 mins 59 secs
+    | @ 37971 days 6 hours 27 mins 59 secs
+    | @ 1447 days 6 hours 27 mins 59 secs
+    | @ 35077 days 17 hours 32 mins 1 sec
+    | @ 1801 days 6 hours 27 mins 59 secs
+    | @ 1800 days 6 hours 27 mins 59 secs
+    | @ 1799 days 6 hours 27 mins 59 secs
+    | @ 1495 days 6 hours 27 mins 59 secs
+    | @ 1494 days 6 hours 27 mins 59 secs
+    | @ 1493 days 6 hours 27 mins 59 secs
+    | @ 1435 days 6 hours 27 mins 59 secs
+    | @ 1434 days 6 hours 27 mins 59 secs
+    | @ 1130 days 6 hours 27 mins 59 secs
+    | @ 1129 days 6 hours 27 mins 59 secs
+    | @ 399 days 6 hours 27 mins 59 secs
+    | @ 398 days 6 hours 27 mins 59 secs
+    | @ 33 days 6 hours 27 mins 59 secs
+    | @ 32 days 6 hours 27 mins 59 secs
+(63 rows)
+
+SELECT '' AS  "0", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMP_TBL;
+ERROR:  interval out of range
+SELECT '' AS "63", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMP_TBL WHERE isfinite(d1);
+ 63 |               Distance                
+----+---------------------------------------
+    | @ 11356 days 1 hour 23 mins 45 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 43 secs
+    | @ 1453 days 7 hours 51 mins 43.6 secs
+    | @ 1453 days 7 hours 51 mins 43.5 secs
+    | @ 1453 days 7 hours 51 mins 43.4 secs
+    | @ 1493 days 1 hour 23 mins 45 secs
+    | @ 1492 days 22 hours 19 mins 40 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1333 days 7 hours 51 mins 44 secs
+    | @ 231 days 16 hours 55 mins 35 secs
+    | @ 324 days 17 hours 9 mins 44 secs
+    | @ 324 days 12 hours 9 mins 43 secs
+    | @ 324 days 13 hours 9 mins 42 secs
+    | @ 324 days 22 hours 9 mins 41 secs
+    | @ 324 days 23 hours 9 mins 40 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 45 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1333 days 6 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1452 days 7 hours 51 mins 44 secs
+    | @ 1451 days 7 hours 51 mins 44 secs
+    | @ 1450 days 7 hours 51 mins 44 secs
+    | @ 1449 days 7 hours 51 mins 44 secs
+    | @ 1448 days 7 hours 51 mins 44 secs
+    | @ 1447 days 7 hours 51 mins 44 secs
+    | @ 765901 days 7 hours 51 mins 44 secs
+    | @ 695407 days 7 hours 51 mins 44 secs
+    | @ 512786 days 7 hours 51 mins 44 secs
+    | @ 330165 days 7 hours 51 mins 44 secs
+    | @ 111019 days 7 hours 51 mins 44 secs
+    | @ 74495 days 7 hours 51 mins 44 secs
+    | @ 37971 days 7 hours 51 mins 44 secs
+    | @ 1447 days 7 hours 51 mins 44 secs
+    | @ 35077 days 16 hours 8 mins 16 secs
+    | @ 1801 days 7 hours 51 mins 44 secs
+    | @ 1800 days 7 hours 51 mins 44 secs
+    | @ 1799 days 7 hours 51 mins 44 secs
+    | @ 1495 days 7 hours 51 mins 44 secs
+    | @ 1494 days 7 hours 51 mins 44 secs
+    | @ 1493 days 7 hours 51 mins 44 secs
+    | @ 1435 days 7 hours 51 mins 44 secs
+    | @ 1434 days 7 hours 51 mins 44 secs
+    | @ 1130 days 7 hours 51 mins 44 secs
+    | @ 1129 days 7 hours 51 mins 44 secs
+    | @ 399 days 7 hours 51 mins 44 secs
+    | @ 398 days 7 hours 51 mins 44 secs
+    | @ 33 days 7 hours 51 mins 44 secs
+    | @ 32 days 7 hours 51 mins 44 secs
+(63 rows)
+
+SELECT '' AS  "0", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMP_TBL;
+ERROR:  interval out of range
+SELECT '' AS "63", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMP_TBL WHERE isfinite(d1);
+ 63 |                Distance                
+----+----------------------------------------
+    | @ 11355 days 14 hours 23 mins 45 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 43 secs
+    | @ 1452 days 20 hours 51 mins 43.6 secs
+    | @ 1452 days 20 hours 51 mins 43.5 secs
+    | @ 1452 days 20 hours 51 mins 43.4 secs
+    | @ 1492 days 14 hours 23 mins 45 secs
+    | @ 1492 days 11 hours 19 mins 40 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1332 days 21 hours 51 mins 44 secs
+    | @ 232 days 2 hours 55 mins 35 secs
+    | @ 324 days 6 hours 9 mins 44 secs
+    | @ 324 days 1 hour 9 mins 43 secs
+    | @ 324 days 2 hours 9 mins 42 secs
+    | @ 324 days 11 hours 9 mins 41 secs
+    | @ 324 days 12 hours 9 mins 40 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 45 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1332 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1451 days 20 hours 51 mins 44 secs
+    | @ 1450 days 20 hours 51 mins 44 secs
+    | @ 1449 days 20 hours 51 mins 44 secs
+    | @ 1448 days 20 hours 51 mins 44 secs
+    | @ 1447 days 20 hours 51 mins 44 secs
+    | @ 1446 days 20 hours 51 mins 44 secs
+    | @ 765900 days 20 hours 51 mins 44 secs
+    | @ 695406 days 20 hours 51 mins 44 secs
+    | @ 512785 days 20 hours 51 mins 44 secs
+    | @ 330164 days 20 hours 51 mins 44 secs
+    | @ 111018 days 20 hours 51 mins 44 secs
+    | @ 74494 days 20 hours 51 mins 44 secs
+    | @ 37970 days 20 hours 51 mins 44 secs
+    | @ 1446 days 20 hours 51 mins 44 secs
+    | @ 35078 days 3 hours 8 mins 16 secs
+    | @ 1800 days 20 hours 51 mins 44 secs
+    | @ 1799 days 20 hours 51 mins 44 secs
+    | @ 1798 days 20 hours 51 mins 44 secs
+    | @ 1494 days 20 hours 51 mins 44 secs
+    | @ 1493 days 20 hours 51 mins 44 secs
+    | @ 1492 days 20 hours 51 mins 44 secs
+    | @ 1434 days 20 hours 51 mins 44 secs
+    | @ 1433 days 20 hours 51 mins 44 secs
+    | @ 1129 days 20 hours 51 mins 44 secs
+    | @ 1128 days 20 hours 51 mins 44 secs
+    | @ 398 days 20 hours 51 mins 44 secs
+    | @ 397 days 20 hours 51 mins 44 secs
+    | @ 32 days 20 hours 51 mins 44 secs
+    | @ 31 days 20 hours 51 mins 44 secs
+(63 rows)
+
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 8a4c719..0a05e37 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -2544,3 +2544,217 @@ select * from tmptz where f1 at time zone 'utc' = '2017-01-18 00:00';
  Tue Jan 17 16:00:00 2017 PST
 (1 row)
 
+-- distance operators
+SELECT '' AS  "0", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMPTZ_TBL;
+ERROR:  interval out of range
+SELECT '' AS "63", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMPTZ_TBL WHERE isfinite(d1);
+ 63 |               Distance                
+----+---------------------------------------
+    | @ 11356 days 8 hours
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 58 secs
+    | @ 1453 days 6 hours 27 mins 58.6 secs
+    | @ 1453 days 6 hours 27 mins 58.5 secs
+    | @ 1453 days 6 hours 27 mins 58.4 secs
+    | @ 1493 days
+    | @ 1492 days 20 hours 55 mins 55 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1333 days 7 hours 27 mins 59 secs
+    | @ 231 days 17 hours 19 mins 20 secs
+    | @ 324 days 15 hours 45 mins 59 secs
+    | @ 324 days 19 hours 45 mins 58 secs
+    | @ 324 days 21 hours 45 mins 57 secs
+    | @ 324 days 20 hours 45 mins 56 secs
+    | @ 324 days 22 hours 45 mins 55 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 28 mins
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1453 days 14 hours 27 mins 59 secs
+    | @ 1453 days 14 hours 27 mins 59 secs
+    | @ 1453 days 14 hours 27 mins 59 secs
+    | @ 1453 days 9 hours 27 mins 59 secs
+    | @ 1303 days 10 hours 27 mins 59 secs
+    | @ 1333 days 6 hours 27 mins 59 secs
+    | @ 1453 days 6 hours 27 mins 59 secs
+    | @ 1452 days 6 hours 27 mins 59 secs
+    | @ 1451 days 6 hours 27 mins 59 secs
+    | @ 1450 days 6 hours 27 mins 59 secs
+    | @ 1449 days 6 hours 27 mins 59 secs
+    | @ 1448 days 6 hours 27 mins 59 secs
+    | @ 1447 days 6 hours 27 mins 59 secs
+    | @ 765901 days 6 hours 27 mins 59 secs
+    | @ 695407 days 6 hours 27 mins 59 secs
+    | @ 512786 days 6 hours 27 mins 59 secs
+    | @ 330165 days 6 hours 27 mins 59 secs
+    | @ 111019 days 6 hours 27 mins 59 secs
+    | @ 74495 days 6 hours 27 mins 59 secs
+    | @ 37971 days 6 hours 27 mins 59 secs
+    | @ 1447 days 6 hours 27 mins 59 secs
+    | @ 35077 days 17 hours 32 mins 1 sec
+    | @ 1801 days 6 hours 27 mins 59 secs
+    | @ 1800 days 6 hours 27 mins 59 secs
+    | @ 1799 days 6 hours 27 mins 59 secs
+    | @ 1495 days 6 hours 27 mins 59 secs
+    | @ 1494 days 6 hours 27 mins 59 secs
+    | @ 1493 days 6 hours 27 mins 59 secs
+    | @ 1435 days 6 hours 27 mins 59 secs
+    | @ 1434 days 6 hours 27 mins 59 secs
+    | @ 1130 days 6 hours 27 mins 59 secs
+    | @ 1129 days 6 hours 27 mins 59 secs
+    | @ 399 days 6 hours 27 mins 59 secs
+    | @ 398 days 6 hours 27 mins 59 secs
+    | @ 33 days 6 hours 27 mins 59 secs
+    | @ 32 days 6 hours 27 mins 59 secs
+(64 rows)
+
+SELECT '' AS  "0", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMPTZ_TBL;
+ERROR:  interval out of range
+SELECT '' AS "63", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMPTZ_TBL WHERE isfinite(d1);
+ 63 |               Distance                
+----+---------------------------------------
+    | @ 11356 days 9 hours 23 mins 45 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 43 secs
+    | @ 1453 days 7 hours 51 mins 43.6 secs
+    | @ 1453 days 7 hours 51 mins 43.5 secs
+    | @ 1453 days 7 hours 51 mins 43.4 secs
+    | @ 1493 days 1 hour 23 mins 45 secs
+    | @ 1492 days 22 hours 19 mins 40 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1333 days 8 hours 51 mins 44 secs
+    | @ 231 days 15 hours 55 mins 35 secs
+    | @ 324 days 17 hours 9 mins 44 secs
+    | @ 324 days 21 hours 9 mins 43 secs
+    | @ 324 days 23 hours 9 mins 42 secs
+    | @ 324 days 22 hours 9 mins 41 secs
+    | @ 325 days 9 mins 40 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 45 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1453 days 15 hours 51 mins 44 secs
+    | @ 1453 days 15 hours 51 mins 44 secs
+    | @ 1453 days 15 hours 51 mins 44 secs
+    | @ 1453 days 10 hours 51 mins 44 secs
+    | @ 1303 days 11 hours 51 mins 44 secs
+    | @ 1333 days 7 hours 51 mins 44 secs
+    | @ 1453 days 7 hours 51 mins 44 secs
+    | @ 1452 days 7 hours 51 mins 44 secs
+    | @ 1451 days 7 hours 51 mins 44 secs
+    | @ 1450 days 7 hours 51 mins 44 secs
+    | @ 1449 days 7 hours 51 mins 44 secs
+    | @ 1448 days 7 hours 51 mins 44 secs
+    | @ 1447 days 7 hours 51 mins 44 secs
+    | @ 765901 days 7 hours 51 mins 44 secs
+    | @ 695407 days 7 hours 51 mins 44 secs
+    | @ 512786 days 7 hours 51 mins 44 secs
+    | @ 330165 days 7 hours 51 mins 44 secs
+    | @ 111019 days 7 hours 51 mins 44 secs
+    | @ 74495 days 7 hours 51 mins 44 secs
+    | @ 37971 days 7 hours 51 mins 44 secs
+    | @ 1447 days 7 hours 51 mins 44 secs
+    | @ 35077 days 16 hours 8 mins 16 secs
+    | @ 1801 days 7 hours 51 mins 44 secs
+    | @ 1800 days 7 hours 51 mins 44 secs
+    | @ 1799 days 7 hours 51 mins 44 secs
+    | @ 1495 days 7 hours 51 mins 44 secs
+    | @ 1494 days 7 hours 51 mins 44 secs
+    | @ 1493 days 7 hours 51 mins 44 secs
+    | @ 1435 days 7 hours 51 mins 44 secs
+    | @ 1434 days 7 hours 51 mins 44 secs
+    | @ 1130 days 7 hours 51 mins 44 secs
+    | @ 1129 days 7 hours 51 mins 44 secs
+    | @ 399 days 7 hours 51 mins 44 secs
+    | @ 398 days 7 hours 51 mins 44 secs
+    | @ 33 days 7 hours 51 mins 44 secs
+    | @ 32 days 7 hours 51 mins 44 secs
+(64 rows)
+
+SELECT '' AS  "0", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMPTZ_TBL;
+ERROR:  interval out of range
+SELECT '' AS "63", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMPTZ_TBL WHERE isfinite(d1);
+ 63 |                Distance                
+----+----------------------------------------
+    | @ 11355 days 22 hours 23 mins 45 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 43 secs
+    | @ 1452 days 20 hours 51 mins 43.6 secs
+    | @ 1452 days 20 hours 51 mins 43.5 secs
+    | @ 1452 days 20 hours 51 mins 43.4 secs
+    | @ 1492 days 14 hours 23 mins 45 secs
+    | @ 1492 days 11 hours 19 mins 40 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1332 days 21 hours 51 mins 44 secs
+    | @ 232 days 2 hours 55 mins 35 secs
+    | @ 324 days 6 hours 9 mins 44 secs
+    | @ 324 days 10 hours 9 mins 43 secs
+    | @ 324 days 12 hours 9 mins 42 secs
+    | @ 324 days 11 hours 9 mins 41 secs
+    | @ 324 days 13 hours 9 mins 40 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 45 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1453 days 4 hours 51 mins 44 secs
+    | @ 1453 days 4 hours 51 mins 44 secs
+    | @ 1453 days 4 hours 51 mins 44 secs
+    | @ 1452 days 23 hours 51 mins 44 secs
+    | @ 1303 days 51 mins 44 secs
+    | @ 1332 days 20 hours 51 mins 44 secs
+    | @ 1452 days 20 hours 51 mins 44 secs
+    | @ 1451 days 20 hours 51 mins 44 secs
+    | @ 1450 days 20 hours 51 mins 44 secs
+    | @ 1449 days 20 hours 51 mins 44 secs
+    | @ 1448 days 20 hours 51 mins 44 secs
+    | @ 1447 days 20 hours 51 mins 44 secs
+    | @ 1446 days 20 hours 51 mins 44 secs
+    | @ 765900 days 20 hours 51 mins 44 secs
+    | @ 695406 days 20 hours 51 mins 44 secs
+    | @ 512785 days 20 hours 51 mins 44 secs
+    | @ 330164 days 20 hours 51 mins 44 secs
+    | @ 111018 days 20 hours 51 mins 44 secs
+    | @ 74494 days 20 hours 51 mins 44 secs
+    | @ 37970 days 20 hours 51 mins 44 secs
+    | @ 1446 days 20 hours 51 mins 44 secs
+    | @ 35078 days 3 hours 8 mins 16 secs
+    | @ 1800 days 20 hours 51 mins 44 secs
+    | @ 1799 days 20 hours 51 mins 44 secs
+    | @ 1798 days 20 hours 51 mins 44 secs
+    | @ 1494 days 20 hours 51 mins 44 secs
+    | @ 1493 days 20 hours 51 mins 44 secs
+    | @ 1492 days 20 hours 51 mins 44 secs
+    | @ 1434 days 20 hours 51 mins 44 secs
+    | @ 1433 days 20 hours 51 mins 44 secs
+    | @ 1129 days 20 hours 51 mins 44 secs
+    | @ 1128 days 20 hours 51 mins 44 secs
+    | @ 398 days 20 hours 51 mins 44 secs
+    | @ 397 days 20 hours 51 mins 44 secs
+    | @ 32 days 20 hours 51 mins 44 secs
+    | @ 31 days 20 hours 51 mins 44 secs
+(64 rows)
+
diff --git a/src/test/regress/sql/date.sql b/src/test/regress/sql/date.sql
index 22f80f2..24be476 100644
--- a/src/test/regress/sql/date.sql
+++ b/src/test/regress/sql/date.sql
@@ -346,3 +346,8 @@ select make_date(2013, 13, 1);
 select make_date(2013, 11, -1);
 select make_time(10, 55, 100.1);
 select make_time(24, 0, 2.1);
+
+-- distance operators
+SELECT '' AS "Fifteen", f1 <-> date '2001-02-03' AS "Distance" FROM DATE_TBL;
+SELECT '' AS "Fifteen", f1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM DATE_TBL;
+SELECT '' AS "Fifteen", f1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM DATE_TBL;
diff --git a/src/test/regress/sql/float4.sql b/src/test/regress/sql/float4.sql
index 646027f..35b5942 100644
--- a/src/test/regress/sql/float4.sql
+++ b/src/test/regress/sql/float4.sql
@@ -87,6 +87,9 @@ UPDATE FLOAT4_TBL
 
 SELECT '' AS five, * FROM FLOAT4_TBL;
 
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3' AS dist FROM FLOAT4_TBL f;
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3'::float8 AS dist FROM FLOAT4_TBL f;
+
 -- test edge-case coercions to integer
 SELECT '32767.4'::float4::int2;
 SELECT '32767.6'::float4::int2;
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index a333218..7fe9bca 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -131,6 +131,9 @@ SELECT ||/ float8 '27' AS three;
 
 SELECT '' AS five, f.f1, ||/f.f1 AS cbrt_f1 FROM FLOAT8_TBL f;
 
+-- distance
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3'::float8 AS dist FROM FLOAT8_TBL f;
+SELECT '' AS five, f.f1, f.f1 <-> '1004.3'::float4 AS dist FROM FLOAT8_TBL f;
 
 SELECT '' AS five, * FROM FLOAT8_TBL;
 
diff --git a/src/test/regress/sql/int2.sql b/src/test/regress/sql/int2.sql
index 7dbafb6..16dd5d8 100644
--- a/src/test/regress/sql/int2.sql
+++ b/src/test/regress/sql/int2.sql
@@ -84,6 +84,16 @@ SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT2_TBL i;
 
 SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT2_TBL i;
 
+-- distance
+SELECT '' AS five, i.f1, i.f1 <-> int2 '2' AS x FROM INT2_TBL i;
+
+SELECT '' AS four, i.f1, i.f1 <-> int2 '2' AS x FROM INT2_TBL i
+WHERE f1 > -32767;
+
+SELECT '' AS five, i.f1, i.f1 <-> int4 '2' AS x FROM INT2_TBL i;
+
+SELECT '' AS five, i.f1, i.f1 <-> int8 '2' AS x FROM INT2_TBL i;
+
 -- corner cases
 SELECT (-1::int2<<15)::text;
 SELECT ((-1::int2<<15)+1::int2)::text;
diff --git a/src/test/regress/sql/int4.sql b/src/test/regress/sql/int4.sql
index f014cb2..cff32946 100644
--- a/src/test/regress/sql/int4.sql
+++ b/src/test/regress/sql/int4.sql
@@ -93,6 +93,16 @@ SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i;
 
 SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i;
 
+SELECT '' AS five, i.f1, i.f1 <-> int2 '2' AS x FROM INT4_TBL i;
+
+SELECT '' AS four, i.f1, i.f1 <-> int2 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+
+SELECT '' AS four, i.f1, i.f1 <-> int4 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+
+SELECT '' AS five, i.f1, i.f1 <-> int8 '2' AS x FROM INT4_TBL i;
+
 --
 -- more complex expressions
 --
diff --git a/src/test/regress/sql/int8.sql b/src/test/regress/sql/int8.sql
index e890452..d7f5bde 100644
--- a/src/test/regress/sql/int8.sql
+++ b/src/test/regress/sql/int8.sql
@@ -89,6 +89,11 @@ SELECT q1 + 42::int2 AS "8plus2", q1 - 42::int2 AS "8minus2", q1 * 42::int2 AS "
 -- int2 op int8
 SELECT 246::int2 + q1 AS "2plus8", 246::int2 - q1 AS "2minus8", 246::int2 * q1 AS "2mul8", 246::int2 / q1 AS "2div8" FROM INT8_TBL;
 
+-- distance
+SELECT '' AS five, q2, q2 <-> int2 '123' AS dist FROM INT8_TBL i;
+SELECT '' AS five, q2, q2 <-> int4 '123' AS dist FROM INT8_TBL i;
+SELECT '' AS five, q2, q2 <-> int8 '123' AS dist FROM INT8_TBL i;
+
 SELECT q2, abs(q2) FROM INT8_TBL;
 SELECT min(q1), min(q2) FROM INT8_TBL;
 SELECT max(q1), max(q2) FROM INT8_TBL;
diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql
index bc5537d..d51c866 100644
--- a/src/test/regress/sql/interval.sql
+++ b/src/test/regress/sql/interval.sql
@@ -59,6 +59,8 @@ SELECT '' AS fortyfive, r1.*, r2.*
    WHERE r1.f1 > r2.f1
    ORDER BY r1.f1, r2.f1;
 
+SELECT '' AS ten, f1 <-> interval '@ 2 day 3 hours' FROM INTERVAL_TBL;
+
 -- Test intervals that are large enough to overflow 64 bits in comparisons
 CREATE TEMP TABLE INTERVAL_TBL_OF (f1 interval);
 INSERT INTO INTERVAL_TBL_OF (f1) VALUES
diff --git a/src/test/regress/sql/money.sql b/src/test/regress/sql/money.sql
index 37b9ecc..8428d59 100644
--- a/src/test/regress/sql/money.sql
+++ b/src/test/regress/sql/money.sql
@@ -25,6 +25,7 @@ SELECT m / 2::float8 FROM money_data;
 SELECT m * 2::float4 FROM money_data;
 SELECT 2::float4 * m FROM money_data;
 SELECT m / 2::float4 FROM money_data;
+SELECT m <-> '$123.45' FROM money_data;
 
 -- All true
 SELECT m = '$123.00' FROM money_data;
diff --git a/src/test/regress/sql/oid.sql b/src/test/regress/sql/oid.sql
index 4a09689..9f54f92 100644
--- a/src/test/regress/sql/oid.sql
+++ b/src/test/regress/sql/oid.sql
@@ -40,4 +40,6 @@ SELECT '' AS four, o.* FROM OID_TBL o WHERE o.f1 >= '1234';
 
 SELECT '' AS three, o.* FROM OID_TBL o WHERE o.f1 > '1234';
 
+SELECT '' AS eight, f1, f1 <-> oid '123' FROM OID_TBL;
+
 DROP TABLE OID_TBL;
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index e2014fc..959928b 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -818,7 +818,7 @@ WHERE pp.oid = ap.amproc AND po.oid = o.oprcode AND o.oid = ao.amopopr AND
     ao.amoprighttype = ap.amprocrighttype AND
     ap.amprocnum = 1 AND
     (pp.provolatile != po.provolatile OR
-     pp.proleakproof != po.proleakproof)
+     (NOT pp.proleakproof AND po.proleakproof))
 ORDER BY 1;
 
 
diff --git a/src/test/regress/sql/time.sql b/src/test/regress/sql/time.sql
index 99a1562..31f0330 100644
--- a/src/test/regress/sql/time.sql
+++ b/src/test/regress/sql/time.sql
@@ -40,3 +40,6 @@ SELECT f1 AS "Eight" FROM TIME_TBL WHERE f1 >= '00:00';
 -- where we do mixed-type arithmetic. - thomas 2000-12-02
 
 SELECT f1 + time '00:01' AS "Illegal" FROM TIME_TBL;
+
+-- distance
+SELECT f1 AS "Ten", f1 <-> time '01:23:45' AS "Distance" FROM TIME_TBL;
diff --git a/src/test/regress/sql/timestamp.sql b/src/test/regress/sql/timestamp.sql
index b7957cb..5d023dd 100644
--- a/src/test/regress/sql/timestamp.sql
+++ b/src/test/regress/sql/timestamp.sql
@@ -230,3 +230,11 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
 
 -- timestamp numeric fields constructor
 SELECT make_timestamp(2014,12,28,6,30,45.887);
+
+-- distance operators
+SELECT '' AS  "0", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMP_TBL;
+SELECT '' AS "63", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMP_TBL WHERE isfinite(d1);
+SELECT '' AS  "0", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMP_TBL;
+SELECT '' AS "63", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMP_TBL WHERE isfinite(d1);
+SELECT '' AS  "0", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMP_TBL;
+SELECT '' AS "63", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMP_TBL WHERE isfinite(d1);
diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql
index c3bd46c..7f0525d 100644
--- a/src/test/regress/sql/timestamptz.sql
+++ b/src/test/regress/sql/timestamptz.sql
@@ -464,3 +464,11 @@ insert into tmptz values ('2017-01-18 00:00+00');
 explain (costs off)
 select * from tmptz where f1 at time zone 'utc' = '2017-01-18 00:00';
 select * from tmptz where f1 at time zone 'utc' = '2017-01-18 00:00';
+
+-- distance operators
+SELECT '' AS  "0", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMPTZ_TBL;
+SELECT '' AS "63", d1 <-> date '2001-02-03' AS "Distance" FROM TIMESTAMPTZ_TBL WHERE isfinite(d1);
+SELECT '' AS  "0", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMPTZ_TBL;
+SELECT '' AS "63", d1 <-> timestamp '2001-02-03 01:23:45' AS "Distance" FROM TIMESTAMPTZ_TBL WHERE isfinite(d1);
+SELECT '' AS  "0", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMPTZ_TBL;
+SELECT '' AS "63", d1 <-> timestamptz '2001-02-03 01:23:45+03' AS "Distance" FROM TIMESTAMPTZ_TBL WHERE isfinite(d1);
