Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d6e503a

Browse files
committed
Attempt to fix EXPLAIN (FORMAT YAML) quoting to behave sanely.
The previous code failed to quote in many cases where quoting was necessary - YAML has loads of special characters, including -:[]{},"'|*& - so quote much more aggressively, and only refrain from quoting things where it seems fairly clear that it isn't necessary. Per report from Dean Rasheed.
1 parent a624356 commit d6e503a

File tree

1 file changed

+35
-9
lines changed

1 file changed

+35
-9
lines changed

src/backend/commands/explain.c

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.204 2010/02/26 02:00:39 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.205 2010/06/09 02:39:34 rhaas Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -2152,22 +2152,48 @@ escape_json(StringInfo buf, const char *str)
21522152
}
21532153

21542154
/*
2155-
* YAML is a superset of JSON: if we find quotable characters, we call
2156-
* escape_json. If not, we emit the property unquoted for better readability.
2155+
* YAML is a superset of JSON, so we can use JSON escaping when escaping is
2156+
* needed. However, some things that need to be quoted in JSON don't require
2157+
* quoting in YAML, and we prefer not to quote unnecessarily, to improve
2158+
* readability.
2159+
*
2160+
* Unfortunately, the YAML quoting rules are ridiculously complicated -- as
2161+
* documented in sections 5.3 and 7.3.3 of http://yaml.org/spec/1.2/spec.html
2162+
* -- and it doesn't seem worth expending a large amount of energy to avoid
2163+
* all unnecessary quoting, so we just do something (sort of) simple: we quote
2164+
* any string which is empty; any string which contains characters other than
2165+
* alphanumerics, period, underscore, or space; or begins or ends with a
2166+
* space. The exception for period is mostly so that floating-point numbers
2167+
* (e.g., cost values) won't be quoted.
21572168
*/
21582169
static void
21592170
escape_yaml(StringInfo buf, const char *str)
21602171
{
2161-
const char *p;
2172+
bool needs_quoting = false;
21622173

2163-
for (p = str; *p; p++)
2174+
#define is_safe_yaml(x) \
2175+
(isalnum(((unsigned char) x)) || (x) == '.' || (x) == '_')
2176+
2177+
if (!is_safe_yaml(str[0]))
2178+
needs_quoting = true;
2179+
else
21642180
{
2165-
if ((unsigned char) *p < ' ' || strchr("\"\\\b\f\n\r\t", *p))
2181+
const char *p;
2182+
2183+
for (p = str; *p; p++)
21662184
{
2167-
escape_json(buf, str);
2168-
return;
2185+
if (*p != ' ' && !is_safe_yaml(*p))
2186+
{
2187+
needs_quoting = true;
2188+
break;
2189+
}
21692190
}
2191+
if (!*p && p[-1] == ' ')
2192+
needs_quoting = true;
21702193
}
21712194

2172-
appendStringInfo(buf, "%s", str);
2195+
if (needs_quoting)
2196+
escape_json(buf, str);
2197+
else
2198+
appendStringInfoString(buf, str);
21732199
}

0 commit comments

Comments
 (0)