]> granicus.if.org Git - postgresql/commitdiff
Fix handling of format string text characters in to_timestamp()/to_date()
authorAlexander Korotkov <akorotkov@postgresql.org>
Thu, 20 Sep 2018 12:48:04 +0000 (15:48 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Thu, 20 Sep 2018 12:48:04 +0000 (15:48 +0300)
cf984672 introduced improvement of handling of spaces and separators in
to_timestamp()/to_date() functions.  In particular, now we're skipping spaces
both before and after fields.  That may cause format string text character to
consume part of field in the situations, when it didn't happen before cf984672.
This commit cause format string text character consume input string characters
only when since previous field (or string beginning) number of skipped input
string characters is not greater than number of corresponding format string
characters (that is we didn't skip any extra characters in input string).

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

index 2ed8ca675bde9bf15049f1c2482d99e70447ef2c..0ed59f1c347fbf5ed3dfad9747d8b8620de34955 100644 (file)
@@ -3061,9 +3061,24 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
                         * Text character, so consume one character from input string.
                         * Notice we don't insist that the consumed character match the
                         * format's character.
-                        * Text field ignores FX mode.
                         */
-                       s += pg_mblen(s);
+                       if (!fx_mode)
+                       {
+                               /*
+                                * In non FX mode we might have skipped some extra characters
+                                * (more than specified in format string) before.  In this
+                                * case we don't skip input string character, because it might
+                                * be part of field.
+                                */
+                               if (extra_skip > 0)
+                                       extra_skip--;
+                               else
+                                       s += pg_mblen(s);
+                       }
+                       else
+                       {
+                               s += pg_mblen(s);
+                       }
                        continue;
                }
 
index 7d11f25158491ab3ba779fce526ad7ba69952619..b00ab0f142c2f6ed4efc09adbb4b78eba5eb1c41 100644 (file)
@@ -3128,6 +3128,21 @@ SELECT to_date('2011   12 18', 'YYYY  MM DD');
  12-18-2011
 (1 row)
 
+SELECT to_date('2011 12 18', 'YYYYxMMxDD');
+  to_date   
+------------
+ 12-18-2011
+(1 row)
+
+SELECT to_date('2011x 12x 18', 'YYYYxMMxDD');
+  to_date   
+------------
+ 12-18-2011
+(1 row)
+
+SELECT to_date('2011 x12 x18', 'YYYYxMMxDD');
+ERROR:  invalid value "x1" for "MM"
+DETAIL:  Value must be an integer.
 --
 -- Check errors for some incorrect usages of to_timestamp() and to_date()
 --
index 807037be76ef6f326a23882037ef2cb522d50bda..ca34e8753defa710c85360f01c8ec70b8e49cdc1 100644 (file)
@@ -495,6 +495,10 @@ SELECT to_date('2011 12 18', 'YYYY  MM DD');
 SELECT to_date('2011  12 18', 'YYYY  MM DD');
 SELECT to_date('2011   12 18', 'YYYY  MM DD');
 
+SELECT to_date('2011 12 18', 'YYYYxMMxDD');
+SELECT to_date('2011x 12x 18', 'YYYYxMMxDD');
+SELECT to_date('2011 x12 x18', 'YYYYxMMxDD');
+
 --
 -- Check errors for some incorrect usages of to_timestamp() and to_date()
 --