diff -cprN head/contrib/auto_explain/auto_explain.c work/contrib/auto_explain/auto_explain.c *** head/contrib/auto_explain/auto_explain.c 2009-08-10 14:46:49.000000000 +0900 --- work/contrib/auto_explain/auto_explain.c 2009-11-30 11:54:52.313491403 +0900 *************** static const struct config_enum_entry fo *** 29,34 **** --- 29,35 ---- {"text", EXPLAIN_FORMAT_TEXT, false}, {"xml", EXPLAIN_FORMAT_XML, false}, {"json", EXPLAIN_FORMAT_JSON, false}, + {"yaml", EXPLAIN_FORMAT_YAML, false}, {NULL, 0, false} }; diff -cprN head/doc/src/sgml/auto-explain.sgml work/doc/src/sgml/auto-explain.sgml *** head/doc/src/sgml/auto-explain.sgml 2009-08-10 14:46:50.000000000 +0900 --- work/doc/src/sgml/auto-explain.sgml 2009-11-30 11:54:52.314487423 +0900 *************** LOAD 'auto_explain'; *** 114,120 **** auto_explain.log_format selects the EXPLAIN output format to be used. The allowed values are text, xml, ! and json. The default is text. Only superusers can change this setting. --- 114,120 ---- auto_explain.log_format selects the EXPLAIN output format to be used. The allowed values are text, xml, ! json, and yaml. The default is text. Only superusers can change this setting. diff -cprN head/doc/src/sgml/ref/explain.sgml work/doc/src/sgml/ref/explain.sgml *** head/doc/src/sgml/ref/explain.sgml 2009-08-10 14:46:50.000000000 +0900 --- work/doc/src/sgml/ref/explain.sgml 2009-11-30 11:54:52.314487423 +0900 *************** PostgreSQL documentation *** 31,37 **** ! EXPLAIN [ ( { ANALYZE boolean | VERBOSE boolean | COSTS boolean | FORMAT { TEXT | XML | JSON } } [, ...] ) ] statement EXPLAIN [ ANALYZE ] [ VERBOSE ] statement --- 31,37 ---- ! EXPLAIN [ ( { ANALYZE boolean | VERBOSE boolean | COSTS boolean | FORMAT { TEXT | XML | JSON | YAML } } [, ...] ) ] statement EXPLAIN [ ANALYZE ] [ VERBOSE ] statement *************** ROLLBACK; *** 143,150 **** FORMAT ! Specify the output format, which can be TEXT, XML, or JSON. ! XML or JSON output contains the same information as the text output format, but is easier for programs to parse. This parameter defaults to TEXT. --- 143,150 ---- FORMAT ! Specify the output format, which can be TEXT, XML, JSON, or YAML. ! Non-text output contains the same information as the text output format, but is easier for programs to parse. This parameter defaults to TEXT. diff -cprN head/doc/src/sgml/release-8.5.sgml work/doc/src/sgml/release-8.5.sgml *** head/doc/src/sgml/release-8.5.sgml 2009-11-27 06:20:12.000000000 +0900 --- work/doc/src/sgml/release-8.5.sgml 2009-11-30 11:54:52.314487423 +0900 *************** *** 176,182 **** ! EXPLAIN allows output of plans in XML or JSON format for automated processing of explain plans by analysis or visualization tools. --- 176,182 ---- ! EXPLAIN allows output of plans in XML, JSON, or YAML format for automated processing of explain plans by analysis or visualization tools. diff -cprN head/src/backend/commands/explain.c work/src/backend/commands/explain.c *** head/src/backend/commands/explain.c 2009-11-05 07:26:04.000000000 +0900 --- work/src/backend/commands/explain.c 2009-11-30 12:23:01.926467595 +0900 *************** static void ExplainBeginOutput(ExplainSt *** 95,101 **** --- 95,103 ---- static void ExplainEndOutput(ExplainState *es); static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es); static void ExplainJSONLineEnding(ExplainState *es); + static void ExplainYAMLLineStarting(ExplainState *es); static void escape_json(StringInfo buf, const char *str); + static void escape_yaml(StringInfo buf, const char *str); /* *************** ExplainQuery(ExplainStmt *stmt, const ch *** 135,140 **** --- 137,144 ---- es.format = EXPLAIN_FORMAT_XML; else if (strcmp(p, "json") == 0) es.format = EXPLAIN_FORMAT_JSON; + else if (strcmp(p, "yaml") == 0) + es.format = EXPLAIN_FORMAT_YAML; else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), *************** ExplainPropertyList(const char *qlabel, *** 1537,1542 **** --- 1541,1559 ---- } appendStringInfoChar(es->str, ']'); break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + escape_yaml(es->str, qlabel); + appendStringInfoChar(es->str, ':'); + foreach(lc, data) + { + appendStringInfoChar(es->str, '\n'); + appendStringInfoSpaces(es->str, es->indent * 2 + 2); + appendStringInfoString(es->str, "- "); + escape_yaml(es->str, (const char *) lfirst(lc)); + } + break; } } *************** ExplainProperty(const char *qlabel, cons *** 1584,1589 **** --- 1601,1615 ---- else escape_json(es->str, value); break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + appendStringInfo(es->str, "%s: ", qlabel); + if (numeric) + appendStringInfoString(es->str, value); + else + escape_yaml(es->str, value); + break; } } *************** ExplainOpenGroup(const char *objtype, co *** 1668,1673 **** --- 1694,1714 ---- es->grouping_stack = lcons_int(0, es->grouping_stack); es->indent++; break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + if (labelname) + { + appendStringInfo(es->str, "%s:", labelname); + es->grouping_stack = lcons_int(1, es->grouping_stack); + } + else + { + appendStringInfoChar(es->str, '-'); + es->grouping_stack = lcons_int(0, es->grouping_stack); + } + es->indent++; + break; } } *************** ExplainCloseGroup(const char *objtype, c *** 1697,1702 **** --- 1738,1748 ---- appendStringInfoChar(es->str, labeled ? '}' : ']'); es->grouping_stack = list_delete_first(es->grouping_stack); break; + + case EXPLAIN_FORMAT_YAML: + es->indent--; + es->grouping_stack = list_delete_first(es->grouping_stack); + break; } } *************** ExplainDummyGroup(const char *objtype, c *** 1729,1734 **** --- 1775,1787 ---- } escape_json(es->str, objtype); break; + + case EXPLAIN_FORMAT_YAML: + ExplainYAMLLineStarting(es); + if (labelname) + appendStringInfo(es->str, "%s:", labelname); + appendStringInfoString(es->str, objtype); + break; } } *************** ExplainBeginOutput(ExplainState *es) *** 1759,1764 **** --- 1812,1821 ---- es->grouping_stack = lcons_int(0, es->grouping_stack); es->indent++; break; + + case EXPLAIN_FORMAT_YAML: + es->grouping_stack = lcons_int(0, es->grouping_stack); + break; } } *************** ExplainEndOutput(ExplainState *es) *** 1784,1789 **** --- 1841,1850 ---- appendStringInfoString(es->str, "\n]"); es->grouping_stack = list_delete_first(es->grouping_stack); break; + + case EXPLAIN_FORMAT_YAML: + es->grouping_stack = list_delete_first(es->grouping_stack); + break; } } *************** ExplainSeparatePlans(ExplainState *es) *** 1796,1801 **** --- 1857,1863 ---- switch (es->format) { case EXPLAIN_FORMAT_TEXT: + case EXPLAIN_FORMAT_YAML: /* add a blank line */ appendStringInfoChar(es->str, '\n'); break; *************** ExplainJSONLineEnding(ExplainState *es) *** 1859,1864 **** --- 1921,1945 ---- } /* + * Indent a YAML line. + */ + static void + ExplainYAMLLineStarting(ExplainState *es) + { + Assert(es->format == EXPLAIN_FORMAT_YAML); + if (linitial_int(es->grouping_stack) == 0) + { + appendStringInfoChar(es->str, ' '); + linitial_int(es->grouping_stack) = 1; + } + else + { + appendStringInfoChar(es->str, '\n'); + appendStringInfoSpaces(es->str, es->indent * 2); + } + } + + /* * Produce a JSON string literal, properly escaping characters in the text. */ static void *************** escape_json(StringInfo buf, const char * *** 1902,1904 **** --- 1983,2005 ---- } appendStringInfoCharMacro(buf, '\"'); } + + /* + * YAML is a superset of JSON: if we find quotable characters, we call escape_json + */ + static void + escape_yaml(StringInfo buf, const char *str) + { + const char *p; + + for (p = str; *p; p++) + { + if ((unsigned char) *p < ' ' || strchr("\"\\\b\f\n\r\t", *p)) + { + escape_json(buf, str); + return; + } + } + + appendStringInfo(buf, "%s", str); + } diff -cprN head/src/include/commands/explain.h work/src/include/commands/explain.h *** head/src/include/commands/explain.h 2009-08-10 14:46:50.000000000 +0900 --- work/src/include/commands/explain.h 2009-11-30 11:54:52.315490662 +0900 *************** typedef enum ExplainFormat *** 19,25 **** { EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, ! EXPLAIN_FORMAT_JSON } ExplainFormat; typedef struct ExplainState --- 19,26 ---- { EXPLAIN_FORMAT_TEXT, EXPLAIN_FORMAT_XML, ! EXPLAIN_FORMAT_JSON, ! EXPLAIN_FORMAT_YAML } ExplainFormat; typedef struct ExplainState