aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-01-20 13:45:51 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2014-01-20 13:45:51 -0500
commit9a8f5729b4625ec0468ad5a48296c3e729cf3e65 (patch)
treee1a234f505bd22716b373d5cd96b65f4af20ede2
parent5363c7f2bc5e77caf2f308bed93e3e881a9113cf (diff)
downloadpostgresql-9a8f5729b4625ec0468ad5a48296c3e729cf3e65.tar.gz
postgresql-9a8f5729b4625ec0468ad5a48296c3e729cf3e65.zip
Fix to_timestamp/to_date's handling of consecutive spaces in format string.
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
-rw-r--r--src/backend/utils/adt/formatting.c18
-rw-r--r--src/test/regress/expected/horology.out75
-rw-r--r--src/test/regress/sql/horology.sql20
3 files changed, 107 insertions, 6 deletions
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 27aea9cbbcb..2099ad0c302 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -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)
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index 87a695144ea..1fe02be093f 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -2907,6 +2907,81 @@ SELECT to_timestamp(' 20050302', 'YYYYMMDD');
(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()
--
-- Mixture of date conventions (ISO week and Gregorian):
diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql
index fe9a520cb91..c81437ba358 100644
--- a/src/test/regress/sql/horology.sql
+++ b/src/test/regress/sql/horology.sql
@@ -441,6 +441,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()
--