1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

Be more careful about out-of-range dates and timestamps.

Tighten the semantics of boundary-case timestamptz so that we allow
timestamps >= '4714-11-24 00:00+00 BC' and < 'ENDYEAR-01-01 00:00+00 AD'
exactly, no more and no less, but it is allowed to enter timestamps
within that range using non-GMT timezone offsets (which could make the
nominal date 4714-11-23 BC or ENDYEAR-01-01 AD).  This eliminates
dump/reload failure conditions for timestamps near the endpoints.
To do this, separate checking of the inputs for date2j() from the
final range check, and allow the Julian date code to handle a range
slightly wider than the nominal range of the datatypes.

Also add a bunch of checks to detect out-of-range dates and timestamps
that formerly could be returned by operations such as date-plus-integer.
All C-level functions that return date, timestamp, or timestamptz should
now be proof against returning a value that doesn't pass IS_VALID_DATE()
or IS_VALID_TIMESTAMP().

Vitaly Burovoy, reviewed by Anastasia Lubennikova, and substantially
whacked around by me
This commit is contained in:
Tom Lane
2016-03-16 19:09:04 -04:00
parent f2b74b01d4
commit a70e13a39e
13 changed files with 364 additions and 53 deletions

View File

@ -816,6 +816,27 @@ SELECT date '1999 08 01';
1999-08-01
(1 row)
-- Check upper and lower limits of date range
SELECT date '4714-11-24 BC';
date
---------------
4714-11-24 BC
(1 row)
SELECT date '4714-11-23 BC'; -- out of range
ERROR: date out of range: "4714-11-23 BC"
LINE 1: SELECT date '4714-11-23 BC';
^
SELECT date '5874897-12-31';
date
---------------
5874897-12-31
(1 row)
SELECT date '5874898-01-01'; -- out of range
ERROR: date out of range: "5874898-01-01"
LINE 1: SELECT date '5874898-01-01';
^
RESET datestyle;
--
-- Simple math

View File

@ -250,6 +250,18 @@ SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
| Mon Jan 01 17:32:01 2001
(65 rows)
-- Check behavior at the lower boundary of the timestamp range
SELECT '4714-11-24 00:00:00 BC'::timestamp;
timestamp
-----------------------------
Mon Nov 24 00:00:00 4714 BC
(1 row)
SELECT '4714-11-23 23:59:59 BC'::timestamp; -- out of range
ERROR: timestamp out of range: "4714-11-23 23:59:59 BC"
LINE 1: SELECT '4714-11-23 23:59:59 BC'::timestamp;
^
-- The upper boundary differs between integer and float timestamps, so no check
-- Demonstrate functions and operators
SELECT '' AS "48", d1 FROM TIMESTAMP_TBL
WHERE d1 > timestamp without time zone '1997-01-02';

View File

@ -322,6 +322,30 @@ SELECT '' AS "64", d1 FROM TIMESTAMPTZ_TBL;
| Mon Jan 01 17:32:01 2001 PST
(66 rows)
-- Check behavior at the lower boundary of the timestamp range
SELECT '4714-11-24 00:00:00+00 BC'::timestamptz;
timestamptz
---------------------------------
Sun Nov 23 16:00:00 4714 PST BC
(1 row)
SELECT '4714-11-23 16:00:00-08 BC'::timestamptz;
timestamptz
---------------------------------
Sun Nov 23 16:00:00 4714 PST BC
(1 row)
SELECT 'Sun Nov 23 16:00:00 4714 PST BC'::timestamptz;
timestamptz
---------------------------------
Sun Nov 23 16:00:00 4714 PST BC
(1 row)
SELECT '4714-11-23 23:59:59+00 BC'::timestamptz; -- out of range
ERROR: timestamp out of range: "4714-11-23 23:59:59+00 BC"
LINE 1: SELECT '4714-11-23 23:59:59+00 BC'::timestamptz;
^
-- The upper boundary differs between integer and float timestamps, so no check
-- Demonstrate functions and operators
SELECT '' AS "48", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 > timestamp with time zone '1997-01-02';

View File

@ -186,6 +186,12 @@ SELECT date '01 08 1999';
SELECT date '99 08 01';
SELECT date '1999 08 01';
-- Check upper and lower limits of date range
SELECT date '4714-11-24 BC';
SELECT date '4714-11-23 BC'; -- out of range
SELECT date '5874897-12-31';
SELECT date '5874898-01-01'; -- out of range
RESET datestyle;
--

View File

@ -143,6 +143,11 @@ INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC');
SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
-- Check behavior at the lower boundary of the timestamp range
SELECT '4714-11-24 00:00:00 BC'::timestamp;
SELECT '4714-11-23 23:59:59 BC'::timestamp; -- out of range
-- The upper boundary differs between integer and float timestamps, so no check
-- Demonstrate functions and operators
SELECT '' AS "48", d1 FROM TIMESTAMP_TBL
WHERE d1 > timestamp without time zone '1997-01-02';

View File

@ -162,6 +162,13 @@ SELECT 'Wed Jul 11 10:51:14 PST+03:00 2001'::timestamptz;
SELECT '' AS "64", d1 FROM TIMESTAMPTZ_TBL;
-- Check behavior at the lower boundary of the timestamp range
SELECT '4714-11-24 00:00:00+00 BC'::timestamptz;
SELECT '4714-11-23 16:00:00-08 BC'::timestamptz;
SELECT 'Sun Nov 23 16:00:00 4714 PST BC'::timestamptz;
SELECT '4714-11-23 23:59:59+00 BC'::timestamptz; -- out of range
-- The upper boundary differs between integer and float timestamps, so no check
-- Demonstrate functions and operators
SELECT '' AS "48", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 > timestamp with time zone '1997-01-02';