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

Commit 593e30f

Browse files
jimjonesbrCommitfest Bot
authored and
Commitfest Bot
committed
Add XMLDocument function (SQL/XML X030)
This patch adds the SQL/XML X030 function XMLDocument. It returns an XML document from a given XML expression. An XML document node can have any number of children nodes. Since our XML data type corresponds to XML(CONTENT(ANY)), any expression already validated by the input function is considered valid output for XMLDocument. As a result, this function simply returns its input value. While this implementation is quite trivial, it follows the SQL/XML standard and facilitates the migration of SQL statements from other database systems that also support X030. Usage: WITH t(x) AS ( VALUES (xmlparse(DOCUMENT '<root><foo>bar</foo></root>')), (xmlforest(42 AS foo, 73 AS bar)), (NULL) ) SELECT xmldocument(x) FROM t; xmldocument ----------------------------- <root><foo>bar</foo></root> <foo>42</foo><bar>73</bar> (3 rows) This patch also adds documentation and tests.
1 parent 1722d5e commit 593e30f

File tree

8 files changed

+258
-1
lines changed

8 files changed

+258
-1
lines changed

doc/src/sgml/func.sgml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14655,6 +14655,60 @@ SELECT xmlcomment('hello');
1465514655
</para>
1465614656
</sect3>
1465714657

14658+
<sect3 id="functions-producing-xml-xmldocument">
14659+
<title><literal>xmldocument</literal></title>
14660+
14661+
<indexterm>
14662+
<primary>xmldocument</primary>
14663+
</indexterm>
14664+
14665+
<synopsis>
14666+
<function>xmldocument</function> ( <type>xml</type> ) <returnvalue>xml</returnvalue>
14667+
</synopsis>
14668+
14669+
<para>
14670+
The <function>xmldocument</function> function returns the input argument
14671+
unchanged, or <literal>NULL</literal> if the argument is <literal>NULL</literal>,
14672+
and is provided for compatibility.
14673+
14674+
The SQL-standard <replaceable>XMLDocument</replaceable> function applied to an
14675+
XML value <literal>$EXPR</literal>, has effects equivalent to the XML
14676+
Query expression <replaceable>document { $EXPR }</replaceable>. It replaces any
14677+
document nodes in the input with their children and wraps the whole result in a
14678+
single <replaceable>document node</replaceable>.
14679+
14680+
In the XML Query standard, a <replaceable>document node</replaceable> represents
14681+
a relaxed version of an XML document structure. This corresponds to what PostgreSQL's
14682+
single XML type allows, meaning that any valid non-null PostgreSQL XML value can be
14683+
returned unchanged. Other systems may support more permissive XML data types,
14684+
such as <literal>XML(SEQUENCE)</literal>, which allow values that do not conform to
14685+
this structure. In PostgreSQL, every valid non-null value of the XML type already has
14686+
that structure, making additional processing by this function unnecessary.
14687+
</para>
14688+
14689+
<para>
14690+
Example:
14691+
<screen><![CDATA[
14692+
WITH xmldata (val) AS (
14693+
VALUES
14694+
(xmlparse(DOCUMENT '<root><foo>bar</foo></root>')),
14695+
(xmltext('foo&bar')),
14696+
(xmlelement(NAME el)),
14697+
(xmlforest(42 AS foo, 73 AS bar))
14698+
)
14699+
SELECT xmldocument(val) FROM xmldata;
14700+
14701+
xmldocument
14702+
-----------------------------
14703+
<root><foo>bar</foo></root>
14704+
foo&amp;bar
14705+
<el/>
14706+
<foo>42</foo><bar>73</bar>
14707+
(4 rows)
14708+
]]></screen>
14709+
</para>
14710+
</sect3>
14711+
1465814712
<sect3 id="functions-producing-xml-xmlconcat">
1465914713
<title><literal>xmlconcat</literal></title>
1466014714

src/backend/catalog/sql_features.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ X015 Fields of XML type NO
625625
X016 Persistent XML values YES
626626
X020 XMLConcat YES
627627
X025 XMLCast NO
628-
X030 XMLDocument NO
628+
X030 XMLDocument YES
629629
X031 XMLElement YES
630630
X032 XMLForest YES
631631
X034 XMLAgg YES

src/backend/utils/adt/xml.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,24 @@ xmlcomment(PG_FUNCTION_ARGS)
523523
}
524524

525525

