Skip to content

Commit eafdf9d

Browse files
committed
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
1 parent d2d3547 commit eafdf9d

File tree

5 files changed

+156
-0
lines changed

5 files changed

+156
-0
lines changed

src/backend/utils/adt/timestamp.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5778,6 +5778,20 @@ generate_series_timestamp(PG_FUNCTION_ARGS)
57785778
MemoryContext oldcontext;
57795779
Interval interval_zero;
57805780

5781+
/* Reject infinities in start and stop values */
5782+
if (TIMESTAMP_IS_NOBEGIN(start) ||
5783+
TIMESTAMP_IS_NOEND(start))
5784+
ereport(ERROR,
5785+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5786+
errmsg("start value cannot be infinity")));
5787+
if (TIMESTAMP_IS_NOBEGIN(finish) ||
5788+
TIMESTAMP_IS_NOEND(finish))
5789+
ereport(ERROR,
5790+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5791+
errmsg("stop value cannot be infinity")));
5792+
5793+
/* Interval doesn't (currently) have infinity, so nothing to check */
5794+
57815795
/* create a function context for cross-call persistence */
57825796
funcctx = SRF_FIRSTCALL_INIT();
57835797

@@ -5858,6 +5872,20 @@ generate_series_timestamptz(PG_FUNCTION_ARGS)
58585872
MemoryContext oldcontext;
58595873
Interval interval_zero;
58605874

5875+
/* Reject infinities in start and stop values */
5876+
if (TIMESTAMP_IS_NOBEGIN(start) ||
5877+
TIMESTAMP_IS_NOEND(start))
5878+
ereport(ERROR,
5879+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5880+
errmsg("start value cannot be infinity")));
5881+
if (TIMESTAMP_IS_NOBEGIN(finish) ||
5882+
TIMESTAMP_IS_NOEND(finish))
5883+
ereport(ERROR,
5884+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5885+
errmsg("stop value cannot be infinity")));
5886+
5887+
/* Interval doesn't (currently) have infinity, so nothing to check */
5888+
58615889
/* create a function context for cross-call persistence */
58625890
funcctx = SRF_FIRSTCALL_INIT();
58635891

src/test/regress/expected/timestamp.out

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,3 +2019,52 @@ SELECT make_timestamp(-44, 3, 15, 12, 30, 15);
20192019
-- should fail
20202020
select make_timestamp(0, 7, 15, 12, 30, 15);
20212021
ERROR: date field value out of range: 0-07-15
2022+
-- generate_series for timestamp
2023+
select * from generate_series('2020-01-01 00:00'::timestamp,
2024+
'2020-01-02 03:00'::timestamp,
2025+
'1 hour'::interval);
2026+
generate_series
2027+
--------------------------
2028+
Wed Jan 01 00:00:00 2020
2029+
Wed Jan 01 01:00:00 2020
2030+
Wed Jan 01 02:00:00 2020
2031+
Wed Jan 01 03:00:00 2020
2032+
Wed Jan 01 04:00:00 2020
2033+
Wed Jan 01 05:00:00 2020
2034+
Wed Jan 01 06:00:00 2020
2035+
Wed Jan 01 07:00:00 2020
2036+
Wed Jan 01 08:00:00 2020
2037+
Wed Jan 01 09:00:00 2020
2038+
Wed Jan 01 10:00:00 2020
2039+
Wed Jan 01 11:00:00 2020
2040+
Wed Jan 01 12:00:00 2020
2041+
Wed Jan 01 13:00:00 2020
2042+
Wed Jan 01 14:00:00 2020
2043+
Wed Jan 01 15:00:00 2020
2044+
Wed Jan 01 16:00:00 2020
2045+
Wed Jan 01 17:00:00 2020
2046+
Wed Jan 01 18:00:00 2020
2047+
Wed Jan 01 19:00:00 2020
2048+
Wed Jan 01 20:00:00 2020
2049+
Wed Jan 01 21:00:00 2020
2050+
Wed Jan 01 22:00:00 2020
2051+
Wed Jan 01 23:00:00 2020
2052+
Thu Jan 02 00:00:00 2020
2053+
Thu Jan 02 01:00:00 2020
2054+
Thu Jan 02 02:00:00 2020
2055+
Thu Jan 02 03:00:00 2020
2056+
(28 rows)
2057+
2058+
-- errors
2059+
select * from generate_series('-infinity'::timestamp,
2060+
'2020-01-02 03:00'::timestamp,
2061+
'1 hour'::interval);
2062+
ERROR: start value cannot be infinity
2063+
select * from generate_series('2020-01-01 00:00'::timestamp,
2064+
'infinity'::timestamp,
2065+
'1 hour'::interval);
2066+
ERROR: stop value cannot be infinity
2067+
select * from generate_series('2020-01-01 00:00'::timestamp,
2068+
'2020-01-02 03:00'::timestamp,
2069+
'0 hour'::interval);
2070+
ERROR: step size cannot equal zero

src/test/regress/expected/timestamptz.out

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2362,6 +2362,55 @@ SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT');
23622362
(1 row)
23632363

