From 69d8e9779b2016c4a96262a24c22e10eccdfea0c Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Wed, 13 Sep 2023 12:43:49 +0530 Subject: [PATCH v25 3/7] Introduce 'infinity' interval specification in DecodeInterval() This reverts commit d6d1430f404386162831bc32906ad174b2007776 since RESERVE is required to support infinite intervals. 'infinity' is saved as a RESERVE in datetktbl[], thus required to parse 'infinity'::interval. Infinte interval specification i.e. "+infinity", "-infinity" or "infinity" does not require anything other that one of the three strings. Fix DecodeInterval() to disallow anything else. "ago" may be used to revrse the sign of infinity specification like how ago reverts the sign of finite intervals. But that is not as intuitive as it is with finite intervals. Hence disallows "infinity ago" as well. Ashutosh Bapat --- src/backend/utils/adt/datetime.c | 24 ++++++++++++++++ src/test/regress/expected/interval.out | 39 ++++++++++++++++++++++++++ src/test/regress/sql/interval.sql | 14 +++++++++ 3 files changed, 77 insertions(+) diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index ea2bc65f50..73dadb747c 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -3271,6 +3271,9 @@ ClearPgItmIn(struct pg_itm_in *itm_in) * * Allow ISO-style time span, with implicit units on number of days * preceding an hh:mm:ss field. - thomas 1998-04-30 + * + * itm_in remains undefined for infinite interval values for which dtype alone + * suffices. */ int DecodeInterval(char **field, int *ftype, int nf, int range, @@ -3599,6 +3602,27 @@ DecodeInterval(char **field, int *ftype, int nf, int range, type = uval; break; + case RESERV: + tmask = (DTK_DATE_M | DTK_TIME_M); + + /* + * Only reserved words corresponding to infinite + * intervals are accepted. + */ + if (uval != DTK_LATE && uval != DTK_EARLY) + return DTERR_BAD_FORMAT; + + /* + * infinity can not be followed by anything else. We + * could allow "ago" to reverse the sign of infinity + * but that signed infinity is more intuitive. + */ + if (i != nf - 1) + return DTERR_BAD_FORMAT; + + *dtype = uval; + break; + default: return DTERR_BAD_FORMAT; } diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index 5011fc4815..135d683285 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -2264,3 +2264,42 @@ SELECT INTERVAL '1 year months days 5 hours'; ERROR: invalid input syntax for type interval: "1 year months days 5 hours" LINE 1: SELECT INTERVAL '1 year months days 5 hours'; ^ +-- unacceptable reserved words in interval. Only "infinity", "+infinity" and +-- "-infinity" are allowed. +SELECT INTERVAL 'now'; +ERROR: invalid input syntax for type interval: "now" +LINE 1: SELECT INTERVAL 'now'; + ^ +SELECT INTERVAL 'today'; +ERROR: invalid input syntax for type interval: "today" +LINE 1: SELECT INTERVAL 'today'; + ^ +SELECT INTERVAL 'tomorrow'; +ERROR: invalid input syntax for type interval: "tomorrow" +LINE 1: SELECT INTERVAL 'tomorrow'; + ^ +SELECT INTERVAL 'allballs'; +ERROR: invalid input syntax for type interval: "allballs" +LINE 1: SELECT INTERVAL 'allballs'; + ^ +SELECT INTERVAL 'epoch'; +ERROR: invalid input syntax for type interval: "epoch" +LINE 1: SELECT INTERVAL 'epoch'; + ^ +SELECT INTERVAL 'yesterday'; +ERROR: invalid input syntax for type interval: "yesterday" +LINE 1: SELECT INTERVAL 'yesterday'; + ^ +-- infinity specification should be the only thing +SELECT INTERVAL 'infinity years'; +ERROR: invalid input syntax for type interval: "infinity years" +LINE 1: SELECT INTERVAL 'infinity years'; + ^ +SELECT INTERVAL 'infinity ago'; +ERROR: invalid input syntax for type interval: "infinity ago" +LINE 1: SELECT INTERVAL 'infinity ago'; + ^ +SELECT INTERVAL '+infinity -infinity'; +ERROR: invalid input syntax for type interval: "+infinity -infinity" +LINE 1: SELECT INTERVAL '+infinity -infinity'; + ^ diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql index 590e1000bd..912803a1b0 100644 --- a/src/test/regress/sql/interval.sql +++ b/src/test/regress/sql/interval.sql @@ -745,3 +745,17 @@ SELECT INTERVAL '2 minutes ago 5 days'; -- consecutive and dangling units are not allowed. SELECT INTERVAL 'hour 5 months'; SELECT INTERVAL '1 year months days 5 hours'; + +-- unacceptable reserved words in interval. Only "infinity", "+infinity" and +-- "-infinity" are allowed. +SELECT INTERVAL 'now'; +SELECT INTERVAL 'today'; +SELECT INTERVAL 'tomorrow'; +SELECT INTERVAL 'allballs'; +SELECT INTERVAL 'epoch'; +SELECT INTERVAL 'yesterday'; + +-- infinity specification should be the only thing +SELECT INTERVAL 'infinity years'; +SELECT INTERVAL 'infinity ago'; +SELECT INTERVAL '+infinity -infinity'; -- 2.35.3