526+
/*
527+
* xmldocument implements the SQL/XML function XMLDocument (X030).
528+
* Since our XML data type corresponds to XML(CONTENT(ANY)), any
529+
* expression already validated by the input function is considered
530+
* valid output for XMLDocument. As a result, this function simply
531+
* returns its input value.
532+
*/
533+
Datum
534+
xmldocument(PG_FUNCTION_ARGS)
535+
{
536+
#ifdef USE_LIBXML
537+
PG_RETURN_DATUM(PG_GETARG_DATUM(0));
538+
#else
539+
NO_XML_SUPPORT();
540+
return 0;
541+
#endif /* not USE_LIBXML */
542+
}
543+
526544
Datum
527545
xmltext(PG_FUNCTION_ARGS)
528546
{

src/include/catalog/pg_proc.dat

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9143,6 +9143,9 @@
91439143
{ oid => '3813', descr => 'generate XML text node',
91449144
proname => 'xmltext', prorettype => 'xml', proargtypes => 'text',
91459145
prosrc => 'xmltext' },
9146+
{ oid => '3814', descr => 'generate XML document',
9147+
proname => 'xmldocument', prorettype => 'xml', proargtypes => 'xml',
9148+
prosrc => 'xmldocument'},
91469149

91479150
{ oid => '2923', descr => 'map table contents to XML',
91489151
proname => 'table_to_xml', procost => '100', provolatile => 's',

src/test/regress/expected/xml.out

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,3 +1881,61 @@ SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char);
18811881
x&lt;P&gt;73&lt;/P&gt;0.42truej
18821882
(1 row)
18831883

1884+
SELECT
1885+
xmldocument(
1886+
xmlelement(NAME root,
1887+
xmlattributes(42 AS att),
1888+
xmlcomment('comment'),
1889+
xmlelement(NAME foo,'<foo&bar>'),
1890+
xmlelement(NAME bar, xmlconcat('va', 'lue')),
1891+
xmlpi(name pi),
1892+
xmlelement(NAME txt, xmltext('<"&>'))
1893+
)
1894+
);
1895+
xmldocument
1896+
------------------------------------------------------------------------------------------------------------------------
1897+
<root att="42"><!--comment--><foo>&lt;foo&amp;bar&gt;</foo><bar>value</bar><?pi?><txt>&lt;&quot;&amp;&gt;</txt></root>
1898+
(1 row)
1899+
1900+
SELECT xmldocument(NULL);
1901+
xmldocument
1902+
-------------
1903+
1904+
(1 row)
1905+
1906+
SELECT xmldocument('<foo>bar</foo>'::xml);
1907+
xmldocument
1908+
----------------
1909+
<foo>bar</foo>
1910+
(1 row)
1911+
1912+
SELECT xmldocument('foo'::xml);
1913+
xmldocument
1914+
-------------
1915+
foo
1916+
(1 row)
1917+
1918+
SELECT xmldocument('foo');
1919+
xmldocument
1920+
-------------
1921+
foo
1922+
(1 row)
1923+
1924+
SELECT xmldocument('');
1925+
xmldocument
1926+
-------------
1927+
1928+
(1 row)
1929+
1930+
SELECT xmldocument(' ');
1931+
xmldocument
1932+
-------------
1933+
1934+
(1 row)
1935+
1936+
SELECT xmldocument(xmlcomment('comment'));
1937+
xmldocument
1938+
----------------
1939+
<!--comment-->
1940+
(1 row)
1941+

src/test/regress/expected/xml_1.out

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,3 +1496,50 @@ ERROR: unsupported XML feature
14961496
LINE 1: SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j':...
14971497
^
14981498
DETAIL: This functionality requires the server to be built with libxml support.
1499+
SELECT
1500+
xmldocument(
1501+
xmlelement(NAME root,
1502+
xmlattributes(42 AS att),
1503+
xmlcomment('comment'),
1504+
xmlelement(NAME foo,'<foo&bar>'),
1505+
xmlelement(NAME bar, xmlconcat('va', 'lue')),
1506+
xmlpi(name pi),
1507+
xmlelement(NAME txt, xmltext('<"&>'))
1508+
)
1509+
);
1510+
ERROR: unsupported XML feature
1511+
DETAIL: This functionality requires the server to be built with libxml support.
1512+
SELECT xmldocument(NULL);
1513+
xmldocument
1514+
-------------
1515+
1516+
(1 row)
1517+
1518+
SELECT xmldocument('<foo>bar</foo>'::xml);
1519+
ERROR: unsupported XML feature
1520+
LINE 1: SELECT xmldocument('<foo>bar</foo>'::xml);
1521+
^
1522+
DETAIL: This functionality requires the server to be built with libxml support.
1523+
SELECT xmldocument('foo'::xml);
1524+
ERROR: unsupported XML feature
1525+
LINE 1: SELECT xmldocument('foo'::xml);
1526+
^
1527+
DETAIL: This functionality requires the server to be built with libxml support.
1528+
SELECT xmldocument('foo');
1529+
ERROR: unsupported XML feature
1530+
LINE 1: SELECT xmldocument('foo');
1531+
^
1532+
DETAIL: This functionality requires the server to be built with libxml support.
1533+
SELECT xmldocument('');
1534+
ERROR: unsupported XML feature
1535+
LINE 1: SELECT xmldocument('');
1536+
^
1537+
DETAIL: This functionality requires the server to be built with libxml support.
1538+
SELECT xmldocument(' ');
1539+
ERROR: unsupported XML feature
1540+
LINE 1: SELECT xmldocument(' ');
1541+
^
1542+
DETAIL: This functionality requires the server to be built with libxml support.
1543+
SELECT xmldocument(xmlcomment('comment'));
1544+
ERROR: unsupported XML feature
1545+
DETAIL: This functionality requires the server to be built with libxml support.

src/test/regress/expected/xml_2.out

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,3 +1867,61 @@ SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char);
18671867
x&lt;P&gt;73&lt;/P&gt;0.42truej
18681868
(1 row)
18691869

