diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index fbe3c29ee1..a114ff3a04 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -5757,6 +5757,20 @@ generate_series_timestamp(PG_FUNCTION_ARGS) MemoryContext oldcontext; Interval interval_zero; + /* Reject infinities in start and stop values */ + if (TIMESTAMP_IS_NOBEGIN(start) || + TIMESTAMP_IS_NOEND(start)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("start value cannot be infinity"))); + if (TIMESTAMP_IS_NOBEGIN(finish) || + TIMESTAMP_IS_NOEND(finish)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("stop value cannot be infinity"))); + + /* Interval doesn't (currently) have infinity, so nothing to check */ + /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); @@ -5837,6 +5851,20 @@ generate_series_timestamptz(PG_FUNCTION_ARGS) MemoryContext oldcontext; Interval interval_zero; + /* Reject infinities in start and stop values */ + if (TIMESTAMP_IS_NOBEGIN(start) || + TIMESTAMP_IS_NOEND(start)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("start value cannot be infinity"))); + if (TIMESTAMP_IS_NOBEGIN(finish) || + TIMESTAMP_IS_NOEND(finish)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("stop value cannot be infinity"))); + + /* Interval doesn't (currently) have infinity, so nothing to check */ + /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out index 1a2d48cae9..d5ca6b76a4 100644 --- a/src/test/regress/expected/timestamp.out +++ b/src/test/regress/expected/timestamp.out @@ -2019,3 +2019,52 @@ SELECT make_timestamp(-44, 3, 15, 12, 30, 15); -- should fail select make_timestamp(0, 7, 15, 12, 30, 15); ERROR: date field value out of range: 0-07-15 +-- generate_series for timestamp +select * from generate_series('2020-01-01 00:00'::timestamp, + '2020-01-02 03:00'::timestamp, + '1 hour'::interval); + generate_series +-------------------------- + Wed Jan 01 00:00:00 2020 + Wed Jan 01 01:00:00 2020 + Wed Jan 01 02:00:00 2020 + Wed Jan 01 03:00:00 2020 + Wed Jan 01 04:00:00 2020 + Wed Jan 01 05:00:00 2020 + Wed Jan 01 06:00:00 2020 + Wed Jan 01 07:00:00 2020 + Wed Jan 01 08:00:00 2020 + Wed Jan 01 09:00:00 2020 + Wed Jan 01 10:00:00 2020 + Wed Jan 01 11:00:00 2020 + Wed Jan 01 12:00:00 2020 + Wed Jan 01 13:00:00 2020 + Wed Jan 01 14:00:00 2020 + Wed Jan 01 15:00:00 2020 + Wed Jan 01 16:00:00 2020 + Wed Jan 01 17:00:00 2020 + Wed Jan 01 18:00:00 2020 + Wed Jan 01 19:00:00 2020 + Wed Jan 01 20:00:00 2020 + Wed Jan 01 21:00:00 2020 + Wed Jan 01 22:00:00 2020 + Wed Jan 01 23:00:00 2020 + Thu Jan 02 00:00:00 2020 + Thu Jan 02 01:00:00 2020 + Thu Jan 02 02:00:00 2020 + Thu Jan 02 03:00:00 2020 +(28 rows) + +-- errors +select * from generate_series('-infinity'::timestamp, + '2020-01-02 03:00'::timestamp, + '1 hour'::interval); +ERROR: start value cannot be infinity +select * from generate_series('2020-01-01 00:00'::timestamp, + 'infinity'::timestamp, + '1 hour'::interval); +ERROR: stop value cannot be infinity +select * from generate_series('2020-01-01 00:00'::timestamp, + '2020-01-02 03:00'::timestamp, + '0 hour'::interval); +ERROR: step size cannot equal zero diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out index 990c4eddf1..f0624b71f2 100644 --- a/src/test/regress/expected/timestamptz.out +++ b/src/test/regress/expected/timestamptz.out @@ -2297,6 +2297,55 @@ SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT'); (1 row) RESET TimeZone; +-- generate_series for timestamptz +select * from generate_series('2020-01-01 00:00'::timestamptz, + '2020-01-02 03:00'::timestamptz, + '1 hour'::interval); + generate_series +------------------------------ + Wed Jan 01 00:00:00 2020 PST + Wed Jan 01 01:00:00 2020 PST + Wed Jan 01 02:00:00 2020 PST + Wed Jan 01 03:00:00 2020 PST + Wed Jan 01 04:00:00 2020 PST + Wed Jan 01 05:00:00 2020 PST + Wed Jan 01 06:00:00 2020 PST + Wed Jan 01 07:00:00 2020 PST + Wed Jan 01 08:00:00 2020 PST + Wed Jan 01 09:00:00 2020 PST + Wed Jan 01 10:00:00 2020 PST + Wed Jan 01 11:00:00 2020 PST + Wed Jan 01 12:00:00 2020 PST + Wed Jan 01 13:00:00 2020 PST + Wed Jan 01 14:00:00 2020 PST + Wed Jan 01 15:00:00 2020 PST + Wed Jan 01 16:00:00 2020 PST + Wed Jan 01 17:00:00 2020 PST + Wed Jan 01 18:00:00 2020 PST + Wed Jan 01 19:00:00 2020 PST + Wed Jan 01 20:00:00 2020 PST + Wed Jan 01 21:00:00 2020 PST + Wed Jan 01 22:00:00 2020 PST + Wed Jan 01 23:00:00 2020 PST + Thu Jan 02 00:00:00 2020 PST + Thu Jan 02 01:00:00 2020 PST + Thu Jan 02 02:00:00 2020 PST + Thu Jan 02 03:00:00 2020 PST +(28 rows) + +-- errors +select * from generate_series('-infinity'::timestamptz, + '2020-01-02 03:00'::timestamptz, + '1 hour'::interval); +ERROR: start value cannot be infinity +select * from generate_series('2020-01-01 00:00'::timestamptz, + 'infinity'::timestamptz, + '1 hour'::interval); +ERROR: stop value cannot be infinity +select * from generate_series('2020-01-01 00:00'::timestamptz, + '2020-01-02 03:00'::timestamptz, + '0 hour'::interval); +ERROR: step size cannot equal zero -- -- Test behavior with a dynamic (time-varying) timezone abbreviation. -- These tests rely on the knowledge that MSK (Europe/Moscow standard time) diff --git a/src/test/regress/sql/timestamp.sql b/src/test/regress/sql/timestamp.sql index e011e779ea..0778e5d7c0 100644 --- a/src/test/regress/sql/timestamp.sql +++ b/src/test/regress/sql/timestamp.sql @@ -370,3 +370,18 @@ SELECT make_timestamp(2014, 12, 28, 6, 30, 45.887); SELECT make_timestamp(-44, 3, 15, 12, 30, 15); -- should fail select make_timestamp(0, 7, 15, 12, 30, 15); + +-- generate_series for timestamp +select * from generate_series('2020-01-01 00:00'::timestamp, + '2020-01-02 03:00'::timestamp, + '1 hour'::interval); +-- errors +select * from generate_series('-infinity'::timestamp, + '2020-01-02 03:00'::timestamp, + '1 hour'::interval); +select * from generate_series('2020-01-01 00:00'::timestamp, + 'infinity'::timestamp, + '1 hour'::interval); +select * from generate_series('2020-01-01 00:00'::timestamp, + '2020-01-02 03:00'::timestamp, + '0 hour'::interval); diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql index b18821de53..b355fb8fe3 100644 --- a/src/test/regress/sql/timestamptz.sql +++ b/src/test/regress/sql/timestamptz.sql @@ -410,6 +410,21 @@ SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT'); RESET TimeZone; +-- generate_series for timestamptz +select * from generate_series('2020-01-01 00:00'::timestamptz, + '2020-01-02 03:00'::timestamptz, + '1 hour'::interval); +-- errors +select * from generate_series('-infinity'::timestamptz, + '2020-01-02 03:00'::timestamptz, + '1 hour'::interval); +select * from generate_series('2020-01-01 00:00'::timestamptz, + 'infinity'::timestamptz, + '1 hour'::interval); +select * from generate_series('2020-01-01 00:00'::timestamptz, + '2020-01-02 03:00'::timestamptz, + '0 hour'::interval); + -- -- Test behavior with a dynamic (time-varying) timezone abbreviation. -- These tests rely on the knowledge that MSK (Europe/Moscow standard time)