mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
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.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.204 2010/02/26 02:00:39 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.205 2010/06/09 02:39:34 rhaas Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2152,22 +2152,48 @@ escape_json(StringInfo buf, const char *str)
|
||||
}
|
||||
|
||||
/*
|
||||
* YAML is a superset of JSON: if we find quotable characters, we call
|
||||
* escape_json. If not, we emit the property unquoted for better readability.
|
||||
* YAML is a superset of JSON, so we can use JSON escaping when escaping is
|
||||
* needed. However, some things that need to be quoted in JSON don't require
|
||||
* quoting in YAML, and we prefer not to quote unnecessarily, to improve
|
||||
* readability.
|
||||
*
|
||||
* Unfortunately, the YAML quoting rules are ridiculously complicated -- as
|
||||
* documented in sections 5.3 and 7.3.3 of http://yaml.org/spec/1.2/spec.html
|
||||
* -- and it doesn't seem worth expending a large amount of energy to avoid
|
||||
* all unnecessary quoting, so we just do something (sort of) simple: we quote
|
||||
* any string which is empty; any string which contains characters other than
|
||||
* alphanumerics, period, underscore, or space; or begins or ends with a
|
||||
* space. The exception for period is mostly so that floating-point numbers
|
||||
* (e.g., cost values) won't be quoted.
|
||||
*/
|
||||
static void
|
||||
escape_yaml(StringInfo buf, const char *str)
|
||||
{
|
||||
const char *p;
|
||||
bool needs_quoting = false;
|
||||
|
||||
for (p = str; *p; p++)
|
||||
#define is_safe_yaml(x) \
|
||||
(isalnum(((unsigned char) x)) || (x) == '.' || (x) == '_')
|
||||
|
||||
if (!is_safe_yaml(str[0]))
|
||||
needs_quoting = true;
|
||||
else
|
||||
{
|
||||
if ((unsigned char) *p < ' ' || strchr("\"\\\b\f\n\r\t", *p))
|
||||
const char *p;
|
||||
|
||||
for (p = str; *p; p++)
|
||||
{
|
||||
escape_json(buf, str);
|
||||
return;
|
||||
if (*p != ' ' && !is_safe_yaml(*p))
|
||||
{
|
||||
needs_quoting = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!*p && p[-1] == ' ')
|
||||
needs_quoting = true;
|
||||
}
|
||||
|
||||
appendStringInfo(buf, "%s", str);
|
||||
if (needs_quoting)
|
||||
escape_json(buf, str);
|
||||
else
|
||||
appendStringInfoString(buf, str);
|
||||
}
|
||||
|
Reference in New Issue
Block a user