]> granicus.if.org Git - postgresql/commitdiff
Fix to_timestamp/to_date's handling of consecutive spaces in format string.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 20 Jan 2014 18:45:51 +0000 (13:45 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 20 Jan 2014 18:45:51 +0000 (13:45 -0500)
When there are consecutive spaces (or other non-format-code characters) in
the format, we should advance over exactly that many characters of input.
The previous coding mistakenly did a "skip whitespace" action between such
characters, possibly allowing more input to be skipped than the user
intended.  We only need to skip whitespace just before an actual field.

This is really a bug fix, but given the minimal number of field complaints
and the risk of breaking applications coded to expect the old behavior,
let's not back-patch it.

Jeevan Chalke

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

index 27aea9cbbcb39e7d976cea33dd04337280a08f9e..2099ad0c3023472b72d4cb8f63d531f3a6e8cfa5 100644 (file)
@@ -2839,16 +2839,22 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
        {
                if (n->type != NODE_TYPE_ACTION)
                {
+                       /*
+                        * Separator, so consume one character from input string.  Notice
+                        * we don't insist that the consumed character match the format's
+                        * character.
+                        */
                        s++;
-                       /* Ignore spaces when not in FX (fixed width) mode */
-                       if (isspace((unsigned char) n->character) && !fx_mode)
-                       {
-                               while (*s != '\0' && isspace((unsigned char) *s))
-                                       s++;
-                       }
                        continue;
                }
 
+               /* Ignore spaces before fields when not in FX (fixed width) mode */
+               if (!fx_mode && n->key->id != DCH_FX)
+               {
+                       while (*s != '\0' && isspace((unsigned char) *s))
+                               s++;
+               }
+
                from_char_set_mode(out, n->key->date_mode);
 
                switch (n->key->id)
index 87a695144eaf4f2ea1457dabefb8074e2182a5a9..1fe02be093f8d38a4839cbc4af8deba30637c390 100644 (file)
@@ -2906,6 +2906,81 @@ SELECT to_timestamp('  20050302', 'YYYYMMDD');
  Wed Mar 02 00:00:00 2005 PST
 (1 row)
 
+--
+-- Check handling of multiple spaces in format and/or input
+--
+SELECT to_timestamp('2011-12-18 23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 03:38:15 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 23:38:15 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18   23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 23:38:15 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD HH24:MI:SS');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 23:38:15 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 23:38:15 2011 PST
+(1 row)
+
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD   HH24:MI:SS');
+         to_timestamp         
+------------------------------
+ Sun Dec 18 03:38:15 2011 PST
+(1 row)
+
+SELECT to_date('2011 12  18', 'YYYY MM DD');
+  to_date   
+------------
+ 12-18-2011
+(1 row)
+
+SELECT to_date('2011 12  18', 'YYYY MM  DD');
+  to_date   
+------------
+ 12-18-2011
+(1 row)
+
+SELECT to_date('2011 12  18', 'YYYY MM   DD');
+  to_date   
+------------
+ 12-08-2011
+(1 row)
+
+SELECT to_date('2011 12 18', 'YYYY  MM DD');
+  to_date   
+------------
+ 02-18-2011
+(1 row)
+
+SELECT to_date('2011  12 18', 'YYYY  MM DD');
+  to_date   
+------------
+ 12-18-2011
+(1 row)
+
+SELECT to_date('2011   12 18', 'YYYY  MM DD');
+  to_date   
+------------
+ 12-18-2011
+(1 row)
+
 --
 -- Check errors for some incorrect usages of to_timestamp()
 --
index fe9a520cb91437638c6cf50f5ccd1a47607aae0b..c81437ba3582caaefc534060b4eb2a9987032f1f 100644 (file)
@@ -440,6 +440,26 @@ SELECT to_timestamp(' 2005 03 02', 'YYYYMMDD');
 
 SELECT to_timestamp('  20050302', 'YYYYMMDD');
 
+--
+-- Check handling of multiple spaces in format and/or input
+--
+
+SELECT to_timestamp('2011-12-18 23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+SELECT to_timestamp('2011-12-18   23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD HH24:MI:SS');
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD  HH24:MI:SS');
+SELECT to_timestamp('2011-12-18  23:38:15', 'YYYY-MM-DD   HH24:MI:SS');
+
+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', 'YYYY  MM DD');
+SELECT to_date('2011  12 18', 'YYYY  MM DD');
+SELECT to_date('2011   12 18', 'YYYY  MM DD');
+
 --
 -- Check errors for some incorrect usages of to_timestamp()
 --