23642364
RESET TimeZone;
2365+
-- generate_series for timestamptz
2366+
select * from generate_series('2020-01-01 00:00'::timestamptz,
2367+
'2020-01-02 03:00'::timestamptz,
2368+
'1 hour'::interval);
2369+
generate_series
2370+
------------------------------
2371+
Wed Jan 01 00:00:00 2020 PST
2372+
Wed Jan 01 01:00:00 2020 PST
2373+
Wed Jan 01 02:00:00 2020 PST
2374+
Wed Jan 01 03:00:00 2020 PST
2375+
Wed Jan 01 04:00:00 2020 PST
2376+
Wed Jan 01 05:00:00 2020 PST
2377+
Wed Jan 01 06:00:00 2020 PST
2378+
Wed Jan 01 07:00:00 2020 PST
2379+
Wed Jan 01 08:00:00 2020 PST
2380+
Wed Jan 01 09:00:00 2020 PST
2381+
Wed Jan 01 10:00:00 2020 PST
2382+
Wed Jan 01 11:00:00 2020 PST
2383+
Wed Jan 01 12:00:00 2020 PST
2384+
Wed Jan 01 13:00:00 2020 PST
2385+
Wed Jan 01 14:00:00 2020 PST
2386+
Wed Jan 01 15:00:00 2020 PST
2387+
Wed Jan 01 16:00:00 2020 PST
2388+
Wed Jan 01 17:00:00 2020 PST
2389+
Wed Jan 01 18:00:00 2020 PST
2390+
Wed Jan 01 19:00:00 2020 PST
2391+
Wed Jan 01 20:00:00 2020 PST
2392+
Wed Jan 01 21:00:00 2020 PST
2393+
Wed Jan 01 22:00:00 2020 PST
2394+
Wed Jan 01 23:00:00 2020 PST
2395+
Thu Jan 02 00:00:00 2020 PST
2396+
Thu Jan 02 01:00:00 2020 PST
2397+
Thu Jan 02 02:00:00 2020 PST
2398+
Thu Jan 02 03:00:00 2020 PST
2399+
(28 rows)
2400+
2401+
-- errors
2402+
select * from generate_series('-infinity'::timestamptz,
2403+
'2020-01-02 03:00'::timestamptz,
2404+
'1 hour'::interval);
2405+
ERROR: start value cannot be infinity
2406+
select * from generate_series('2020-01-01 00:00'::timestamptz,
2407+
'infinity'::timestamptz,
2408+
'1 hour'::interval);
2409+
ERROR: stop value cannot be infinity
2410+
select * from generate_series('2020-01-01 00:00'::timestamptz,
2411+
'2020-01-02 03:00'::timestamptz,
2412+
'0 hour'::interval);
2413+
ERROR: step size cannot equal zero
23652414
--
23662415
-- Test behavior with a dynamic (time-varying) timezone abbreviation.
23672416
-- These tests rely on the knowledge that MSK (Europe/Moscow standard time)

src/test/regress/sql/timestamp.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,18 @@ SELECT make_timestamp(2014, 12, 28, 6, 30, 45.887);
370370
SELECT make_timestamp(-44, 3, 15, 12, 30, 15);
371371
-- should fail
372372
select make_timestamp(0, 7, 15, 12, 30, 15);
373+
374+
-- generate_series for timestamp
375+
select * from generate_series('2020-01-01 00:00'::timestamp,
376+
'2020-01-02 03:00'::timestamp,
377+
'1 hour'::interval);
378+
-- errors
379+
select * from generate_series('-infinity'::timestamp,
380+
'2020-01-02 03:00'::timestamp,
381+
'1 hour'::interval);
382+
select * from generate_series('2020-01-01 00:00'::timestamp,
383+
'infinity'::timestamp,
384+
'1 hour'::interval);
385+
select * from generate_series('2020-01-01 00:00'::timestamp,
386+
'2020-01-02 03:00'::timestamp,
387+
'0 hour'::interval);

src/test/regress/sql/timestamptz.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,21 @@ SELECT make_timestamptz(2014, 12, 10, 10, 10, 10, 'PST8PDT');
432432

433433
RESET TimeZone;
434434

435+
-- generate_series for timestamptz
436+
select * from generate_series('2020-01-01 00:00'::timestamptz,
437+
'2020-01-02 03:00'::timestamptz,
438+
'1 hour'::interval);
439+
-- errors
440+
select * from generate_series('-infinity'::timestamptz,
441+
'2020-01-02 03:00'::timestamptz,
442+
'1 hour'::interval);
443+
select * from generate_series('2020-01-01 00:00'::timestamptz,
444+
'infinity'::timestamptz,
445+
'1 hour'::interval);
446+
select * from generate_series('2020-01-01 00:00'::timestamptz,
447+
'2020-01-02 03:00'::timestamptz,
448+
'0 hour'::interval);
449+
435450
--
436451
-- Test behavior with a dynamic (time-varying) timezone abbreviation.
437452
-- These tests rely on the knowledge that MSK (Europe/Moscow standard time)

0 commit comments

Comments
 (0)