Disallow infinite endpoints in generate_series() for timestamps.

Such cases will lead to infinite loops, so they're of no practical
value.  The numeric variant of generate_series() already threw error
for this, so borrow its message wording.

Per report from Richard Wesley.  Back-patch to all supported branches.

Discussion: https://postgr.es/m/91B44E7B-68D5-448F-95C8-B4B3B0F5DEAF@duckdblabs.com
This commit is contained in:
Tom Lane 2022-04-20 18:08:15 -04:00
parent 4a66300acd
commit e346329470
5 changed files with 156 additions and 0 deletions

View File

@ -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();

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)