aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/datetime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/datetime.c')
-rw-r--r--src/backend/utils/adt/datetime.c221
1 files changed, 29 insertions, 192 deletions
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index a7558d39a0e..516ee9c154b 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -983,7 +983,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
int fmask = 0,
tmask,
type;
- int ptype = 0; /* "prefix type" for ISO y2001m02d04 format */
+ int ptype = 0; /* "prefix type" for ISO and Julian formats */
int i;
int val;
int dterr;
@@ -1071,6 +1071,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
{
char *cp;
+ /*
+ * Allow a preceding "t" field, but no other units.
+ */
if (ptype != 0)
{
/* Sanity check; should not fail this test */
@@ -1175,8 +1178,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
case DTK_NUMBER:
/*
- * Was this an "ISO date" with embedded field labels? An
- * example is "y2001m02d04" - thomas 2001-02-04
+ * Deal with cases where previous field labeled this one
*/
if (ptype != 0)
{
@@ -1187,85 +1189,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
value = strtoint(field[i], &cp, 10);
if (errno == ERANGE)
return DTERR_FIELD_OVERFLOW;
-
- /*
- * only a few kinds are allowed to have an embedded
- * decimal
- */
- if (*cp == '.')
- switch (ptype)
- {
- case DTK_JULIAN:
- case DTK_TIME:
- case DTK_SECOND:
- break;
- default:
- return DTERR_BAD_FORMAT;
- break;
- }
- else if (*cp != '\0')
+ if (*cp != '.' && *cp != '\0')
return DTERR_BAD_FORMAT;
switch (ptype)
{
- case DTK_YEAR:
- tm->tm_year = value;
- tmask = DTK_M(YEAR);
- break;
-
- case DTK_MONTH:
-
- /*
- * already have a month and hour? then assume
- * minutes
- */
- if ((fmask & DTK_M(MONTH)) != 0 &&
- (fmask & DTK_M(HOUR)) != 0)
- {
- tm->tm_min = value;
- tmask = DTK_M(MINUTE);
- }
- else
- {
- tm->tm_mon = value;
- tmask = DTK_M(MONTH);
- }
- break;
-
- case DTK_DAY:
- tm->tm_mday = value;
- tmask = DTK_M(DAY);
- break;
-
- case DTK_HOUR:
- tm->tm_hour = value;
- tmask = DTK_M(HOUR);
- break;
-
- case DTK_MINUTE:
- tm->tm_min = value;
- tmask = DTK_M(MINUTE);
- break;
-
- case DTK_SECOND:
- tm->tm_sec = value;
- tmask = DTK_M(SECOND);
- if (*cp == '.')
- {
- dterr = ParseFractionalSecond(cp, fsec);
- if (dterr)
- return dterr;
- tmask = DTK_ALL_SECS_M;
- }
- break;
-
- case DTK_TZ:
- tmask = DTK_M(TZ);
- dterr = DecodeTimezone(field[i], tzp);
- if (dterr)
- return dterr;
- break;
-
case DTK_JULIAN:
/* previous field was a label for "julian date" */
if (value < 0)
@@ -1519,6 +1447,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
case UNITS:
tmask = 0;
+ /* reject consecutive unhandled units */
+ if (ptype != 0)
+ return DTERR_BAD_FORMAT;
ptype = val;
break;
@@ -1534,18 +1465,9 @@ DecodeDateTime(char **field, int *ftype, int nf,
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
return DTERR_BAD_FORMAT;
- /***
- * We will need one of the following fields:
- * DTK_NUMBER should be hhmmss.fff
- * DTK_TIME should be hh:mm:ss.fff
- * DTK_DATE should be hhmmss-zz
- ***/
- if (i >= nf - 1 ||
- (ftype[i + 1] != DTK_NUMBER &&
- ftype[i + 1] != DTK_TIME &&
- ftype[i + 1] != DTK_DATE))
+ /* reject consecutive unhandled units */
+ if (ptype != 0)
return DTERR_BAD_FORMAT;
-
ptype = val;
break;
@@ -1576,6 +1498,10 @@ DecodeDateTime(char **field, int *ftype, int nf,
fmask |= tmask;
} /* end loop over fields */
+ /* reject if prefix type appeared and was never handled */
+ if (ptype != 0)
+ return DTERR_BAD_FORMAT;
+
/* do additional checking for normal date specs (but not "infinity" etc) */
if (*dtype == DTK_DATE)
{
@@ -1943,7 +1869,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
int fmask = 0,
tmask,
type;
- int ptype = 0; /* "prefix type" for ISO h04mm05s06 format */
+ int ptype = 0; /* "prefix type" for ISO and Julian formats */
int i;
int val;
int dterr;
@@ -2070,112 +1996,26 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
case DTK_NUMBER:
/*
- * Was this an "ISO time" with embedded field labels? An
- * example is "h04mm05s06" - thomas 2001-02-04
+ * Deal with cases where previous field labeled this one
*/
if (ptype != 0)
{
char *cp;
int value;
- /* Only accept a date under limited circumstances */
- switch (ptype)
- {
- case DTK_JULIAN:
- case DTK_YEAR:
- case DTK_MONTH:
- case DTK_DAY:
- if (tzp == NULL)
- return DTERR_BAD_FORMAT;
- default:
- break;
- }
-
errno = 0;
value = strtoint(field[i], &cp, 10);
if (errno == ERANGE)
return DTERR_FIELD_OVERFLOW;
-
- /*
- * only a few kinds are allowed to have an embedded
- * decimal
- */
- if (*cp == '.')
- switch (ptype)
- {
- case DTK_JULIAN:
- case DTK_TIME:
- case DTK_SECOND:
- break;
- default:
- return DTERR_BAD_FORMAT;
- break;
- }
- else if (*cp != '\0')
+ if (*cp != '.' && *cp != '\0')
return DTERR_BAD_FORMAT;
switch (ptype)
{
- case DTK_YEAR:
- tm->tm_year = value;
- tmask = DTK_M(YEAR);
- break;
-
- case DTK_MONTH:
-
- /*
- * already have a month and hour? then assume
- * minutes
- */
- if ((fmask & DTK_M(MONTH)) != 0 &&
- (fmask & DTK_M(HOUR)) != 0)
- {
- tm->tm_min = value;
- tmask = DTK_M(MINUTE);
- }
- else
- {
- tm->tm_mon = value;
- tmask = DTK_M(MONTH);
- }
- break;
-
- case DTK_DAY:
- tm->tm_mday = value;
- tmask = DTK_M(DAY);
- break;
-
- case DTK_HOUR:
- tm->tm_hour = value;
- tmask = DTK_M(HOUR);
- break;
-
- case DTK_MINUTE:
- tm->tm_min = value;
- tmask = DTK_M(MINUTE);
- break;
-
- case DTK_SECOND:
- tm->tm_sec = value;
- tmask = DTK_M(SECOND);
- if (*cp == '.')
- {
- dterr = ParseFractionalSecond(cp, fsec);
- if (dterr)
- return dterr;
- tmask = DTK_ALL_SECS_M;
- }
- break;
-
- case DTK_TZ:
- tmask = DTK_M(TZ);
- dterr = DecodeTimezone(field[i], tzp);
- if (dterr)
- return dterr;
- break;
-
case DTK_JULIAN:
/* previous field was a label for "julian date" */
+ if (tzp == NULL)
+ return DTERR_BAD_FORMAT;
if (value < 0)
return DTERR_FIELD_OVERFLOW;
tmask = DTK_DATE_M;
@@ -2378,24 +2218,17 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
case UNITS:
tmask = 0;
+ /* reject consecutive unhandled units */
+ if (ptype != 0)
+ return DTERR_BAD_FORMAT;
ptype = val;
break;
case ISOTIME:
tmask = 0;
-
- /***
- * We will need one of the following fields:
- * DTK_NUMBER should be hhmmss.fff
- * DTK_TIME should be hh:mm:ss.fff
- * DTK_DATE should be hhmmss-zz
- ***/
- if (i >= nf - 1 ||
- (ftype[i + 1] != DTK_NUMBER &&
- ftype[i + 1] != DTK_TIME &&
- ftype[i + 1] != DTK_DATE))
+ /* reject consecutive unhandled units */
+ if (ptype != 0)
return DTERR_BAD_FORMAT;
-
ptype = val;
break;
@@ -2426,6 +2259,10 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
fmask |= tmask;
} /* end loop over fields */
+ /* reject if prefix type appeared and was never handled */
+ if (ptype != 0)
+ return DTERR_BAD_FORMAT;
+
/* do final checking/adjustment of Y/M/D fields */
dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
if (dterr)