Tighten unit parsing in internal values
Interval values now generate an error when the user has multiple consecutive units or a unit without a value. Previously, it was possible to specify multiple units consecutively which is contrary to what the documentation allows, so it was possible to finish with confusing interval values. This is a follow-up of the work done in 165d581f146b. Author: Joseph Koshakow Reviewed-by: Jacob Champion, Gurjeet Singh, Reid Thompson Discussion: https://postgr.es/m/CAAvxfHd-yNO+XYnUxL=GaNZ1n+eE0V-oE0+-cC1jdjdU0KS3iw@mail.gmail.com
This commit is contained in:
parent
165d581f14
commit
617f9b7d4b
@ -3278,6 +3278,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||||||
{
|
{
|
||||||
bool force_negative = false;
|
bool force_negative = false;
|
||||||
bool is_before = false;
|
bool is_before = false;
|
||||||
|
bool parsing_unit_val = false;
|
||||||
char *cp;
|
char *cp;
|
||||||
int fmask = 0,
|
int fmask = 0,
|
||||||
tmask,
|
tmask,
|
||||||
@ -3336,6 +3337,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||||||
itm_in->tm_usec > 0)
|
itm_in->tm_usec > 0)
|
||||||
itm_in->tm_usec = -itm_in->tm_usec;
|
itm_in->tm_usec = -itm_in->tm_usec;
|
||||||
type = DTK_DAY;
|
type = DTK_DAY;
|
||||||
|
parsing_unit_val = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DTK_TZ:
|
case DTK_TZ:
|
||||||
@ -3373,6 +3375,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||||||
* are reading right to left.
|
* are reading right to left.
|
||||||
*/
|
*/
|
||||||
type = DTK_DAY;
|
type = DTK_DAY;
|
||||||
|
parsing_unit_val = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3562,10 +3565,14 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||||||
default:
|
default:
|
||||||
return DTERR_BAD_FORMAT;
|
return DTERR_BAD_FORMAT;
|
||||||
}
|
}
|
||||||
|
parsing_unit_val = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DTK_STRING:
|
case DTK_STRING:
|
||||||
case DTK_SPECIAL:
|
case DTK_SPECIAL:
|
||||||
|
/* reject consecutive unhandled units */
|
||||||
|
if (parsing_unit_val)
|
||||||
|
return DTERR_BAD_FORMAT;
|
||||||
type = DecodeUnits(i, field[i], &uval);
|
type = DecodeUnits(i, field[i], &uval);
|
||||||
if (type == IGNORE_DTF)
|
if (type == IGNORE_DTF)
|
||||||
continue;
|
continue;
|
||||||
@ -3575,6 +3582,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||||||
{
|
{
|
||||||
case UNITS:
|
case UNITS:
|
||||||
type = uval;
|
type = uval;
|
||||||
|
parsing_unit_val = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AGO:
|
case AGO:
|
||||||
@ -3607,6 +3615,10 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
|
|||||||
if (fmask == 0)
|
if (fmask == 0)
|
||||||
return DTERR_BAD_FORMAT;
|
return DTERR_BAD_FORMAT;
|
||||||
|
|
||||||
|
/* reject if unit appeared and was never handled */
|
||||||
|
if (parsing_unit_val)
|
||||||
|
return DTERR_BAD_FORMAT;
|
||||||
|
|
||||||
/* finally, AGO negates everything */
|
/* finally, AGO negates everything */
|
||||||
if (is_before)
|
if (is_before)
|
||||||
{
|
{
|
||||||
|
@ -1796,3 +1796,12 @@ SELECT INTERVAL '2 minutes ago 5 days';
|
|||||||
ERROR: invalid input syntax for type interval: "2 minutes ago 5 days"
|
ERROR: invalid input syntax for type interval: "2 minutes ago 5 days"
|
||||||
LINE 1: SELECT INTERVAL '2 minutes ago 5 days';
|
LINE 1: SELECT INTERVAL '2 minutes ago 5 days';
|
||||||
^
|
^
|
||||||
|
-- consecutive and dangling units are not allowed.
|
||||||
|
SELECT INTERVAL 'hour 5 months';
|
||||||
|
ERROR: invalid input syntax for type interval: "hour 5 months"
|
||||||
|
LINE 1: SELECT INTERVAL 'hour 5 months';
|
||||||
|
^
|
||||||
|
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';
|
||||||
|
^
|
||||||
|
@ -586,3 +586,7 @@ SELECT extract(epoch from interval '1000000000 days');
|
|||||||
-- "ago" can only appear once at the end of an interval.
|
-- "ago" can only appear once at the end of an interval.
|
||||||
SELECT INTERVAL '42 days 2 seconds ago ago';
|
SELECT INTERVAL '42 days 2 seconds ago ago';
|
||||||
SELECT INTERVAL '2 minutes ago 5 days';
|
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';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user