mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +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
|
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* YAML is a superset of JSON, so we can use JSON escaping when escaping is
|
||||||
* escape_json. If not, we emit the property unquoted for better readability.
|
* 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
|
static void
|
||||||
escape_yaml(StringInfo buf, const char *str)
|
escape_yaml(StringInfo buf, const char *str)
|
||||||
{
|
{
|
||||||
|
bool needs_quoting = false;
|
||||||
|
|
||||||
|
#define is_safe_yaml(x) \
|
||||||
|
(isalnum(((unsigned char) x)) || (x) == '.' || (x) == '_')
|
||||||
|
|
||||||
|
if (!is_safe_yaml(str[0]))
|
||||||
|
needs_quoting = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
for (p = str; *p; p++)
|
for (p = str; *p; p++)
|
||||||
{
|
{
|
||||||
if ((unsigned char) *p < ' ' || strchr("\"\\\b\f\n\r\t", *p))
|
if (*p != ' ' && !is_safe_yaml(*p))
|
||||||
{
|
{
|
||||||
escape_json(buf, str);
|
needs_quoting = true;
|
||||||
return;
|
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