From bb51c8162c6ae84d94e3ab42de55fa6198aea2fe Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Wed, 13 Sep 2023 12:43:49 +0530 Subject: [PATCH 4/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 5fed7e3dd1..b25bd6a551 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -3254,6 +3254,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, @@ -3582,6 +3585,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 a4630d17ef..d61b07f38e 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -2244,3 +2244,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 023cf3761a..183ddfaf31 100644 --- a/src/test/regress/sql/interval.sql +++ b/src/test/regress/sql/interval.sql @@ -735,3 +735,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.25.1