Reject combining "epoch" and "infinity" with other datetime fields.

Datetime input formerly accepted combinations such as
'1995-08-06 infinity', but this seems like a clear error.
Reject any combination of regular y/m/d/h/m/s fields with
these special tokens.

Joseph Koshakow, reviewed by Keisuke Kuroda and myself

Discussion: https://postgr.es/m/CAAvxfHdm8wwXwG_FFRaJ1nTHiMWb7YXS2YKCzCt8Q0a2ZoMcHg@mail.gmail.com
This commit is contained in:
Tom Lane 2023-03-09 16:49:03 -05:00
parent 27b62377b4
commit bcc704b524
3 changed files with 133 additions and 15 deletions

View File

@ -1431,8 +1431,17 @@ DecodeDateTime(char **field, int *ftype, int nf,
*tzp = 0;
break;
default:
case DTK_EPOCH:
case DTK_LATE:
case DTK_EARLY:
tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
*dtype = val;
/* caller ignores tm for these dtype codes */
break;
default:
elog(ERROR, "unrecognized RESERV datetime token: %d",
val);
}
break;
@ -1567,22 +1576,23 @@ DecodeDateTime(char **field, int *ftype, int nf,
fmask |= tmask;
} /* end loop over fields */
/* do final checking/adjustment of Y/M/D fields */
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
if (dterr)
return dterr;
/* handle AM/PM */
if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
return DTERR_FIELD_OVERFLOW;
if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
tm->tm_hour = 0;
else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
tm->tm_hour += HOURS_PER_DAY / 2;
/* do additional checking for full date specs... */
/* do additional checking for normal date specs (but not "infinity" etc) */
if (*dtype == DTK_DATE)
{
/* do final checking/adjustment of Y/M/D fields */
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
if (dterr)
return dterr;
/* handle AM/PM */
if (mer != HR24 && tm->tm_hour > HOURS_PER_DAY / 2)
return DTERR_FIELD_OVERFLOW;
if (mer == AM && tm->tm_hour == HOURS_PER_DAY / 2)
tm->tm_hour = 0;
else if (mer == PM && tm->tm_hour != HOURS_PER_DAY / 2)
tm->tm_hour += HOURS_PER_DAY / 2;
/* check for incomplete input */
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
{
if ((fmask & DTK_TIME_M) == DTK_TIME_M)

View File

@ -283,6 +283,91 @@ SELECT date 'J0' AS "Julian Epoch";
11-24-4714 BC
(1 row)
-- conflicting fields should throw errors
SELECT date '1995-08-06 epoch';
ERROR: invalid input syntax for type date: "1995-08-06 epoch"
LINE 1: SELECT date '1995-08-06 epoch';
^
SELECT date '1995-08-06 infinity';
ERROR: invalid input syntax for type date: "1995-08-06 infinity"
LINE 1: SELECT date '1995-08-06 infinity';
^
SELECT date '1995-08-06 -infinity';
ERROR: invalid input syntax for type date: "1995-08-06 -infinity"
LINE 1: SELECT date '1995-08-06 -infinity';
^
SELECT date 'today infinity';
ERROR: invalid input syntax for type date: "today infinity"
LINE 1: SELECT date 'today infinity';
^
SELECT date '-infinity infinity';
ERROR: invalid input syntax for type date: "-infinity infinity"
LINE 1: SELECT date '-infinity infinity';
^
SELECT timestamp '1995-08-06 epoch';
ERROR: invalid input syntax for type timestamp: "1995-08-06 epoch"
LINE 1: SELECT timestamp '1995-08-06 epoch';
^
SELECT timestamp '1995-08-06 infinity';
ERROR: invalid input syntax for type timestamp: "1995-08-06 infinity"
LINE 1: SELECT timestamp '1995-08-06 infinity';
^
SELECT timestamp '1995-08-06 -infinity';
ERROR: invalid input syntax for type timestamp: "1995-08-06 -infinity"
LINE 1: SELECT timestamp '1995-08-06 -infinity';
^
SELECT timestamp 'epoch 01:01:01';
ERROR: invalid input syntax for type timestamp: "epoch 01:01:01"
LINE 1: SELECT timestamp 'epoch 01:01:01';
^
SELECT timestamp 'infinity 01:01:01';
ERROR: invalid input syntax for type timestamp: "infinity 01:01:01"
LINE 1: SELECT timestamp 'infinity 01:01:01';
^
SELECT timestamp '-infinity 01:01:01';
ERROR: invalid input syntax for type timestamp: "-infinity 01:01:01"
LINE 1: SELECT timestamp '-infinity 01:01:01';
^
SELECT timestamp 'now epoch';
ERROR: invalid input syntax for type timestamp: "now epoch"
LINE 1: SELECT timestamp 'now epoch';
^
SELECT timestamp '-infinity infinity';
ERROR: invalid input syntax for type timestamp: "-infinity infinity"
LINE 1: SELECT timestamp '-infinity infinity';
^
SELECT timestamptz '1995-08-06 epoch';
ERROR: invalid input syntax for type timestamp with time zone: "1995-08-06 epoch"
LINE 1: SELECT timestamptz '1995-08-06 epoch';
^
SELECT timestamptz '1995-08-06 infinity';
ERROR: invalid input syntax for type timestamp with time zone: "1995-08-06 infinity"
LINE 1: SELECT timestamptz '1995-08-06 infinity';
^
SELECT timestamptz '1995-08-06 -infinity';
ERROR: invalid input syntax for type timestamp with time zone: "1995-08-06 -infinity"
LINE 1: SELECT timestamptz '1995-08-06 -infinity';
^
SELECT timestamptz 'epoch 01:01:01';
ERROR: invalid input syntax for type timestamp with time zone: "epoch 01:01:01"
LINE 1: SELECT timestamptz 'epoch 01:01:01';
^
SELECT timestamptz 'infinity 01:01:01';
ERROR: invalid input syntax for type timestamp with time zone: "infinity 01:01:01"
LINE 1: SELECT timestamptz 'infinity 01:01:01';
^
SELECT timestamptz '-infinity 01:01:01';
ERROR: invalid input syntax for type timestamp with time zone: "-infinity 01:01:01"
LINE 1: SELECT timestamptz '-infinity 01:01:01';
^
SELECT timestamptz 'now epoch';
ERROR: invalid input syntax for type timestamp with time zone: "now epoch"
LINE 1: SELECT timestamptz 'now epoch';
^
SELECT timestamptz '-infinity infinity';
ERROR: invalid input syntax for type timestamp with time zone: "-infinity infinity"
LINE 1: SELECT timestamptz '-infinity infinity';
^
--
-- date, time arithmetic
--

View File

@ -62,6 +62,29 @@ SET DateStyle = 'Postgres, MDY';
SELECT date 'J1520447' AS "Confucius' Birthday";
SELECT date 'J0' AS "Julian Epoch";
-- conflicting fields should throw errors
SELECT date '1995-08-06 epoch';
SELECT date '1995-08-06 infinity';
SELECT date '1995-08-06 -infinity';
SELECT date 'today infinity';
SELECT date '-infinity infinity';
SELECT timestamp '1995-08-06 epoch';
SELECT timestamp '1995-08-06 infinity';
SELECT timestamp '1995-08-06 -infinity';
SELECT timestamp 'epoch 01:01:01';
SELECT timestamp 'infinity 01:01:01';
SELECT timestamp '-infinity 01:01:01';
SELECT timestamp 'now epoch';
SELECT timestamp '-infinity infinity';
SELECT timestamptz '1995-08-06 epoch';
SELECT timestamptz '1995-08-06 infinity';
SELECT timestamptz '1995-08-06 -infinity';
SELECT timestamptz 'epoch 01:01:01';
SELECT timestamptz 'infinity 01:01:01';
SELECT timestamptz '-infinity 01:01:01';
SELECT timestamptz 'now epoch';
SELECT timestamptz '-infinity infinity';
--
-- date, time arithmetic
--