1870+
SELECT
1871+
xmldocument(
1872+
xmlelement(NAME root,
1873+
xmlattributes(42 AS att),
1874+
xmlcomment('comment'),
1875+
xmlelement(NAME foo,'<foo&bar>'),
1876+
xmlelement(NAME bar, xmlconcat('va', 'lue')),
1877+
xmlpi(name pi),
1878+
xmlelement(NAME txt, xmltext('<"&>'))
1879+
)
1880+
);
1881+
xmldocument
1882+
------------------------------------------------------------------------------------------------------------------------
1883+
<root att="42"><!--comment--><foo>&lt;foo&amp;bar&gt;</foo><bar>value</bar><?pi?><txt>&lt;&quot;&amp;&gt;</txt></root>
1884+
(1 row)
1885+
1886+
SELECT xmldocument(NULL);
1887+
xmldocument
1888+
-------------
1889+
1890+
(1 row)
1891+
1892+
SELECT xmldocument('<foo>bar</foo>'::xml);
1893+
xmldocument
1894+
----------------
1895+
<foo>bar</foo>
1896+
(1 row)
1897+
1898+
SELECT xmldocument('foo'::xml);
1899+
xmldocument
1900+
-------------
1901+
foo
1902+
(1 row)
1903+
1904+
SELECT xmldocument('foo');
1905+
xmldocument
1906+
-------------
1907+
foo
1908+
(1 row)
1909+
1910+
SELECT xmldocument('');
1911+
xmldocument
1912+
-------------
1913+
1914+
(1 row)
1915+
1916+
SELECT xmldocument(' ');
1917+
xmldocument
1918+
-------------
1919+
1920+
(1 row)
1921+
1922+
SELECT xmldocument(xmlcomment('comment'));
1923+
xmldocument
1924+
----------------
1925+
<!--comment-->
1926+
(1 row)
1927+

src/test/regress/sql/xml.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,3 +679,22 @@ SELECT xmltext(' ');
679679
SELECT xmltext('foo `$_-+?=*^%!|/\()[]{}');
680680
SELECT xmltext('foo & <"bar">');
681681
SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char);
682+
683+
SELECT
684+
xmldocument(
685+
xmlelement(NAME root,
686+
xmlattributes(42 AS att),
687+
xmlcomment('comment'),
688+
xmlelement(NAME foo,'<foo&bar>'),
689+
xmlelement(NAME bar, xmlconcat('va', 'lue')),
690+
xmlpi(name pi),
691+
xmlelement(NAME txt, xmltext('<"&>'))
692+
)
693+
);
694+
SELECT xmldocument(NULL);
695+
SELECT xmldocument('<foo>bar</foo>'::xml);
696+
SELECT xmldocument('foo'::xml);
697+
SELECT xmldocument('foo');
698+
SELECT xmldocument('');
699+
SELECT xmldocument(' ');
700+
SELECT xmldocument(xmlcomment('comment'));

0 commit comments

Comments
 (0)