mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Make xpath() do something useful with XPath expressions that return scalars.
Previously, xpath() simply returned an empty array if the expression did not yield a node set. This is useless for expressions that return scalars, such as one with name() at the top level. Arrange to return the scalar value as a single-element xml array, instead. (String values will be suitably escaped.) This change will also cause xpath_exists() to return true, not false, for such expressions. Florian Pflug, reviewed by Radoslaw Smogura
This commit is contained in:
@ -9275,6 +9275,8 @@ SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuf
|
|||||||
against the XML value
|
against the XML value
|
||||||
<replaceable>xml</replaceable>. It returns an array of XML values
|
<replaceable>xml</replaceable>. It returns an array of XML values
|
||||||
corresponding to the node set produced by the XPath expression.
|
corresponding to the node set produced by the XPath expression.
|
||||||
|
If the XPath expression returns a scalar value rather than a node set,
|
||||||
|
a single-element array is returned.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -126,6 +126,8 @@ static bool print_xml_decl(StringInfo buf, const xmlChar *version,
|
|||||||
static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg,
|
static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg,
|
||||||
bool preserve_whitespace, int encoding);
|
bool preserve_whitespace, int encoding);
|
||||||
static text *xml_xmlnodetoxmltype(xmlNodePtr cur);
|
static text *xml_xmlnodetoxmltype(xmlNodePtr cur);
|
||||||
|
static int xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
|
||||||
|
ArrayBuildState **astate);
|
||||||
#endif /* USE_LIBXML */
|
#endif /* USE_LIBXML */
|
||||||
|
|
||||||
static StringInfo query_to_xml_internal(const char *query, char *tablename,
|
static StringInfo query_to_xml_internal(const char *query, char *tablename,
|
||||||
@ -3503,6 +3505,7 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_LIBXML
|
#ifdef USE_LIBXML
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert XML node to text (dump subtree in case of element,
|
* Convert XML node to text (dump subtree in case of element,
|
||||||
* return value otherwise)
|
* return value otherwise)
|
||||||
@ -3554,20 +3557,100 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
/*
|
||||||
|
* Convert an XML XPath object (the result of evaluating an XPath expression)
|
||||||
|
* to an array of xml values, which is returned at *astate. The function
|
||||||
|
* result value is the number of elements in the array.
|
||||||
|
*
|
||||||
|
* If "astate" is NULL then we don't generate the array value, but we still
|
||||||
|
* return the number of elements it would have had.
|
||||||
|
*
|
||||||
|
* Nodesets are converted to an array containing the nodes' textual
|
||||||
|
* representations. Primitive values (float, double, string) are converted
|
||||||
|
* to a single-element array containing the value's string representation.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
|
||||||
|
ArrayBuildState **astate)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
Datum datum;
|
||||||
|
Oid datumtype;
|
||||||
|
char *result_str;
|
||||||
|
|
||||||
|
if (astate != NULL)
|
||||||
|
*astate = NULL;
|
||||||
|
|
||||||
|
switch (xpathobj->type)
|
||||||
|
{
|
||||||
|
case XPATH_NODESET:
|
||||||
|
if (xpathobj->nodesetval != NULL)
|
||||||
|
{
|
||||||
|
result = xpathobj->nodesetval->nodeNr;
|
||||||
|
if (astate != NULL)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < result; i++)
|
||||||
|
{
|
||||||
|
datum = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
|
||||||
|
*astate = accumArrayResult(*astate, datum,
|
||||||
|
false, XMLOID,
|
||||||
|
CurrentMemoryContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
case XPATH_BOOLEAN:
|
||||||
|
if (astate == NULL)
|
||||||
|
return 1;
|
||||||
|
datum = BoolGetDatum(xpathobj->boolval);
|
||||||
|
datumtype = BOOLOID;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XPATH_NUMBER:
|
||||||
|
if (astate == NULL)
|
||||||
|
return 1;
|
||||||
|
datum = Float8GetDatum(xpathobj->floatval);
|
||||||
|
datumtype = FLOAT8OID;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XPATH_STRING:
|
||||||
|
if (astate == NULL)
|
||||||
|
return 1;
|
||||||
|
datum = CStringGetDatum((char *) xpathobj->stringval);
|
||||||
|
datumtype = CSTRINGOID;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
elog(ERROR, "xpath expression result type %d is unsupported",
|
||||||
|
xpathobj->type);
|
||||||
|
return 0; /* keep compiler quiet */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common code for scalar-value cases */
|
||||||
|
result_str = map_sql_value_to_xml_value(datum, datumtype, true);
|
||||||
|
datum = PointerGetDatum(cstring_to_xmltype(result_str));
|
||||||
|
*astate = accumArrayResult(*astate, datum,
|
||||||
|
false, XMLOID,
|
||||||
|
CurrentMemoryContext);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common code for xpath() and xmlexists()
|
* Common code for xpath() and xmlexists()
|
||||||
*
|
*
|
||||||
* Evaluate XPath expression and return number of nodes in res_items
|
* Evaluate XPath expression and return number of nodes in res_items
|
||||||
* and array of XML values in astate.
|
* and array of XML values in astate. Either of those pointers can be
|
||||||
|
* NULL if the corresponding result isn't wanted.
|
||||||
*
|
*
|
||||||
* It is up to the user to ensure that the XML passed is in fact
|
* It is up to the user to ensure that the XML passed is in fact
|
||||||
* an XML document - XPath doesn't work easily on fragments without
|
* an XML document - XPath doesn't work easily on fragments without
|
||||||
* a context node being known.
|
* a context node being known.
|
||||||
*/
|
*/
|
||||||
#ifdef USE_LIBXML
|
|
||||||
static void
|
static void
|
||||||
xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
|
xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
|
||||||
int *res_nitems, ArrayBuildState **astate)
|
int *res_nitems, ArrayBuildState **astate)
|
||||||
@ -3711,26 +3794,13 @@ xpath_internal(text *xpath_expr_text, xmltype *data, ArrayType *namespaces,
|
|||||||
xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
|
xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
|
||||||
"could not create XPath object");
|
"could not create XPath object");
|
||||||
|
|
||||||
/* return empty array in cases when nothing is found */
|
/*
|
||||||
if (xpathobj->nodesetval == NULL)
|
* Extract the results as requested.
|
||||||
*res_nitems = 0;
|
*/
|
||||||
|
if (res_nitems != NULL)
|
||||||
|
*res_nitems = xml_xpathobjtoxmlarray(xpathobj, astate);
|
||||||
else
|
else
|
||||||
*res_nitems = xpathobj->nodesetval->nodeNr;
|
(void) xml_xpathobjtoxmlarray(xpathobj, astate);
|
||||||
|
|
||||||
if (*res_nitems && astate)
|
|
||||||
{
|
|
||||||
*astate = NULL;
|
|
||||||
for (i = 0; i < xpathobj->nodesetval->nodeNr; i++)
|
|
||||||
{
|
|
||||||
Datum elem;
|
|
||||||
bool elemisnull = false;
|
|
||||||
|
|
||||||
elem = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
|
|
||||||
*astate = accumArrayResult(*astate, elem,
|
|
||||||
elemisnull, XMLOID,
|
|
||||||
CurrentMemoryContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PG_CATCH();
|
PG_CATCH();
|
||||||
{
|
{
|
||||||
|
@ -601,6 +601,42 @@ SELECT xpath('//@value', '<root value="<"/>');
|
|||||||
{<}
|
{<}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath('''<<invalid>>''', '<root/>');
|
||||||
|
xpath
|
||||||
|
---------------------------
|
||||||
|
{<<invalid>>}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
|
||||||
|
xpath
|
||||||
|
-------
|
||||||
|
{3}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
|
||||||
|
xpath
|
||||||
|
---------
|
||||||
|
{false}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
|
||||||
|
xpath
|
||||||
|
--------
|
||||||
|
{true}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
|
||||||
|
xpath
|
||||||
|
--------
|
||||||
|
{root}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath('/nosuchtag', '<root/>');
|
||||||
|
xpath
|
||||||
|
-------
|
||||||
|
{}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Test xmlexists and xpath_exists
|
-- Test xmlexists and xpath_exists
|
||||||
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
||||||
xmlexists
|
xmlexists
|
||||||
@ -614,6 +650,12 @@ SELECT xmlexists('//town[text() = ''Cwmbran'']' PASSING BY REF '<towns><town>Bid
|
|||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
|
||||||
|
xmlexists
|
||||||
|
-----------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
||||||
xpath_exists
|
xpath_exists
|
||||||
--------------
|
--------------
|
||||||
@ -626,6 +668,12 @@ SELECT xpath_exists('//town[text() = ''Cwmbran'']','<towns><town>Bidford-on-Avon
|
|||||||
t
|
t
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
|
||||||
|
xpath_exists
|
||||||
|
--------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
||||||
INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
||||||
INSERT INTO xmltest VALUES (6, '<myns:menu xmlns:myns="http://myns.com"><myns:beers><myns:name>Budvar</myns:name><myns:cost>free</myns:cost><myns:name>Carling</myns:name><myns:cost>lots</myns:cost></myns:beers></myns:menu>'::xml);
|
INSERT INTO xmltest VALUES (6, '<myns:menu xmlns:myns="http://myns.com"><myns:beers><myns:name>Budvar</myns:name><myns:cost>free</myns:cost><myns:name>Carling</myns:name><myns:cost>lots</myns:cost></myns:beers></myns:menu>'::xml);
|
||||||
|
@ -516,6 +516,42 @@ LINE 1: SELECT xpath('//@value', '<root value="<"/>');
|
|||||||
^
|
^
|
||||||
DETAIL: This functionality requires the server to be built with libxml support.
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath('''<<invalid>>''', '<root/>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath('''<<invalid>>''', '<root/>');
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath('/nosuchtag', '<root/>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath('/nosuchtag', '<root/>');
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
-- Test xmlexists and xpath_exists
|
-- Test xmlexists and xpath_exists
|
||||||
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
||||||
ERROR: unsupported XML feature
|
ERROR: unsupported XML feature
|
||||||
@ -529,6 +565,12 @@ LINE 1: ...sts('//town[text() = ''Cwmbran'']' PASSING BY REF '<towns><t...
|
|||||||
^
|
^
|
||||||
DETAIL: This functionality requires the server to be built with libxml support.
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: ...LECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>')...
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
||||||
ERROR: unsupported XML feature
|
ERROR: unsupported XML feature
|
||||||
LINE 1: ...ELECT xpath_exists('//town[text() = ''Toronto'']','<towns><t...
|
LINE 1: ...ELECT xpath_exists('//town[text() = ''Toronto'']','<towns><t...
|
||||||
@ -541,6 +583,12 @@ LINE 1: ...ELECT xpath_exists('//town[text() = ''Cwmbran'']','<towns><t...
|
|||||||
^
|
^
|
||||||
DETAIL: This functionality requires the server to be built with libxml support.
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
|
SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
|
||||||
|
ERROR: unsupported XML feature
|
||||||
|
LINE 1: SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
|
||||||
|
^
|
||||||
|
DETAIL: This functionality requires the server to be built with libxml support.
|
||||||
|
HINT: You need to rebuild PostgreSQL using --with-libxml.
|
||||||
INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
||||||
ERROR: unsupported XML feature
|
ERROR: unsupported XML feature
|
||||||
LINE 1: INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</n...
|
LINE 1: INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</n...
|
||||||
|
@ -177,12 +177,20 @@ SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="http://127.0.0.1"><loc
|
|||||||
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
|
SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
|
||||||
SELECT xpath('//text()', '<root><</root>');
|
SELECT xpath('//text()', '<root><</root>');
|
||||||
SELECT xpath('//@value', '<root value="<"/>');
|
SELECT xpath('//@value', '<root value="<"/>');
|
||||||
|
SELECT xpath('''<<invalid>>''', '<root/>');
|
||||||
|
SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
|
||||||
|
SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
|
||||||
|
SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
|
||||||
|
SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
|
||||||
|
SELECT xpath('/nosuchtag', '<root/>');
|
||||||
|
|
||||||
-- Test xmlexists and xpath_exists
|
-- Test xmlexists and xpath_exists
|
||||||
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
||||||
SELECT xmlexists('//town[text() = ''Cwmbran'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
SELECT xmlexists('//town[text() = ''Cwmbran'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
|
||||||
|
SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
|
||||||
SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
||||||
SELECT xpath_exists('//town[text() = ''Cwmbran'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
SELECT xpath_exists('//town[text() = ''Cwmbran'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
|
||||||
|
SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
|
||||||
|
|
||||||
INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
||||||
INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
|
||||||
|
Reference in New Issue
Block a user