Skip to content

Commit 765f76d

Browse files
committed
Fix is_digit labeling of to_timestamp's FFn format codes.
These format codes produce or consume strings of digits, so they should be labeled with is_digit = true, but they were not. This has effect in only one place, where is_next_separator() is checked to see if the preceding format code should slurp up all the available digits. Thus, with a format such as '...SSFF3' with remaining input '12345', the 'SS' code would consume all five digits (and then complain about seconds being out of range) when it should eat only two digits. Per report from Nick Davies. This bug goes back to d589f94 where the FFn codes were introduced, so back-patch to v13. Discussion: https://postgr.es/m/AM8PR08MB6356AC979252CFEA78B56678B6312@AM8PR08MB6356.eurprd08.prod.outlook.com
1 parent c140c0f commit 765f76d

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

src/backend/utils/adt/formatting.c

+13-13
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ typedef enum
622622
DCH_Day,
623623
DCH_Dy,
624624
DCH_D,
625-
DCH_FF1,
625+
DCH_FF1, /* FFn codes must be consecutive */
626626
DCH_FF2,
627627
DCH_FF3,
628628
DCH_FF4,
@@ -788,12 +788,12 @@ static const KeyWord DCH_keywords[] = {
788788
{"Day", 3, DCH_Day, false, FROM_CHAR_DATE_NONE},
789789
{"Dy", 2, DCH_Dy, false, FROM_CHAR_DATE_NONE},
790790
{"D", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN},
791-
{"FF1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE}, /* F */
792-
{"FF2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE},
793-
{"FF3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE},
794-
{"FF4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE},
795-
{"FF5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE},
796-
{"FF6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE},
791+
{"FF1", 3, DCH_FF1, true, FROM_CHAR_DATE_NONE}, /* F */
792+
{"FF2", 3, DCH_FF2, true, FROM_CHAR_DATE_NONE},
793+
{"FF3", 3, DCH_FF3, true, FROM_CHAR_DATE_NONE},
794+
{"FF4", 3, DCH_FF4, true, FROM_CHAR_DATE_NONE},
795+
{"FF5", 3, DCH_FF5, true, FROM_CHAR_DATE_NONE},
796+
{"FF6", 3, DCH_FF6, true, FROM_CHAR_DATE_NONE},
797797
{"FX", 2, DCH_FX, false, FROM_CHAR_DATE_NONE},
798798
{"HH24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* H */
799799
{"HH12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE},
@@ -844,12 +844,12 @@ static const KeyWord DCH_keywords[] = {
844844
{"dd", 2, DCH_DD, true, FROM_CHAR_DATE_GREGORIAN},
845845
{"dy", 2, DCH_dy, false, FROM_CHAR_DATE_NONE},
846846
{"d", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN},
847-
{"ff1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE}, /* f */
848-
{"ff2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE},
849-
{"ff3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE},
850-
{"ff4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE},
851-
{"ff5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE},
852-
{"ff6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE},
847+
{"ff1", 3, DCH_FF1, true, FROM_CHAR_DATE_NONE}, /* f */
848+
{"ff2", 3, DCH_FF2, true, FROM_CHAR_DATE_NONE},
849+
{"ff3", 3, DCH_FF3, true, FROM_CHAR_DATE_NONE},
850+
{"ff4", 3, DCH_FF4, true, FROM_CHAR_DATE_NONE},
851+
{"ff5", 3, DCH_FF5, true, FROM_CHAR_DATE_NONE},
852+
{"ff6", 3, DCH_FF6, true, FROM_CHAR_DATE_NONE},
853853
{"fx", 2, DCH_FX, false, FROM_CHAR_DATE_NONE},
854854
{"hh24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* h */
855855
{"hh12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE},

src/test/regress/expected/horology.out

+11
Original file line numberDiff line numberDiff line change
@@ -3453,6 +3453,17 @@ SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF'
34533453

34543454
SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
34553455
ERROR: date/time field value out of range: "2018-11-02 12:34:56.123456789"
3456+
SELECT i, to_timestamp('20181102123456123456', 'YYYYMMDDHH24MISSFF' || i) FROM generate_series(1, 6) i;
3457+
i | to_timestamp
3458+
---+-------------------------------------
3459+
1 | Fri Nov 02 12:34:56.1 2018 PDT
3460+
2 | Fri Nov 02 12:34:56.12 2018 PDT
3461+
3 | Fri Nov 02 12:34:56.123 2018 PDT
3462+
4 | Fri Nov 02 12:34:56.1235 2018 PDT
3463+
5 | Fri Nov 02 12:34:56.12346 2018 PDT
3464+
6 | Fri Nov 02 12:34:56.123456 2018 PDT
3465+
(6 rows)
3466+
34563467
SELECT to_date('1 4 1902', 'Q MM YYYY'); -- Q is ignored
34573468
to_date
34583469
------------

src/test/regress/sql/horology.sql

+1
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ SELECT i, to_timestamp('2018-11-02 12:34:56.1234', 'YYYY-MM-DD HH24:MI:SS.FF' ||
558558
SELECT i, to_timestamp('2018-11-02 12:34:56.12345', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
559559
SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
560560
SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
561+
SELECT i, to_timestamp('20181102123456123456', 'YYYYMMDDHH24MISSFF' || i) FROM generate_series(1, 6) i;
561562

562563
SELECT to_date('1 4 1902', 'Q MM YYYY'); -- Q is ignored
563564
SELECT to_date('3 4 21 01', 'W MM CC YY');

0 commit comments

Comments
 (0)