|
7 | 7 | * Portions Copyright (c) 1994-5, Regents of the University of California
|
8 | 8 | *
|
9 | 9 | * 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 $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -2152,22 +2152,48 @@ escape_json(StringInfo buf, const char *str)
|
2152 | 2152 | }
|
2153 | 2153 |
|
2154 | 2154 | /*
|
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. |
2157 | 2168 | */
|
2158 | 2169 | static void
|
2159 | 2170 | escape_yaml(StringInfo buf, const char *str)
|
2160 | 2171 | {
|
2161 |
| - const char *p; |
| 2172 | + bool needs_quoting = false; |
2162 | 2173 |
|
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 |
2164 | 2180 | {
|
2165 |
| - if ((unsigned char) *p < ' ' || strchr("\"\\\b\f\n\r\t", *p)) |
| 2181 | + const char *p; |
| 2182 | + |
| 2183 | + for (p = str; *p; p++) |
2166 | 2184 | {
|
2167 |
| - escape_json(buf, str); |
2168 |
| - return; |
| 2185 | + if (*p != ' ' && !is_safe_yaml(*p)) |
| 2186 | + { |
| 2187 | + needs_quoting = true; |
| 2188 | + break; |
| 2189 | + } |
2169 | 2190 | }
|
| 2191 | + if (!*p && p[-1] == ' ') |
| 2192 | + needs_quoting = true; |
2170 | 2193 | }
|
2171 | 2194 |
|
2172 |
| - appendStringInfo(buf, "%s", str); |
| 2195 | + if (needs_quoting) |
| 2196 | + escape_json(buf, str); |
| 2197 | + else |
| 2198 | + appendStringInfoString(buf, str); |
2173 | 2199 | }
|
0 commit comments