diff options
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 5 | ||||
-rw-r--r-- | src/test/regress/expected/timestamp.out | 9 | ||||
-rw-r--r-- | src/test/regress/expected/timestamptz.out | 9 | ||||
-rw-r--r-- | src/test/regress/sql/timestamp.sql | 4 | ||||
-rw-r--r-- | src/test/regress/sql/timestamptz.sql | 4 |
5 files changed, 30 insertions, 1 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 47e059a409b..de93db89d48 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -2713,7 +2713,10 @@ timestamp_mi(PG_FUNCTION_ARGS) (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("cannot subtract infinite timestamps"))); - result->time = dt1 - dt2; + if (unlikely(pg_sub_s64_overflow(dt1, dt2, &result->time))) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("interval out of range"))); result->month = 0; result->day = 0; diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out index edc6912e7ab..eef2f7001c3 100644 --- a/src/test/regress/expected/timestamp.out +++ b/src/test/regress/expected/timestamp.out @@ -1207,6 +1207,15 @@ SELECT extract(epoch from '5000-01-01 00:00:00'::timestamp); 95617584000.000000 (1 row) +-- test edge-case overflow in timestamp subtraction +SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224193' AS ok; + ok +----------------------------------------- + @ 106751991 days 4 hours 54.775807 secs +(1 row) + +SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224192' AS overflows; +ERROR: interval out of range -- TO_CHAR() SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') FROM TIMESTAMP_TBL; diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out index 00379fd0fd3..b85a93a3c29 100644 --- a/src/test/regress/expected/timestamptz.out +++ b/src/test/regress/expected/timestamptz.out @@ -1331,6 +1331,15 @@ SELECT extract(epoch from '5000-01-01 00:00:00+00'::timestamptz); 95617584000.000000 (1 row) +-- test edge-case overflow in timestamp subtraction +SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224193 UTC' AS ok; + ok +----------------------------------------- + @ 106751991 days 4 hours 54.775807 secs +(1 row) + +SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224192 UTC' AS overflows; +ERROR: interval out of range -- TO_CHAR() SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') FROM TIMESTAMPTZ_TBL; diff --git a/src/test/regress/sql/timestamp.sql b/src/test/regress/sql/timestamp.sql index 1d580f77f15..2d5f01ab868 100644 --- a/src/test/regress/sql/timestamp.sql +++ b/src/test/regress/sql/timestamp.sql @@ -326,6 +326,10 @@ SELECT extract(epoch from '294270-01-01 00:00:00'::timestamp); -- another internal overflow test case SELECT extract(epoch from '5000-01-01 00:00:00'::timestamp); +-- test edge-case overflow in timestamp subtraction +SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224193' AS ok; +SELECT timestamp '294276-12-31 23:59:59' - timestamp '1999-12-23 19:59:04.224192' AS overflows; + -- TO_CHAR() SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') FROM TIMESTAMP_TBL; diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql index 4905dd08317..6d10937d863 100644 --- a/src/test/regress/sql/timestamptz.sql +++ b/src/test/regress/sql/timestamptz.sql @@ -306,6 +306,10 @@ SELECT extract(epoch from '294270-01-01 00:00:00+00'::timestamptz); -- another internal overflow test case SELECT extract(epoch from '5000-01-01 00:00:00+00'::timestamptz); +-- test edge-case overflow in timestamp subtraction +SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224193 UTC' AS ok; +SELECT timestamptz '294276-12-31 23:59:59 UTC' - timestamptz '1999-12-23 19:59:04.224192 UTC' AS overflows; + -- TO_CHAR() SELECT to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon') FROM TIMESTAMPTZ_TBL; |