From 841b4a2d5552fcee2333dff53e66052fbee7bd22 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 4 Jul 2003 18:21:14 +0000
Subject: [PATCH] tm2timestamp should return -1, not elog, on overflow.  (In
 the backend this is merely an API inconsistency, but in ecpg it's fatal.) 
 Also, fix misconceived overflow test in HAVE_INT64_TIMESTAMP case.

---
 src/backend/utils/adt/timestamp.c          | 15 ++++++++++-----
 src/interfaces/ecpg/pgtypeslib/timestamp.c | 13 +++++++++----
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 6cfd2bf1ec6..6cf4f3667cf 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.84 2003/05/12 23:08:50 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.85 2003/07/04 18:21:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1052,6 +1052,8 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn)
  * Convert a tm structure to a timestamp data type.
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
+ *
+ * Returns -1 on failure (overflow).
  */
 int
 tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
@@ -1072,10 +1074,13 @@ tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
 	date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
 	time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #ifdef HAVE_INT64_TIMESTAMP
-	*result = ((date * INT64CONST(86400000000)) + time);
-	if ((*result < 0 && date >= 0) || (*result >= 0 && date < 0))
-		elog(ERROR, "TIMESTAMP out of range '%04d-%02d-%02d'",
-			tm->tm_year, tm->tm_mon, tm->tm_mday);
+	*result = (date * INT64CONST(86400000000)) + time;
+	/* check for major overflow */
+	if ((*result - time) / INT64CONST(86400000000) != date)
+		return -1;
+	/* check for just-barely overflow (okay except time-of-day wraps) */
+	if ((*result < 0) ? (date >= 0) : (date < 0))
+		return -1;
 #else
 	*result = ((date * 86400) + time);
 #endif
diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c
index 6bc2d5e5ad2..564e1f83c6b 100644
--- a/src/interfaces/ecpg/pgtypeslib/timestamp.c
+++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c
@@ -44,6 +44,8 @@ dt2local(Timestamp dt, int tz)
  * Convert a tm structure to a timestamp data type.
  * Note that year is _not_ 1900-based, but is an explicit full value.
  * Also, month is one-based, _not_ zero-based.
+ *
+ * Returns -1 on failure (overflow).
  */
 static int
 tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
@@ -64,10 +66,13 @@ tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
 	date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
 	time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
 #ifdef HAVE_INT64_TIMESTAMP
-	*result = ((date * INT64CONST(86400000000)) + time);
-	if ((*result < 0 && date >= 0) || (*result >= 0 && date < 0))
-		elog(ERROR, "TIMESTAMP out of range '%04d-%02d-%02d'",
-			tm->tm_year, tm->tm_mon, tm->tm_mday);
+	*result = (date * INT64CONST(86400000000)) + time;
+	/* check for major overflow */
+	if ((*result - time) / INT64CONST(86400000000) != date)
+		return -1;
+	/* check for just-barely overflow (okay except time-of-day wraps) */
+	if ((*result < 0) ? (date >= 0) : (date < 0))
+		return -1;
 #else
 	*result = ((date * 86400) + time);
 #endif
-- 
GitLab