From a9e08392dd6fc6d7d1122296bf5525fbbd61ad0d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 14 Feb 2004 20:16:18 +0000
Subject: [PATCH] Create crosstype comparison operators for date vs. timestamp
 and date vs. timestamptz.  This allows use of indexes for expressions like  
 datecol >= date 'today' - interval '1 month' which were formerly not
 indexable without casting the righthand side down from timestamp to date.

---
 src/backend/utils/adt/date.c      | 485 +++++++++++++++++++++++++-----
 src/backend/utils/adt/timestamp.c |  20 +-
 src/include/catalog/catversion.h  |   4 +-
 src/include/catalog/pg_amop.h     |  26 +-
 src/include/catalog/pg_amproc.h   |   6 +-
 src/include/catalog/pg_operator.h |  39 ++-
 src/include/catalog/pg_proc.h     |  75 ++++-
 src/include/utils/date.h          |  32 +-
 src/include/utils/timestamp.h     |  14 +-
 9 files changed, 601 insertions(+), 100 deletions(-)

diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 8afe5450d27..9346f2ab68c 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.94 2003/11/29 19:51:58 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.95 2004/02/14 20:16:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -150,6 +150,10 @@ date_send(PG_FUNCTION_ARGS)
 }
 
 
+/*
+ * Comparison functions for dates
+ */
+
 Datum
 date_eq(PG_FUNCTION_ARGS)
 {
@@ -269,61 +273,441 @@ date_mii(PG_FUNCTION_ARGS)
 	PG_RETURN_DATEADT(dateVal - days);
 }
 
-#if NOT_USED
-/* date_pl_interval() and date_mi_interval() are probably
- * better implmented by converting the input date
- * to timestamp without time zone. So that is what we do
- * in pg_proc.h - thomas 2002-03-11
+/*
+ * Internal routines for promoting date to timestamp and timestamp with
+ * time zone
  */
 
