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.193 2009/11/04 22:26:04 tgl Exp $
10
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.194 2009/12/11 01:33:35 adunstan Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -95,7 +95,9 @@ static void ExplainBeginOutput(ExplainState *es);
95
95
static void ExplainEndOutput (ExplainState * es );
96
96
static void ExplainXMLTag (const char * tagname , int flags , ExplainState * es );
97
97
static void ExplainJSONLineEnding (ExplainState * es );
98
+ static void ExplainYAMLLineStarting (ExplainState * es );
98
99
static void escape_json (StringInfo buf , const char * str );
100
+ static void escape_yaml (StringInfo buf , const char * str );
99
101
100
102
101
103
/*
@@ -135,6 +137,8 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
135
137
es .format = EXPLAIN_FORMAT_XML ;
136
138
else if (strcmp (p , "json" ) == 0 )
137
139
es .format = EXPLAIN_FORMAT_JSON ;
140
+ else if (strcmp (p , "yaml" ) == 0 )
141
+ es .format = EXPLAIN_FORMAT_YAML ;
138
142
else
139
143
ereport (ERROR ,
140
144
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
@@ -1537,6 +1541,19 @@ ExplainPropertyList(const char *qlabel, List *data, ExplainState *es)
1537
1541
}
1538
1542
appendStringInfoChar (es -> str , ']' );
1539
1543
break ;
1544
+
1545
+ case EXPLAIN_FORMAT_YAML :
1546
+ ExplainYAMLLineStarting (es );
1547
+ escape_yaml (es -> str , qlabel );
1548
+ appendStringInfoChar (es -> str , ':' );
1549
+ foreach (lc , data )
1550
+ {
1551
+ appendStringInfoChar (es -> str , '\n' );
1552
+ appendStringInfoSpaces (es -> str , es -> indent * 2 + 2 );
1553
+ appendStringInfoString (es -> str , "- " );
1554
+ escape_yaml (es -> str , (const char * ) lfirst (lc ));
1555
+ }
1556
+ break ;
1540
1557
}
1541
1558
}
1542
1559
@@ -1584,6 +1601,15 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric,
1584
1601
else
1585
1602
escape_json (es -> str , value );
1586
1603
break ;
1604
+
1605
+ case EXPLAIN_FORMAT_YAML :
1606
+ ExplainYAMLLineStarting (es );
1607
+ appendStringInfo (es -> str , "%s: " , qlabel );
1608
+ if (numeric )
1609
+ appendStringInfoString (es -> str , value );
1610
+ else
1611
+ escape_yaml (es -> str , value );
1612
+ break ;
1587
1613
}
1588
1614
}
1589
1615
@@ -1668,6 +1694,21 @@ ExplainOpenGroup(const char *objtype, const char *labelname,
1668
1694
es -> grouping_stack = lcons_int (0 , es -> grouping_stack );
1669
1695
es -> indent ++ ;
1670
1696
break ;
1697
+
1698
+ case EXPLAIN_FORMAT_YAML :
1699
+ ExplainYAMLLineStarting (es );
1700
+ if (labelname )
1701
+ {
1702
+ appendStringInfo (es -> str , "%s:" , labelname );
1703
+ es -> grouping_stack = lcons_int (1 , es -> grouping_stack );
1704
+ }
1705
+ else
1706
+ {
1707
+ appendStringInfoChar (es -> str , '-' );
1708
+ es -> grouping_stack = lcons_int (0 , es -> grouping_stack );
1709
+ }
1710
+ es -> indent ++ ;
1711
+ break ;
1671
1712
}
1672
1713
}
1673
1714
@@ -1697,6 +1738,11 @@ ExplainCloseGroup(const char *objtype, const char *labelname,
1697
1738
appendStringInfoChar (es -> str , labeled ? '}' : ']' );
1698
1739
es -> grouping_stack = list_delete_first (es -> grouping_stack );
1699
1740
break ;
1741
+
1742
+ case EXPLAIN_FORMAT_YAML :
1743
+ es -> indent -- ;
1744
+ es -> grouping_stack = list_delete_first (es -> grouping_stack );
1745
+ break ;
1700
1746
}
1701
1747
}
1702
1748
@@ -1729,6 +1775,13 @@ ExplainDummyGroup(const char *objtype, const char *labelname, ExplainState *es)
1729
1775
}
1730
1776
escape_json (es -> str , objtype );
1731
1777
break ;
1778
+
1779
+ case EXPLAIN_FORMAT_YAML :
1780
+ ExplainYAMLLineStarting (es );
1781
+ if (labelname )
1782
+ appendStringInfo (es -> str , "%s:" , labelname );
1783
+ appendStringInfoString (es -> str , objtype );
1784
+ break ;
1732
1785
}
1733
1786
}
1734
1787
@@ -1759,6 +1812,10 @@ ExplainBeginOutput(ExplainState *es)
1759
1812
es -> grouping_stack = lcons_int (0 , es -> grouping_stack );
1760
1813
es -> indent ++ ;
1761
1814
break ;
1815
+
1816
+ case EXPLAIN_FORMAT_YAML :
1817
+ es -> grouping_stack = lcons_int (0 , es -> grouping_stack );
1818
+ break ;
1762
1819
}
1763
1820
}
1764
1821
@@ -1784,6 +1841,10 @@ ExplainEndOutput(ExplainState *es)
1784
1841
appendStringInfoString (es -> str , "\n]" );
1785
1842
es -> grouping_stack = list_delete_first (es -> grouping_stack );
1786
1843
break ;
1844
+
1845
+ case EXPLAIN_FORMAT_YAML :
1846
+ es -> grouping_stack = list_delete_first (es -> grouping_stack );
1847
+ break ;
1787
1848
}
1788
1849
}
1789
1850
@@ -1796,6 +1857,7 @@ ExplainSeparatePlans(ExplainState *es)
1796
1857
switch (es -> format )
1797
1858
{
1798
1859
case EXPLAIN_FORMAT_TEXT :
1860
+ case EXPLAIN_FORMAT_YAML :
1799
1861
/* add a blank line */
1800
1862
appendStringInfoChar (es -> str , '\n' );
1801
1863
break ;
@@ -1858,6 +1920,25 @@ ExplainJSONLineEnding(ExplainState *es)
1858
1920
appendStringInfoChar (es -> str , '\n' );
1859
1921
}
1860
1922
1923
+ /*
1924
+ * Indent a YAML line.
1925
+ */
1926
+ static void
1927
+ ExplainYAMLLineStarting (ExplainState * es )
1928
+ {
1929
+ Assert (es -> format == EXPLAIN_FORMAT_YAML );
1930
+ if (linitial_int (es -> grouping_stack ) == 0 )
1931
+ {
1932
+ appendStringInfoChar (es -> str , ' ' );
1933
+ linitial_int (es -> grouping_stack ) = 1 ;
1934
+ }
1935
+ else
1936
+ {
1937
+ appendStringInfoChar (es -> str , '\n' );
1938
+ appendStringInfoSpaces (es -> str , es -> indent * 2 );
1939
+ }
1940
+ }
1941
+
1861
1942
/*
1862
1943
* Produce a JSON string literal, properly escaping characters in the text.
1863
1944
*/
@@ -1902,3 +1983,23 @@ escape_json(StringInfo buf, const char *str)
1902
1983
}
1903
1984
appendStringInfoCharMacro (buf , '\"' );
1904
1985
}
1986
+
1987
+ /*
1988
+ * YAML is a superset of JSON: if we find quotable characters, we call escape_json
1989
+ */
1990
+ static void
1991
+ escape_yaml (StringInfo buf , const char * str )
1992
+ {
1993
+ const char * p ;
1994
+
1995
+ for (p = str ; * p ; p ++ )
1996
+ {
1997
+ if ((unsigned char ) * p < ' ' || strchr ("\"\\\b\f\n\r\t" , * p ))
1998
+ {
1999
+ escape_json (buf , str );
2000
+ return ;
2001
+ }
2002
+ }
2003
+
2004
+ appendStringInfo (buf , "%s" , str );
2005
+ }
0 commit comments