Fix an oversight in commit 4c70098ff.
authorTom Lane <[email protected]>
Thu, 23 Jan 2020 21:15:32 +0000 (16:15 -0500)
committerTom Lane <[email protected]>
Thu, 23 Jan 2020 21:15:32 +0000 (16:15 -0500)
I had supposed that the from_char_seq_search() call sites were
all passing the constant arrays you'd expect them to pass ...
but on looking closer, the one for DY format was passing the
days[] array not days_short[].  This accidentally worked because
the day abbreviations in English are all the same as the first
three letters of the full day names.  However, once we took out
the "maximum comparison length" logic, it stopped working.

As penance for that oversight, add regression test cases covering
this, as well as every other switch case in DCH_from_char() that
was not reached according to the code coverage report.

Also, fold the DCH_RM and DCH_rm cases into one --- now that
seq_search is case independent, there's no need to pass different
comparison arrays for those cases.

Back-patch, as the previous commit was.

src/backend/utils/adt/formatting.c
src/test/regress/expected/horology.out
src/test/regress/sql/horology.sql

index e222037013e377907ee0d2ab8bd0b66b81d9e7e5..e7f868b281d7acec4576c76ca0876d52a36f804e 100644 (file)
@@ -3077,7 +3077,7 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out)
            case DCH_DY:
            case DCH_Dy:
            case DCH_dy:
-               from_char_seq_search(&value, &s, days,
+               from_char_seq_search(&value, &s, days_short,
                                     n);
                from_char_set_int(&out->d, value, n);
                out->d++;
@@ -3176,10 +3176,6 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out)
                SKIP_THth(s, n->suffix);
                break;
            case DCH_RM:
-               from_char_seq_search(&value, &s, rm_months_upper,
-                                    n);
-               from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n);
-               break;
            case DCH_rm:
                from_char_seq_search(&value, &s, rm_months_lower,
                                     n);
index b691e307036458bea6efe53c040fa306f50ac3be..dc3a188c51b8ba1804328e2387392cdf925fd017 100644 (file)
@@ -2822,6 +2822,18 @@ SELECT to_timestamp('20000-1116', 'YYYY-MMDD');
  Thu Nov 16 00:00:00 20000 PST
 (1 row)
 
+SELECT to_timestamp('1997 A.D. 11 16', 'YYYY B.C. MM DD');
+         to_timestamp         
+------------------------------
+ Sun Nov 16 00:00:00 1997 PST
+(1 row)
+
+SELECT to_timestamp('1997 B.C. 11 16', 'YYYY B.C. MM DD');
+          to_timestamp           
+---------------------------------
+ Tue Nov 16 00:00:00 1997 PST BC
+(1 row)
+
 SELECT to_timestamp('9-1116', 'Y-MMDD');
          to_timestamp         
 ------------------------------
@@ -2906,6 +2918,44 @@ SELECT to_timestamp('  20050302', 'YYYYMMDD');
  Wed Mar 02 00:00:00 2005 PST
 (1 row)
 
+SELECT to_timestamp('2011-12-18 11:38 A.M.', 'YYYY-MM-DD HH12:MI P.M.');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 11:38:00 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18 11:38 P.M.', 'YYYY-MM-DD HH12:MI P.M.');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 23:38:00 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18 11:38 PST', 'YYYY-MM-DD HH12:MI TZ');  -- NYI
+ERROR:  "TZ"/"tz"/"OF" format patterns are not supported in to_date
+SELECT to_timestamp('2018-11-02 12:34:56.025', 'YYYY-MM-DD HH24:MI:SS.MS');
+           to_timestamp           
+----------------------------------
+ Fri Nov 02 12:34:56.025 2018 PDT
+(1 row)
+
+SELECT to_date('1 4 1902', 'Q MM YYYY');  -- Q is ignored
+  to_date   
+------------
+ 04-01-1902
+(1 row)
+
+SELECT to_date('3 4 21 01', 'W MM CC YY');
+  to_date   
+------------
+ 04-15-2001
+(1 row)
+
+SELECT to_date('2458872', 'J');
+  to_date   
+------------
+ 01-23-2020
+(1 row)
+
 --
 -- Check handling of multiple spaces in format and/or input
 --