+#ifdef HAVE_INT64_TIMESTAMP
+/* date is days since 2000, timestamp is microseconds since same... */
+#define date2timestamp(dateVal) \
+	((Timestamp) ((dateVal) * INT64CONST(86400000000)))
+#else
+/* date is days since 2000, timestamp is seconds since same... */
+#define date2timestamp(dateVal) \
+	((Timestamp) ((dateVal) * 86400.0))
+#endif
+
+static TimestampTz
+date2timestamptz(DateADT dateVal)
+{
+	TimestampTz result;
+	struct tm	tt,
+			   *tm = &tt;
+
+	j2date(dateVal + POSTGRES_EPOCH_JDATE,
+		   &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
+
+	if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+	{
+		int			tz;
+
+		tm->tm_hour = 0;
+		tm->tm_min = 0;
+		tm->tm_sec = 0;
+		tz = DetermineLocalTimeZone(tm);
+
+#ifdef HAVE_INT64_TIMESTAMP
+		result = (dateVal * INT64CONST(86400000000))
+			+ (tz * INT64CONST(1000000));
+#else
+		result = dateVal * 86400.0 + tz;
+#endif
+	}
+	else
+	{
+		/* Outside of range for timezone support, so assume UTC */
+#ifdef HAVE_INT64_TIMESTAMP
+		result = (dateVal * INT64CONST(86400000000));
+#else
+		result = dateVal * 86400.0;
+#endif
+	}
+
+	return result;
+}
+
+
+/*
+ * Crosstype comparison functions for dates
+ */
+
+Datum
+date_eq_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
+}
+
+Datum
+date_ne_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
+}
+
+Datum
+date_lt_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
+}
+
+Datum
+date_gt_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
+}
+
+Datum
+date_le_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
+}
+
+Datum
+date_ge_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
+}
+
+Datum
+date_cmp_timestamp(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
+	Timestamp	dt1;
+
+	dt1 = date2timestamp(dateVal);
+
+	PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));
+}
+
+Datum
+date_eq_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);
+}
+
+Datum
+date_ne_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);
+}
+
+Datum
+date_lt_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);
+}
+
+Datum
+date_gt_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);
+}
+
+Datum
+date_le_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);
+}
+
+Datum
+date_ge_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);
+}
+
+Datum
+date_cmp_timestamptz(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	TimestampTz	dt2 = PG_GETARG_TIMESTAMPTZ(1);
+	TimestampTz	dt1;
+
+	dt1 = date2timestamptz(dateVal);
+
+	PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));
+}
+
+Datum
+timestamp_eq_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
+}
+
+Datum
+timestamp_ne_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
+}
+
+Datum
+timestamp_lt_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
+}
+
+Datum
+timestamp_gt_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
+}
+
+Datum
+timestamp_le_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
+}
+
+Datum
+timestamp_ge_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
+}
+
+Datum
+timestamp_cmp_date(PG_FUNCTION_ARGS)
+{
+	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	Timestamp	dt2;
+
+	dt2 = date2timestamp(dateVal);
+
+	PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));
+}
+
+Datum
+timestamptz_eq_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) == 0);
+}
+
+Datum
+timestamptz_ne_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) != 0);
+}
+
+Datum
+timestamptz_lt_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) < 0);
+}
+
+Datum
+timestamptz_gt_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) > 0);
+}
+
+Datum
+timestamptz_le_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) <= 0);
+}
+
+Datum
+timestamptz_ge_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_BOOL(timestamptz_cmp_internal(dt1, dt2) >= 0);
+}
+
+Datum
+timestamptz_cmp_date(PG_FUNCTION_ARGS)
+{
+	TimestampTz	dt1 = PG_GETARG_TIMESTAMPTZ(0);
+	DateADT		dateVal = PG_GETARG_DATEADT(1);
+	TimestampTz	dt2;
+
+	dt2 = date2timestamptz(dateVal);
+
+	PG_RETURN_INT32(timestamptz_cmp_internal(dt1, dt2));
+}
+
+
 /* Add an interval to a date, giving a new date.
  * Must handle both positive and negative intervals.
+ *
+ * We implement this by promoting the date to timestamp (without time zone)
+ * and then using the timestamp plus interval function.
  */
 Datum
 date_pl_interval(PG_FUNCTION_ARGS)
 {
 	DateADT		dateVal = PG_GETARG_DATEADT(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
-	struct tm	tt,
-			   *tm = &tt;
+	Timestamp	dateStamp;
 
-	if (span->month != 0)
-	{
-		j2date(dateVal + POSTGRES_EPOCH_JDATE,
-			   &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
-		tm->tm_mon += span->month;
-		dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
-	}
-	if (span->time != 0)
-		dateVal += (span->time / 86400e0);
+	dateStamp = date2timestamp(dateVal);
 
-	PG_RETURN_DATEADT(dateVal);
+	return DirectFunctionCall2(timestamp_pl_interval,
+							   TimestampGetDatum(dateStamp),
+							   PointerGetDatum(span));
 }
 
 /* Subtract an interval from a date, giving a new date.
  * Must handle both positive and negative intervals.
+ *
+ * We implement this by promoting the date to timestamp (without time zone)
+ * and then using the timestamp minus interval function.
  */
 Datum
 date_mi_interval(PG_FUNCTION_ARGS)
 {
 	DateADT		dateVal = PG_GETARG_DATEADT(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
-	struct tm	tt,
-			   *tm = &tt;
+	Timestamp	dateStamp;
 
-	if (span->month != 0)
-	{
-		j2date(dateVal + POSTGRES_EPOCH_JDATE,
-			   &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
-		tm->tm_mon -= span->month;
-		dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
-	}
-	if (span->time != 0)
-		dateVal -= (span->time / 86400e0);
+	dateStamp = date2timestamp(dateVal);
 
-	PG_RETURN_DATEADT(dateVal);
+	return DirectFunctionCall2(timestamp_mi_interval,
+							   TimestampGetDatum(dateStamp),
+							   PointerGetDatum(span));
 }
-#endif
 
 /* date_timestamp()
  * Convert date to timestamp data type.
@@ -334,13 +718,7 @@ date_timestamp(PG_FUNCTION_ARGS)
 	DateADT		dateVal = PG_GETARG_DATEADT(0);
 	Timestamp	result;
 
-#ifdef HAVE_INT64_TIMESTAMP
-	/* date is days since 2000, timestamp is microseconds since same... */
-	result = dateVal * INT64CONST(86400000000);
-#else
-	/* date is days since 2000, timestamp is seconds since same... */
-	result = dateVal * 86400.0;
-#endif
+	result = date2timestamp(dateVal);
 
 	PG_RETURN_TIMESTAMP(result);
 }
@@ -380,37 +758,8 @@ date_timestamptz(PG_FUNCTION_ARGS)
 {
 	DateADT		dateVal = PG_GETARG_DATEADT(0);
 	TimestampTz result;
-	struct tm	tt,
-			   *tm = &tt;
-
-	j2date(dateVal + POSTGRES_EPOCH_JDATE,
-		   &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
-
-	if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
-	{
-		int			tz;
-
-		tm->tm_hour = 0;
-		tm->tm_min = 0;
-		tm->tm_sec = 0;
-		tz = DetermineLocalTimeZone(tm);
 
-#ifdef HAVE_INT64_TIMESTAMP
-		result = (dateVal * INT64CONST(86400000000))
-			+ (tz * INT64CONST(1000000));
-#else
-		result = dateVal * 86400.0 + tz;
-#endif
-	}
-	else
-	{
-		/* Outside of range for timezone support, so assume UTC */
-#ifdef HAVE_INT64_TIMESTAMP
-		result = (dateVal * INT64CONST(86400000000));
-#else
-		result = dateVal * 86400.0;
-#endif
-	}
+	result = date2timestamptz(dateVal);
 
 	PG_RETURN_TIMESTAMP(result);
 }
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 7aab2455a26..ad79025ebc0 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.98 2003/12/25 03:36:23 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.99 2004/02/14 20:16:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1296,7 +1296,7 @@ SetEpochTimestamp(void)
  *
  *		collate invalid timestamp at the end
  */
-static int
+int
 timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
 {
 #ifdef HAVE_INT64_TIMESTAMP
@@ -1703,7 +1703,7 @@ timestamp_mi(PG_FUNCTION_ARGS)
 }
 
 
-/* timestamp_pl_span()
+/* timestamp_pl_interval()
  * Add a interval to a timestamp data type.
  * Note that interval has provisions for qualitative year/month
  *	units, so try to do the right thing with them.
@@ -1713,7 +1713,7 @@ timestamp_mi(PG_FUNCTION_ARGS)
  * Lastly, add in the "quantitative time".
  */
 Datum
-timestamp_pl_span(PG_FUNCTION_ARGS)
+timestamp_pl_interval(PG_FUNCTION_ARGS)
 {
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
@@ -1764,7 +1764,7 @@ timestamp_pl_span(PG_FUNCTION_ARGS)
 }
 
 Datum
-timestamp_mi_span(PG_FUNCTION_ARGS)
+timestamp_mi_interval(PG_FUNCTION_ARGS)
 {
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
@@ -1773,13 +1773,13 @@ timestamp_mi_span(PG_FUNCTION_ARGS)
 	tspan.month = -span->month;
 	tspan.time = -span->time;
 
-	return DirectFunctionCall2(timestamp_pl_span,
+	return DirectFunctionCall2(timestamp_pl_interval,
 							   TimestampGetDatum(timestamp),
 							   PointerGetDatum(&tspan));
 }
 
 
-/* timestamptz_pl_span()
+/* timestamptz_pl_interval()
  * Add a interval to a timestamp with time zone data type.
  * Note that interval has provisions for qualitative year/month
  *	units, so try to do the right thing with them.
@@ -1789,7 +1789,7 @@ timestamp_mi_span(PG_FUNCTION_ARGS)
  * Lastly, add in the "quantitative time".
  */
 Datum
-timestamptz_pl_span(PG_FUNCTION_ARGS)
+timestamptz_pl_interval(PG_FUNCTION_ARGS)
 {
 	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
@@ -1844,7 +1844,7 @@ timestamptz_pl_span(PG_FUNCTION_ARGS)
 }
 
 Datum
-timestamptz_mi_span(PG_FUNCTION_ARGS)
+timestamptz_mi_interval(PG_FUNCTION_ARGS)
 {
 	TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
@@ -1853,7 +1853,7 @@ timestamptz_mi_span(PG_FUNCTION_ARGS)
 	tspan.month = -span->month;
 	tspan.time = -span->time;
 
-	return DirectFunctionCall2(timestamptz_pl_span,
+	return DirectFunctionCall2(timestamptz_pl_interval,
 							   TimestampGetDatum(timestamp),
 							   PointerGetDatum(&tspan));
 }
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 7fdadf5206a..a32809d9d4c 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.218 2004/02/12 23:41:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.219 2004/02/14 20:16:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200402121
+#define CATALOG_VERSION_NO	200402141
 
 #endif
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 70b0f007128..8d7c59c5bf7 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -23,7 +23,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.57 2003/11/29 22:40:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.58 2004/02/14 20:16:17 tgl Exp $
  *
  * NOTES
  *	 the genbki.sh script reads this file and generates .bki
@@ -301,6 +301,18 @@ DATA(insert (	 434    0 2 f 1096 ));
 DATA(insert (	 434    0 3 f 1093 ));
 DATA(insert (	 434    0 4 f 1098 ));
 DATA(insert (	 434    0 5 f 1097 ));
+/* crosstype operators vs timestamp */
+DATA(insert (	 434 1114 1 f 2345 ));
+DATA(insert (	 434 1114 2 f 2346 ));
+DATA(insert (	 434 1114 3 f 2347 ));
+DATA(insert (	 434 1114 4 f 2348 ));
+DATA(insert (	 434 1114 5 f 2349 ));
+/* crosstype operators vs timestamptz */
+DATA(insert (	 434 1184 1 f 2358 ));
+DATA(insert (	 434 1184 2 f 2359 ));
+DATA(insert (	 434 1184 3 f 2360 ));
+DATA(insert (	 434 1184 4 f 2361 ));
+DATA(insert (	 434 1184 5 f 2362 ));
 
 /*
  *	btree time_ops
@@ -331,6 +343,12 @@ DATA(insert (	2039    0 2 f 2063 ));
 DATA(insert (	2039    0 3 f 2060 ));
 DATA(insert (	2039    0 4 f 2065 ));
 DATA(insert (	2039    0 5 f 2064 ));
+/* crosstype operators vs date */
+DATA(insert (	2039 1082 1 f 2371 ));
+DATA(insert (	2039 1082 2 f 2372 ));
+DATA(insert (	2039 1082 3 f 2373 ));
+DATA(insert (	2039 1082 4 f 2374 ));
+DATA(insert (	2039 1082 5 f 2375 ));
 
 /*
  *	btree timestamptz_ops
@@ -341,6 +359,12 @@ DATA(insert (	1998    0 2 f 1323 ));
 DATA(insert (	1998    0 3 f 1320 ));
 DATA(insert (	1998    0 4 f 1325 ));
 DATA(insert (	1998    0 5 f 1324 ));
+/* crosstype operators vs date */
+DATA(insert (	1998 1082 1 f 2384 ));
+DATA(insert (	1998 1082 2 f 2385 ));
+DATA(insert (	1998 1082 3 f 2386 ));
+DATA(insert (	1998 1082 4 f 2387 ));
+DATA(insert (	1998 1082 5 f 2388 ));
 
 /*
  *	btree interval_ops
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 7d4c3268d41..c8fbf62432f 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.46 2003/11/29 22:40:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.47 2004/02/14 20:16:17 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -91,6 +91,8 @@ DATA(insert (	 428    0 1 1954 ));
 DATA(insert (	 429    0 1	358 ));
 DATA(insert (	 432    0 1	926 ));
 DATA(insert (	 434    0 1 1092 ));
+DATA(insert (	 434 1114 1 2344 ));
+DATA(insert (	 434 1184 1 2357 ));
 DATA(insert (	1970    0 1	354 ));
 DATA(insert (	1970  701 1	2194 ));
 DATA(insert (	1972    0 1	355 ));
@@ -114,10 +116,12 @@ DATA(insert (	1991    0 1	404 ));
 DATA(insert (	1994    0 1	360 ));
 DATA(insert (	1996    0 1 1107 ));
 DATA(insert (	1998    0 1 1314 ));
+DATA(insert (	1998 1082 1 2383 ));
 DATA(insert (	2000    0 1 1358 ));
 DATA(insert (	2002    0 1 1672 ));
 DATA(insert (	2003    0 1	360 ));
 DATA(insert (	2039    0 1 2045 ));
+DATA(insert (	2039 1082 1 2370 ));
 DATA(insert (	2095    0 1 2166 ));
 DATA(insert (	2096    0 1 2166 ));
 DATA(insert (	2097    0 1 2180 ));
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index f9ce05af2a6..7ee7b4d1e62 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.123 2003/12/01 21:52:37 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.124 2004/02/14 20:16:17 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -535,9 +535,9 @@ DATA(insert OID = 1322 (  "<"	   PGNSP PGUID b f 1184 1184	 16 1324 1325 0 0 0 0
 DATA(insert OID = 1323 (  "<="	   PGNSP PGUID b f 1184 1184	 16 1325 1324 0 0 0 0 timestamptz_le scalarltsel scalarltjoinsel ));
 DATA(insert OID = 1324 (  ">"	   PGNSP PGUID b f 1184 1184	 16 1322 1323 0 0 0 0 timestamptz_gt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 1325 (  ">="	   PGNSP PGUID b f 1184 1184	 16 1323 1322 0 0 0 0 timestamptz_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1327 (  "+"	   PGNSP PGUID b f 1184 1186 1184	 0	0 0 0 0 0 timestamptz_pl_span - - ));
+DATA(insert OID = 1327 (  "+"	   PGNSP PGUID b f 1184 1186 1184	 0	0 0 0 0 0 timestamptz_pl_interval - - ));
 DATA(insert OID = 1328 (  "-"	   PGNSP PGUID b f 1184 1184 1186	 0	0 0 0 0 0 timestamptz_mi - - ));
-DATA(insert OID = 1329 (  "-"	   PGNSP PGUID b f 1184 1186 1184	 0	0 0 0 0 0 timestamptz_mi_span - - ));
+DATA(insert OID = 1329 (  "-"	   PGNSP PGUID b f 1184 1186 1184	 0	0 0 0 0 0 timestamptz_mi_interval - - ));
 
 /* interval operators */
 DATA(insert OID = 1330 (  "="	   PGNSP PGUID b t 1186 1186	 16 1330 1331 1332 1332 1332 1334 interval_eq eqsel eqjoinsel ));
@@ -791,9 +791,9 @@ DATA(insert OID = 2062 (  "<"	   PGNSP PGUID b f 1114 1114	 16 2064 2065 0 0 0 0
 DATA(insert OID = 2063 (  "<="	   PGNSP PGUID b f 1114 1114	 16 2065 2064 0 0 0 0 timestamp_le scalarltsel scalarltjoinsel ));
 DATA(insert OID = 2064 (  ">"	   PGNSP PGUID b f 1114 1114	 16 2062 2063 0 0 0 0 timestamp_gt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 2065 (  ">="	   PGNSP PGUID b f 1114 1114	 16 2063 2062 0 0 0 0 timestamp_ge scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2066 (  "+"	   PGNSP PGUID b f 1114 1186 1114	 0	0 0 0 0 0 timestamp_pl_span - - ));
+DATA(insert OID = 2066 (  "+"	   PGNSP PGUID b f 1114 1186 1114	 0	0 0 0 0 0 timestamp_pl_interval - - ));
 DATA(insert OID = 2067 (  "-"	   PGNSP PGUID b f 1114 1114 1186	 0	0 0 0 0 0 timestamp_mi - - ));
-DATA(insert OID = 2068 (  "-"	   PGNSP PGUID b f 1114 1186 1114	 0	0 0 0 0 0 timestamp_mi_span - - ));
+DATA(insert OID = 2068 (  "-"	   PGNSP PGUID b f 1114 1186 1114	 0	0 0 0 0 0 timestamp_mi_interval - - ));
 
 /* character-by-character (not collation order) comparison operators for character types */
 
@@ -818,6 +818,35 @@ DATA(insert OID = 2335 ( "~>=~" PGNSP PGUID b f 19 19 16 2333 2332 0 0 0 0 name_
 DATA(insert OID = 2336 ( "~>~"	PGNSP PGUID b f 19 19 16 2332 2333 0 0 0 0 name_pattern_gt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 2337 ( "~<>~" PGNSP PGUID b f 19 19 16 2337 2334 0 0 0 0 name_pattern_ne neqsel neqjoinsel ));
 
+/* crosstype operations for date vs. timestamp and timestamptz */
+
+DATA(insert OID = 2345 ( "<"	   PGNSP PGUID b f	1082	1114   16 2375 2348  0 0 0 0 date_lt_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2346 ( "<="	   PGNSP PGUID b f	1082	1114   16 2374 2349  0 0 0 0 date_le_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2347 ( "="	   PGNSP PGUID b f	1082	1114   16 2373 2350  0 0 0 0 date_eq_timestamp eqsel eqjoinsel ));
+DATA(insert OID = 2348 ( ">="	   PGNSP PGUID b f	1082	1114   16 2372 2345  0 0 0 0 date_ge_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2349 ( ">"	   PGNSP PGUID b f	1082	1114   16 2371 2346  0 0 0 0 date_gt_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2350 ( "<>"	   PGNSP PGUID b f	1082	1114   16 2376 2347  0 0 0 0 date_ne_timestamp neqsel neqjoinsel ));
+
+DATA(insert OID = 2358 ( "<"	   PGNSP PGUID b f	1082	1184   16 2388 2361  0 0 0 0 date_lt_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2359 ( "<="	   PGNSP PGUID b f	1082	1184   16 2387 2362  0 0 0 0 date_le_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2360 ( "="	   PGNSP PGUID b f	1082	1184   16 2386 2363  0 0 0 0 date_eq_timestamptz eqsel eqjoinsel ));
+DATA(insert OID = 2361 ( ">="	   PGNSP PGUID b f	1082	1184   16 2385 2358  0 0 0 0 date_ge_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2362 ( ">"	   PGNSP PGUID b f	1082	1184   16 2384 2359  0 0 0 0 date_gt_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2363 ( "<>"	   PGNSP PGUID b f	1082	1184   16 2389 2360  0 0 0 0 date_ne_timestamptz neqsel neqjoinsel ));
+
+DATA(insert OID = 2371 ( "<"	   PGNSP PGUID b f	1114	1082   16 2349 2374  0 0 0 0 timestamp_lt_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2372 ( "<="	   PGNSP PGUID b f	1114	1082   16 2348 2375  0 0 0 0 timestamp_le_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2373 ( "="	   PGNSP PGUID b f	1114	1082   16 2347 2376  0 0 0 0 timestamp_eq_date eqsel eqjoinsel ));
+DATA(insert OID = 2374 ( ">="	   PGNSP PGUID b f	1114	1082   16 2346 2371  0 0 0 0 timestamp_ge_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2375 ( ">"	   PGNSP PGUID b f	1114	1082   16 2345 2372  0 0 0 0 timestamp_gt_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2376 ( "<>"	   PGNSP PGUID b f	1114	1082   16 2350 2373  0 0 0 0 timestamp_ne_date neqsel neqjoinsel ));
+
+DATA(insert OID = 2384 ( "<"	   PGNSP PGUID b f	1184	1082   16 2362 2387  0 0 0 0 timestamptz_lt_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2385 ( "<="	   PGNSP PGUID b f	1184	1082   16 2361 2388  0 0 0 0 timestamptz_le_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2386 ( "="	   PGNSP PGUID b f	1184	1082   16 2360 2389  0 0 0 0 timestamptz_eq_date eqsel eqjoinsel ));
+DATA(insert OID = 2387 ( ">="	   PGNSP PGUID b f	1184	1082   16 2359 2384  0 0 0 0 timestamptz_ge_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2388 ( ">"	   PGNSP PGUID b f	1184	1082   16 2358 2385  0 0 0 0 timestamptz_gt_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2389 ( "<>"	   PGNSP PGUID b f	1184	1082   16 2363 2386  0 0 0 0 timestamptz_ne_date neqsel neqjoinsel ));
 
 
 /*
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index fb6eb885d85..f3b70f31ec7 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.319 2004/02/03 08:29:56 joe Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.320 2004/02/14 20:16:17 tgl Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -1485,9 +1485,9 @@ DESCR("age of a transaction ID, in transactions before current transaction");
 
 DATA(insert OID = 1188 (  timestamptz_mi   PGNSP PGUID 12 f f t f i 2 1186 "1184 1184" _null_	timestamp_mi - _null_ ));
 DESCR("subtract");
-DATA(insert OID = 1189 (  timestamptz_pl_span PGNSP PGUID 12 f f t f i 2 1184 "1184 1186" _null_  timestamptz_pl_span - _null_ ));
+DATA(insert OID = 1189 (  timestamptz_pl_interval PGNSP PGUID 12 f f t f i 2 1184 "1184 1186" _null_  timestamptz_pl_interval - _null_ ));
 DESCR("plus");
-DATA(insert OID = 1190 (  timestamptz_mi_span PGNSP PGUID 12 f f t f i 2 1184 "1184 1186" _null_  timestamptz_mi_span - _null_ ));
+DATA(insert OID = 1190 (  timestamptz_mi_interval PGNSP PGUID 12 f f t f i 2 1184 "1184 1186" _null_  timestamptz_mi_interval - _null_ ));
 DESCR("minus");
 DATA(insert OID = 1191 (  timestamptz		PGNSP PGUID 12 f f t f s 1 1184 "25" _null_	text_timestamptz - _null_ ));
 DESCR("convert text to timestamp with time zone");
@@ -2875,9 +2875,9 @@ DATA(insert OID = 2030 (  abstime			PGNSP PGUID 12 f f t f s 1	702 "1114" _null_
 DESCR("convert timestamp to abstime");
 DATA(insert OID = 2031 (  timestamp_mi		PGNSP PGUID 12 f f t f i 2 1186 "1114 1114" _null_  timestamp_mi - _null_ ));
 DESCR("subtract");
-DATA(insert OID = 2032 (  timestamp_pl_span PGNSP PGUID 12 f f t f i 2 1114 "1114 1186" _null_  timestamp_pl_span - _null_ ));
+DATA(insert OID = 2032 (  timestamp_pl_interval PGNSP PGUID 12 f f t f i 2 1114 "1114 1186" _null_  timestamp_pl_interval - _null_ ));
 DESCR("plus");
-DATA(insert OID = 2033 (  timestamp_mi_span PGNSP PGUID 12 f f t f i 2 1114 "1114 1186" _null_  timestamp_mi_span - _null_ ));
+DATA(insert OID = 2033 (  timestamp_mi_interval PGNSP PGUID 12 f f t f i 2 1114 "1114 1186" _null_  timestamp_mi_interval - _null_ ));
 DESCR("minus");
 DATA(insert OID = 2034 (  text				PGNSP PGUID 12 f f t f s 1	 25 "1114" _null_	timestamp_text - _null_ ));
 DESCR("convert timestamp to text");
@@ -2932,9 +2932,9 @@ DATA(insert OID = 2069 (  timezone			PGNSP PGUID 12 f f t f s 2 1184 "25 1114" _
 DESCR("adjust timestamp to new time zone");
 DATA(insert OID = 2070 (  timezone			PGNSP PGUID 12 f f t f s 2 1184 "1186 1114" _null_  timestamp_izone - _null_ ));
 DESCR("adjust timestamp to new time zone");
-DATA(insert OID = 2071 (  date_pl_interval	PGNSP PGUID 14 f f t f i 2 1114 "1082 1186" _null_  "select cast($1 as timestamp without time zone) + $2;" - _null_ ));
+DATA(insert OID = 2071 (  date_pl_interval	PGNSP PGUID 12 f f t f i 2 1114 "1082 1186" _null_  date_pl_interval - _null_ ));
 DESCR("add");
-DATA(insert OID = 2072 (  date_mi_interval	PGNSP PGUID 14 f f t f i 2 1114 "1082 1186" _null_  "select cast($1 as timestamp without time zone) - $2;" - _null_ ));
+DATA(insert OID = 2072 (  date_mi_interval	PGNSP PGUID 12 f f t f i 2 1114 "1082 1186" _null_  date_mi_interval - _null_ ));
 DESCR("subtract");
 
 DATA(insert OID = 2073 (  substring			PGNSP PGUID 12 f f t f i 2 25 "25 25" _null_	textregexsubstr - _null_ ));
@@ -3200,7 +3200,68 @@ DESCR("I/O");
 DATA(insert OID =  2311 (  md5	   PGNSP PGUID 12 f f t f i 1 25 "25" _null_  md5_text - _null_ ));
 DESCR("calculates md5 hash");
 
+/* crosstype operations for date vs. timestamp and timestamptz */
+DATA(insert OID = 2338 (  date_lt_timestamp		   PGNSP PGUID 12 f f t f i 2 16 "1082 1114" _null_	date_lt_timestamp - _null_ ));
+DESCR("less-than");
+DATA(insert OID = 2339 (  date_le_timestamp		   PGNSP PGUID 12 f f t f i 2 16 "1082 1114" _null_	date_le_timestamp - _null_ ));
+DESCR("less-than-or-equal");
+DATA(insert OID = 2340 (  date_eq_timestamp		   PGNSP PGUID 12 f f t f i 2 16 "1082 1114" _null_	date_eq_timestamp - _null_ ));
+DESCR("equal");
+DATA(insert OID = 2341 (  date_gt_timestamp		   PGNSP PGUID 12 f f t f i 2 16 "1082 1114" _null_	date_gt_timestamp - _null_ ));
+DESCR("greater-than");
+DATA(insert OID = 2342 (  date_ge_timestamp		   PGNSP PGUID 12 f f t f i 2 16 "1082 1114" _null_	date_ge_timestamp - _null_ ));
+DESCR("greater-than-or-equal");
+DATA(insert OID = 2343 (  date_ne_timestamp		   PGNSP PGUID 12 f f t f i 2 16 "1082 1114" _null_	date_ne_timestamp - _null_ ));
+DESCR("not equal");
+DATA(insert OID = 2344 (  date_cmp_timestamp	   PGNSP PGUID 12 f f t f i 2 23 "1082 1114" _null_	date_cmp_timestamp - _null_ ));
+DESCR("less-equal-greater");
+
+DATA(insert OID = 2351 (  date_lt_timestamptz	   PGNSP PGUID 12 f f t f s 2 16 "1082 1184" _null_	date_lt_timestamptz - _null_ ));
+DESCR("less-than");
+DATA(insert OID = 2352 (  date_le_timestamptz	   PGNSP PGUID 12 f f t f s 2 16 "1082 1184" _null_	date_le_timestamptz - _null_ ));
+DESCR("less-than-or-equal");
+DATA(insert OID = 2353 (  date_eq_timestamptz	   PGNSP PGUID 12 f f t f s 2 16 "1082 1184" _null_	date_eq_timestamptz - _null_ ));
+DESCR("equal");
+DATA(insert OID = 2354 (  date_gt_timestamptz	   PGNSP PGUID 12 f f t f s 2 16 "1082 1184" _null_	date_gt_timestamptz - _null_ ));
+DESCR("greater-than");
+DATA(insert OID = 2355 (  date_ge_timestamptz	   PGNSP PGUID 12 f f t f s 2 16 "1082 1184" _null_	date_ge_timestamptz - _null_ ));
+DESCR("greater-than-or-equal");
+DATA(insert OID = 2356 (  date_ne_timestamptz	   PGNSP PGUID 12 f f t f s 2 16 "1082 1184" _null_	date_ne_timestamptz - _null_ ));
+DESCR("not equal");
+DATA(insert OID = 2357 (  date_cmp_timestamptz	   PGNSP PGUID 12 f f t f s 2 23 "1082 1184" _null_	date_cmp_timestamptz - _null_ ));
+DESCR("less-equal-greater");
+
+DATA(insert OID = 2364 (  timestamp_lt_date		   PGNSP PGUID 12 f f t f i 2 16 "1114 1082" _null_	timestamp_lt_date - _null_ ));
+DESCR("less-than");
+DATA(insert OID = 2365 (  timestamp_le_date		   PGNSP PGUID 12 f f t f i 2 16 "1114 1082" _null_	timestamp_le_date - _null_ ));
+DESCR("less-than-or-equal");
+DATA(insert OID = 2366 (  timestamp_eq_date		   PGNSP PGUID 12 f f t f i 2 16 "1114 1082" _null_	timestamp_eq_date - _null_ ));
+DESCR("equal");
+DATA(insert OID = 2367 (  timestamp_gt_date		   PGNSP PGUID 12 f f t f i 2 16 "1114 1082" _null_	timestamp_gt_date - _null_ ));
+DESCR("greater-than");
+DATA(insert OID = 2368 (  timestamp_ge_date		   PGNSP PGUID 12 f f t f i 2 16 "1114 1082" _null_	timestamp_ge_date - _null_ ));
+DESCR("greater-than-or-equal");
+DATA(insert OID = 2369 (  timestamp_ne_date		   PGNSP PGUID 12 f f t f i 2 16 "1114 1082" _null_	timestamp_ne_date - _null_ ));
+DESCR("not equal");
+DATA(insert OID = 2370 (  timestamp_cmp_date	   PGNSP PGUID 12 f f t f i 2 23 "1114 1082" _null_	timestamp_cmp_date - _null_ ));
+DESCR("less-equal-greater");
+
+DATA(insert OID = 2377 (  timestamptz_lt_date	   PGNSP PGUID 12 f f t f s 2 16 "1184 1082" _null_	timestamptz_lt_date - _null_ ));
+DESCR("less-than");
+DATA(insert OID = 2378 (  timestamptz_le_date	   PGNSP PGUID 12 f f t f s 2 16 "1184 1082" _null_	timestamptz_le_date - _null_ ));
+DESCR("less-than-or-equal");
+DATA(insert OID = 2379 (  timestamptz_eq_date	   PGNSP PGUID 12 f f t f s 2 16 "1184 1082" _null_	timestamptz_eq_date - _null_ ));
+DESCR("equal");
+DATA(insert OID = 2380 (  timestamptz_gt_date	   PGNSP PGUID 12 f f t f s 2 16 "1184 1082" _null_	timestamptz_gt_date - _null_ ));
+DESCR("greater-than");
+DATA(insert OID = 2381 (  timestamptz_ge_date	   PGNSP PGUID 12 f f t f s 2 16 "1184 1082" _null_	timestamptz_ge_date - _null_ ));
+DESCR("greater-than-or-equal");
+DATA(insert OID = 2382 (  timestamptz_ne_date	   PGNSP PGUID 12 f f t f s 2 16 "1184 1082" _null_	timestamptz_ne_date - _null_ ));
+DESCR("not equal");
+DATA(insert OID = 2383 (  timestamptz_cmp_date	   PGNSP PGUID 12 f f t f s 2 23 "1184 1082" _null_	timestamptz_cmp_date - _null_ ));
+DESCR("less-equal-greater");
 
+/* send/receive functions */
 DATA(insert OID = 2400 (  array_recv		   PGNSP PGUID 12 f f t f s 2 2277 "2281 26" _null_  array_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2401 (  array_send		   PGNSP PGUID 12 f f t f s 2 17 "2277 26" _null_	array_send - _null_ ));
diff --git a/src/include/utils/date.h b/src/include/utils/date.h
index 5b1fae27f0a..910bac4ec4a 100644
--- a/src/include/utils/date.h
+++ b/src/include/utils/date.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/date.h,v 1.25 2003/11/29 22:41:15 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/date.h,v 1.26 2004/02/14 20:16:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -84,6 +84,36 @@ extern Datum date_smaller(PG_FUNCTION_ARGS);
 extern Datum date_mi(PG_FUNCTION_ARGS);
 extern Datum date_pli(PG_FUNCTION_ARGS);
 extern Datum date_mii(PG_FUNCTION_ARGS);
+extern Datum date_eq_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_ne_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_lt_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_le_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_gt_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_ge_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_cmp_timestamp(PG_FUNCTION_ARGS);
+extern Datum date_eq_timestamptz(PG_FUNCTION_ARGS);
+extern Datum date_ne_timestamptz(PG_FUNCTION_ARGS);
+extern Datum date_lt_timestamptz(PG_FUNCTION_ARGS);
+extern Datum date_le_timestamptz(PG_FUNCTION_ARGS);
+extern Datum date_gt_timestamptz(PG_FUNCTION_ARGS);
+extern Datum date_ge_timestamptz(PG_FUNCTION_ARGS);
+extern Datum date_cmp_timestamptz(PG_FUNCTION_ARGS);
+extern Datum timestamp_eq_date(PG_FUNCTION_ARGS);
+extern Datum timestamp_ne_date(PG_FUNCTION_ARGS);
+extern Datum timestamp_lt_date(PG_FUNCTION_ARGS);
+extern Datum timestamp_le_date(PG_FUNCTION_ARGS);
+extern Datum timestamp_gt_date(PG_FUNCTION_ARGS);
+extern Datum timestamp_ge_date(PG_FUNCTION_ARGS);
+extern Datum timestamp_cmp_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_eq_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_ne_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_lt_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_le_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_gt_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_ge_date(PG_FUNCTION_ARGS);
+extern Datum timestamptz_cmp_date(PG_FUNCTION_ARGS);
+extern Datum date_pl_interval(PG_FUNCTION_ARGS);
+extern Datum date_mi_interval(PG_FUNCTION_ARGS);
 extern Datum date_timestamp(PG_FUNCTION_ARGS);
 extern Datum timestamp_date(PG_FUNCTION_ARGS);
 extern Datum date_timestamptz(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index d70a6f1833f..aa395ba4f49 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.33 2003/12/25 03:36:24 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.34 2004/02/14 20:16:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -218,15 +218,15 @@ extern Datum interval_accum(PG_FUNCTION_ARGS);
 extern Datum interval_avg(PG_FUNCTION_ARGS);
 
 extern Datum timestamp_mi(PG_FUNCTION_ARGS);
-extern Datum timestamp_pl_span(PG_FUNCTION_ARGS);
-extern Datum timestamp_mi_span(PG_FUNCTION_ARGS);
+extern Datum timestamp_pl_interval(PG_FUNCTION_ARGS);
+extern Datum timestamp_mi_interval(PG_FUNCTION_ARGS);
 extern Datum timestamp_age(PG_FUNCTION_ARGS);
 extern Datum overlaps_timestamp(PG_FUNCTION_ARGS);
 
 extern Datum timestamptz_text(PG_FUNCTION_ARGS);
 extern Datum text_timestamptz(PG_FUNCTION_ARGS);
-extern Datum timestamptz_pl_span(PG_FUNCTION_ARGS);
-extern Datum timestamptz_mi_span(PG_FUNCTION_ARGS);
+extern Datum timestamptz_pl_interval(PG_FUNCTION_ARGS);
+extern Datum timestamptz_mi_interval(PG_FUNCTION_ARGS);
 extern Datum timestamptz_age(PG_FUNCTION_ARGS);
 extern Datum timestamptz_trunc(PG_FUNCTION_ARGS);
 extern Datum timestamptz_part(PG_FUNCTION_ARGS);
@@ -246,6 +246,10 @@ extern int	tm2interval(struct tm * tm, fsec_t fsec, Interval *span);
 extern Timestamp SetEpochTimestamp(void);
 extern void GetEpochTime(struct tm * tm);
 
+extern int	timestamp_cmp_internal(Timestamp dt1, Timestamp dt2);
+/* timestamp comparison works for timestamptz also */
+#define timestamptz_cmp_internal(dt1,dt2)	timestamp_cmp_internal(dt1, dt2)
+
 extern void isoweek2date(int woy, int *year, int *mon, int *mday);
 extern int	date2isoweek(int year, int mon, int mday);
 extern int	date2isoyear(int year, int mon, int mday);
-- 
GitLab