Re: PostgreSQL vs SQL/XML Standards
Chapman Flack <chap@anastigmatix.net>
From: Chapman Flack <chap@anastigmatix.net>
To: Pavel Stehule <pavel.stehule@gmail.com>
Cc: Markus Winand <markus.winand@winand.at>,
Alvaro Herrera <alvherre@2ndquadrant.com>, Tom Lane <tgl@sss.pgh.pa.us>,
PostgreSQL Hackers <pgsql-hackers@postgresql.org>
Date: 2019-01-21T23:48:53Z
Lists: pgsql-hackers
Hi,
In two places in the XMLTABLE implementation (XmlTableFetchRow, iterating
through a nodeset returned by the row_expression, and XmlTableGetValue,
going through a nodeset returned by the column_expression), the iteration
proceeds in index order through xpathobj->nodesetval->nodeTab.
The same happens in the older xml_xpathobjtoxmlarray, producing the array
result of the xpath() function.
In <libxml/xpath.h> one finds this unsettling comment:
xmlNodePtr *nodeTab; /* array of nodes in no particular order */
So far, no matter what oddball XPath expressions I think up, nodeTab
does seem to end up in document order. It would be comforting to document
that, but the comment suggests it might not be guaranteed.
Are you aware of any statement I might have missed in the libxml docs,
where they commit to XPath evaluation returning a nodeset where nodeTab
has a predictable order? If there is a statement to that effect somewhere,
it might be worth citing in a comment in xml.c.
Regards,
-Chap
Here is a fairly oddball query, generating an XML document with about
3k names in descending order, partitioning those elements into subsets
having the same second character of the name, and unioning those back
together. You'd sort of expect that to produce a result nodeTab in goofy
order if anything could, but no, the results seem verifiably in descending
order every time, suggesting the result nodeTab is indeed being put
in document order before the XPath evaluator returns. If only they would
document that.
WITH nodeset_order_check(name, prev_name) AS (
SELECT
x, lag(x) OVER (ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
FROM
(SELECT
string_agg(DISTINCT
'x/n[substring(.,2,1) = "' || substring(proname from 2 for 1) || '"]',
'|')
FROM pg_proc) AS rowx(rowx),
(SELECT
XMLELEMENT(NAME x,
XMLAGG(XMLELEMENT(NAME n, proname) ORDER BY proname DESC))
FROM pg_proc) AS src(src),
XMLTABLE(rowx PASSING src COLUMNS x text PATH '.')
)
SELECT every(prev_name >= name IS NOT FALSE) FROM nodeset_order_check;
every
-------
t
(1 row)
Commits
-
Improve documentation about our XML functionality
- 728c49779ba8 11.6 landed
- 603a28b44973 10.11 landed
-
Improve documentation about our XML functionality.
- 12d46ac392d0 12.0 landed
-
Add volatile qualifier missed in commit 2e616dee9.
- b2b819019f44 12.0 landed
-
Fix crash with old libxml2
- 2e616dee9e60 12.0 landed
-
Fix minor deficiencies in XMLTABLE, xpath(), xmlexists()
- 251cf2e27bec 12.0 cited
-
Fix the BY {REF,VALUE} clause of XMLEXISTS/XMLTABLE
- eaaa5986ad03 12.0 landed
-
doc: Update README.links
- b060e6c1f5b4 12.0 landed
-
XPath fixes:
- 3963574d1338 8.3.0 cited