diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 3e7c77ee48..a6161198f8 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -5392,6 +5392,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(); @@ -5473,6 +5487,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 3025d8431e..d6f7a91ffd 100644 --- a/src/test/regress/expected/timestamp.out +++ b/src/test/regress/expected/timestamp.out @@ -1731,3 +1731,52 @@ SELECT make_timestamp(2014,12,28,6,30,45.887); Sun Dec 28 06:30:45.887 2014 (1 row) +-- 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 78d9e39897..8a905aba8d 100644 --- a/src/test/regress/expected/timestamptz.out +++ b/src/test/regress/expected/timestamptz.out @@ -2091,6 +2091,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 55380c59e7..947dbfc325 100644 --- a/src/test/regress/sql/timestamp.sql +++ b/src/test/regress/sql/timestamp.sql @@ -239,3 +239,18 @@ SELECT i, -- timestamp numeric fields constructor SELECT make_timestamp(2014,12,28,6,30,45.887); + +-- 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 a93bec5b4a..e67d33fb5f 100644 --- a/src/test/regress/sql/timestamptz.sql +++ b/src/test/regress/sql/timestamptz.sql @@ -334,6 +334,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)