Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 483bdb2

Browse files
committed
Support [NO] INDENT option in XMLSERIALIZE().
This adds the ability to pretty-print XML documents ... according to libxml's somewhat idiosyncratic notions of what's pretty, anyway. One notable divergence from a strict reading of the spec is that libxml is willing to collapse empty nodes "<node></node>" to just "<node/>", whereas SQL and the underlying XML spec say that this option should only result in whitespace tweaks. Nonetheless, it seems close enough to justify using the SQL-standard syntax. Jim Jones, reviewed by Peter Smith and myself Discussion: https://postgr.es/m/2f5df461-dad8-6d7d-4568-08e10608a69b@uni-muenster.de
1 parent 419a8dd commit 483bdb2

File tree

15 files changed

+775
-22
lines changed

15 files changed

+775
-22
lines changed

doc/src/sgml/datatype.sgml

+8-1
Original file line numberDiff line numberDiff line change
@@ -4460,7 +4460,7 @@ xml '<foo>bar</foo>'
44604460
<type>xml</type>, uses the function
44614461
<function>xmlserialize</function>:<indexterm><primary>xmlserialize</primary></indexterm>
44624462
<synopsis>
4463-
XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <replaceable>type</replaceable> )
4463+
XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <replaceable>type</replaceable> [ [ NO ] INDENT ] )
44644464
</synopsis>
44654465
<replaceable>type</replaceable> can be
44664466
<type>character</type>, <type>character varying</type>, or
@@ -4470,6 +4470,13 @@ XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <repla
44704470
you to simply cast the value.
44714471
</para>
44724472

4473+
<para>
4474+
The <literal>INDENT</literal> option causes the result to be
4475+
pretty-printed, while <literal>NO INDENT</literal> (which is the
4476+
default) just emits the original input string. Casting to a character
4477+
type likewise produces the original string.
4478+
</para>
4479+
44734480
<para>
44744481
When a character string value is cast to or from type
44754482
<type>xml</type> without going through <type>XMLPARSE</type> or

src/backend/catalog/sql_features.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ X061 XMLParse: character string input and DOCUMENT option YES
621621
X065 XMLParse: binary string input and CONTENT option NO
622622
X066 XMLParse: binary string input and DOCUMENT option NO
623623
X068 XMLSerialize: BOM NO
624-
X069 XMLSerialize: INDENT NO
624+
X069 XMLSerialize: INDENT YES
625625
X070 XMLSerialize: character string serialization and CONTENT option YES
626626
X071 XMLSerialize: character string serialization and DOCUMENT option YES
627627
X072 XMLSerialize: character string serialization YES

src/backend/executor/execExprInterp.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -3837,8 +3837,10 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
38373837
return;
38383838
value = argvalue[0];
38393839

3840-
*op->resvalue = PointerGetDatum(xmltotext_with_xmloption(DatumGetXmlP(value),
3841-
xexpr->xmloption));
3840+
*op->resvalue =
3841+
PointerGetDatum(xmltotext_with_options(DatumGetXmlP(value),
3842+
xexpr->xmloption,
3843+
xexpr->indent));
38423844
*op->resnull = false;
38433845
}
38443846
break;

src/backend/parser/gram.y

+11-3
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
613613
%type <node> xml_root_version opt_xml_root_standalone
614614
%type <node> xmlexists_argument
615615
%type <ival> document_or_content
616-
%type <boolean> xml_whitespace_option
616+
%type <boolean> xml_indent_option xml_whitespace_option
617617
%type <list> xmltable_column_list xmltable_column_option_list
618618
%type <node> xmltable_column_el
619619
%type <defelt> xmltable_column_option_el
@@ -702,7 +702,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
702702
HANDLER HAVING HEADER_P HOLD HOUR_P
703703

704704
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IMPORT_P IN_P INCLUDE
705-
INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
705+
INCLUDING INCREMENT INDENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
706706
INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
707707
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
708708

@@ -15532,13 +15532,14 @@ func_expr_common_subexpr:
1553215532
$$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
1553315533
list_make3($3, $5, $6), @1);
1553415534
}
15535-
| XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')'
15535+
| XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename xml_indent_option ')'
1553615536
{
1553715537
XmlSerialize *n = makeNode(XmlSerialize);
1553815538

1553915539
n->xmloption = $3;
1554015540
n->expr = $4;
1554115541
n->typeName = $6;
15542+
n->indent = $7;
1554215543
n->location = @1;
1554315544
$$ = (Node *) n;
1554415545
}
@@ -15592,6 +15593,11 @@ document_or_content: DOCUMENT_P { $$ = XMLOPTION_DOCUMENT; }
1559215593
| CONTENT_P { $$ = XMLOPTION_CONTENT; }
1559315594
;
1559415595

15596+
xml_indent_option: INDENT { $$ = true; }
15597+
| NO INDENT { $$ = false; }
15598+
| /*EMPTY*/ { $$ = false; }
15599+
;
15600+
1559515601
xml_whitespace_option: PRESERVE WHITESPACE_P { $$ = true; }
1559615602
| STRIP_P WHITESPACE_P { $$ = false; }
1559715603
| /*EMPTY*/ { $$ = false; }
@@ -16828,6 +16834,7 @@ unreserved_keyword:
1682816834
| INCLUDE
1682916835
| INCLUDING
1683016836
| INCREMENT
16837+
| INDENT
1683116838
| INDEX
1683216839
| INDEXES
1683316840
| INHERIT
@@ -17384,6 +17391,7 @@ bare_label_keyword:
1738417391
| INCLUDE
1738517392
| INCLUDING
1738617393
| INCREMENT
17394+
| INDENT
1738717395
| INDEX
1738817396
| INDEXES
1738917397
| INHERIT

src/backend/parser/parse_expr.c

+1
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,7 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
23312331
typenameTypeIdAndMod(pstate, xs->typeName, &targetType, &targetTypmod);
23322332

23332333
xexpr->xmloption = xs->xmloption;
2334+
xexpr->indent = xs->indent;
23342335
xexpr->location = xs->location;
23352336
/* We actually only need these to be able to parse back the expression. */
23362337
xexpr->type = targetType;

0 commit comments

Comments
 (0)