Move DTK_ISODOW DTK_DOW and DTK_DOY to be type UNITS rather than
authorGreg Stark <stark@mit.edu>
Sun, 6 Sep 2015 01:04:37 +0000 (02:04 +0100)
committerGreg Stark <stark@mit.edu>
Sun, 6 Sep 2015 02:58:27 +0000 (03:58 +0100)
RESERV. RESERV is meant for tokens like "now" and having them in that
category throws errors like these when used as an input date:

stark=# SELECT 'doy'::timestamptz;
ERROR:  unexpected dtype 33 while parsing timestamptz "doy"
LINE 1: SELECT 'doy'::timestamptz;
               ^
stark=# SELECT 'dow'::timestamptz;
ERROR:  unexpected dtype 32 while parsing timestamptz "dow"
LINE 1: SELECT 'dow'::timestamptz;
               ^

Found by LLVM's Libfuzzer

src/backend/utils/adt/datetime.c
src/backend/utils/adt/timestamp.c

index c5c8bb0854061b39f2ade4e333cb1a063e6a071c..0dbef473aa8a3f866862dda221eab917471814b4 100644 (file)
@@ -106,8 +106,8 @@ static const datetkn datetktbl[] = {
    {"d", UNITS, DTK_DAY},      /* "day of month" for ISO input */
    {"dec", MONTH, 12},
    {"december", MONTH, 12},
-   {"dow", RESERV, DTK_DOW},   /* day of week */
-   {"doy", RESERV, DTK_DOY},   /* day of year */
+   {"dow", UNITS, DTK_DOW},    /* day of week */
+   {"doy", UNITS, DTK_DOY},    /* day of year */
    {"dst", DTZMOD, SECS_PER_HOUR},
    {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
    {"feb", MONTH, 2},
@@ -117,7 +117,7 @@ static const datetkn datetktbl[] = {
    {"h", UNITS, DTK_HOUR},     /* "hour" */
    {LATE, RESERV, DTK_LATE},   /* "infinity" reserved for "late time" */
    {INVALID, RESERV, DTK_INVALID},     /* "invalid" reserved for bad time */
-   {"isodow", RESERV, DTK_ISODOW},     /* ISO day of week, Sunday == 7 */
+   {"isodow", UNITS, DTK_ISODOW},      /* ISO day of week, Sunday == 7 */
    {"isoyear", UNITS, DTK_ISOYEAR},    /* year in terms of the ISO week date */
    {"j", UNITS, DTK_JULIAN},
    {"jan", MONTH, 1},
index 05ae1de5de90c6eebb4f1b9f29c387c4fbaf8a5b..42c92c3e867b44cf2c3b58a71ec246fbf5f7a9ea 100644 (file)
@@ -4106,6 +4106,26 @@ timestamp_part(PG_FUNCTION_ARGS)
                result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
                break;
 
+           case DTK_DOW:
+           case DTK_ISODOW:
+               if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
+                   ereport(ERROR,
+                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                            errmsg("timestamp out of range")));
+               result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
+               if (val == DTK_ISODOW && result == 0)
+                   result = 7;
+               break;
+
+           case DTK_DOY:
+               if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
+                   ereport(ERROR,
+                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                            errmsg("timestamp out of range")));
+               result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
+                         - date2j(tm->tm_year, 1, 1) + 1);
+               break;
+
            case DTK_TZ:
            case DTK_TZ_MINUTE:
            case DTK_TZ_HOUR:
@@ -4129,26 +4149,6 @@ timestamp_part(PG_FUNCTION_ARGS)
 #endif
                break;
 
-           case DTK_DOW:
-           case DTK_ISODOW:
-               if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("timestamp out of range")));
-               result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
-               if (val == DTK_ISODOW && result == 0)
-                   result = 7;
-               break;
-
-           case DTK_DOY:
-               if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("timestamp out of range")));
-               result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
-                         - date2j(tm->tm_year, 1, 1) + 1);
-               break;
-
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -4320,6 +4320,26 @@ timestamptz_part(PG_FUNCTION_ARGS)
                result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
                break;
 
+           case DTK_DOW:
+           case DTK_ISODOW:
+               if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
+                   ereport(ERROR,
+                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                            errmsg("timestamp out of range")));
+               result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
+               if (val == DTK_ISODOW && result == 0)
+                   result = 7;
+               break;
+
+           case DTK_DOY:
+               if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
+                   ereport(ERROR,
+                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                            errmsg("timestamp out of range")));
+               result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
+                         - date2j(tm->tm_year, 1, 1) + 1);
+               break;
+
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -4341,26 +4361,6 @@ timestamptz_part(PG_FUNCTION_ARGS)
 #endif
                break;
 
-           case DTK_DOW:
-           case DTK_ISODOW:
-               if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("timestamp out of range")));
-               result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
-               if (val == DTK_ISODOW && result == 0)
-                   result = 7;
-               break;
-
-           case DTK_DOY:
-               if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
-                   ereport(ERROR,
-                           (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
-                            errmsg("timestamp out of range")));
-               result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
-                         - date2j(tm->tm_year, 1, 1) + 1);
-               break;
-
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),