diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 1c2c39b2e27..26c6742e8b1 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -2873,19 +2873,18 @@ DecodeInterval(char **field, int *ftype, int nf, int range, case DTK_TZ: /* - * Timezone is a token with a leading sign character and at + * Timezone means a token with a leading sign character and at * least one digit; there could be ':', '.', '-' embedded in * it as well. */ Assert(*field[i] == '-' || *field[i] == '+'); /* - * Try for hh:mm or hh:mm:ss. If not, fall through to - * DTK_NUMBER case, which can handle signed float numbers and - * signed year-month values. + * Check for signed hh:mm or hh:mm:ss. If so, process exactly + * like DTK_TIME case above, plus handling the sign. */ if (strchr(field[i] + 1, ':') != NULL && - DecodeTime(field[i] + 1, fmask, INTERVAL_FULL_RANGE, + DecodeTime(field[i] + 1, fmask, range, &tmask, tm, fsec) == 0) { if (*field[i] == '-') @@ -2903,9 +2902,14 @@ DecodeInterval(char **field, int *ftype, int nf, int range, * are reading right to left. */ type = DTK_DAY; - tmask = DTK_M(TZ); break; } + + /* + * Otherwise, fall through to DTK_NUMBER case, which can + * handle signed float numbers and signed year-month values. + */ + /* FALL THROUGH */ case DTK_DATE: diff --git a/src/test/regress/expected/interval.out b/src/test/regress/expected/interval.out index e7e21813332..3bf221187bc 100644 --- a/src/test/regress/expected/interval.out +++ b/src/test/regress/expected/interval.out @@ -545,6 +545,30 @@ SELECT interval '1 2:03:04' minute to second; 1 day 02:03:04 (1 row) +SELECT interval '1 +2:03' minute to second; + interval +---------------- + 1 day 00:02:03 +(1 row) + +SELECT interval '1 +2:03:04' minute to second; + interval +---------------- + 1 day 02:03:04 +(1 row) + +SELECT interval '1 -2:03' minute to second; + interval +----------------- + 1 day -00:02:03 +(1 row) + +SELECT interval '1 -2:03:04' minute to second; + interval +----------------- + 1 day -02:03:04 +(1 row) + SELECT interval '123 11' day to hour; -- ok interval ------------------- @@ -559,6 +583,10 @@ SELECT interval '123 11'; -- not ok, too ambiguous ERROR: invalid input syntax for type interval: "123 11" LINE 1: SELECT interval '123 11'; ^ +SELECT interval '123 2:03 -2:04'; -- not ok, redundant hh:mm fields +ERROR: invalid input syntax for type interval: "123 2:03 -2:04" +LINE 1: SELECT interval '123 2:03 -2:04'; + ^ -- test syntaxes for restricted precision SELECT interval(0) '1 day 01:23:45.6789'; interval diff --git a/src/test/regress/sql/interval.sql b/src/test/regress/sql/interval.sql index 9da2dc63e87..f1da4c29117 100644 --- a/src/test/regress/sql/interval.sql +++ b/src/test/regress/sql/interval.sql @@ -165,9 +165,14 @@ SELECT interval '1 2:03:04' hour to second; SELECT interval '1 2' minute to second; SELECT interval '1 2:03' minute to second; SELECT interval '1 2:03:04' minute to second; +SELECT interval '1 +2:03' minute to second; +SELECT interval '1 +2:03:04' minute to second; +SELECT interval '1 -2:03' minute to second; +SELECT interval '1 -2:03:04' minute to second; SELECT interval '123 11' day to hour; -- ok SELECT interval '123 11' day; -- not ok SELECT interval '123 11'; -- not ok, too ambiguous +SELECT interval '123 2:03 -2:04'; -- not ok, redundant hh:mm fields -- test syntaxes for restricted precision SELECT interval(0) '1 day 01:23:45.6789';