@@ -2998,6 +3048,19 @@ SELECT to_timestamp('19971)24', 'YYYYMMDD');
 ERROR:  invalid value "1)" for "MM"
 DETAIL:  Field requires 2 characters, but only 1 could be parsed.
 HINT:  If your source string is not fixed-width, try using the "FM" modifier.
+-- We don't accept full-length day or month names if short form is specified:
+SELECT to_timestamp('Friday 1-January-1999', 'DY DD MON YYYY');
+ERROR:  invalid value "ay" for "DD"
+DETAIL:  Value must be an integer.
+SELECT to_timestamp('Fri 1-January-1999', 'DY DD MON YYYY');
+ERROR:  invalid value "ary-" for "YYYY"
+DETAIL:  Value must be an integer.
+SELECT to_timestamp('Fri 1-Jan-1999', 'DY DD MON YYYY');  -- ok
+         to_timestamp         
+------------------------------
+ Fri Jan 01 00:00:00 1999 PST
+(1 row)
+
 -- Value clobbering:
 SELECT to_timestamp('1997-11-Jan-16', 'YYYY-MM-Mon-DD');
 ERROR:  conflicting values for "Mon" field in formatting string
index 472d2af794b50574d69c6cb2b886a2114e87a94a..5a278e499b0a2b7a16a3350df09a705514219610 100644 (file)
@@ -412,6 +412,9 @@ SELECT to_timestamp('19971116', 'YYYYMMDD');
 
 SELECT to_timestamp('20000-1116', 'YYYY-MMDD');
 
+SELECT to_timestamp('1997 A.D. 11 16', 'YYYY B.C. MM DD');
+SELECT to_timestamp('1997 B.C. 11 16', 'YYYY B.C. MM DD');
+
 SELECT to_timestamp('9-1116', 'Y-MMDD');
 
 SELECT to_timestamp('95-1116', 'YY-MMDD');
@@ -440,6 +443,17 @@ SELECT to_timestamp(' 2005 03 02', 'YYYYMMDD');
 
 SELECT to_timestamp('  20050302', 'YYYYMMDD');
 
+SELECT to_timestamp('2011-12-18 11:38 A.M.', 'YYYY-MM-DD HH12:MI P.M.');
+SELECT to_timestamp('2011-12-18 11:38 P.M.', 'YYYY-MM-DD HH12:MI P.M.');
+
+SELECT to_timestamp('2011-12-18 11:38 PST', 'YYYY-MM-DD HH12:MI TZ');  -- NYI
+
+SELECT to_timestamp('2018-11-02 12:34:56.025', 'YYYY-MM-DD HH24:MI:SS.MS');
+
+SELECT to_date('1 4 1902', 'Q MM YYYY');  -- Q is ignored
+SELECT to_date('3 4 21 01', 'W MM CC YY');
+SELECT to_date('2458872', 'J');
+
 --
 -- Check handling of multiple spaces in format and/or input
 --
@@ -473,6 +487,11 @@ SELECT to_timestamp('19971', 'YYYYMMDD');
 -- Insufficient digit characters for a single node:
 SELECT to_timestamp('19971)24', 'YYYYMMDD');
 
+-- We don't accept full-length day or month names if short form is specified:
+SELECT to_timestamp('Friday 1-January-1999', 'DY DD MON YYYY');
+SELECT to_timestamp('Fri 1-January-1999', 'DY DD MON YYYY');
+SELECT to_timestamp('Fri 1-Jan-1999', 'DY DD MON YYYY');  -- ok
+
 -- Value clobbering:
 SELECT to_timestamp('1997-11-Jan-16', 'YYYY-MM-Mon-DD');