agora inbox for [email protected]  
help / color / mirror / Atom feed
From: nobody <[email protected]>
Subject: [PATCH] Improve documentation about our XML functionality.
Date: Fri, 2 Aug 2019 22:47:10 -0400

Add a section explaining how our XML features depart from current
versions of the SQL standard.  Update and clarify the descriptions
of some XML functions.

Chapman Flack, reviewed by Ryan Lambert

Discussion: https://postgr.es/m/[email protected]
Discussion: https://postgr.es/m/[email protected]
Discussion: https://postgr.es/m/CAN-V+g-6JqUQEQZ55Q3toXEN6d5Ez5uvzL4VR+8KtvJKj31taw@mail.gmail.com

This version for backpatching PG 10, taken from Tom's commit
for 12, then edited to correctly describe behaviors that are fixed
in 12 but still broken in 10.
---
 doc/src/sgml/datatype.sgml           |   5 +
 doc/src/sgml/features.sgml           | 381 ++++++++++++++++++++++++++++++++++-
 doc/src/sgml/func.sgml               | 190 +++++++++--------
 src/backend/catalog/sql_features.txt |   6 +-
 4 files changed, 493 insertions(+), 89 deletions(-)

diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index cd5f5f0..6b9010f 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4228,6 +4228,11 @@ a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
     value is a full document or only a content fragment.
    </para>
 
+   <para>
+    Limits and compatibility notes for the <type>xml</type> data type
+    can be found in <xref linkend="xml-limits-conformance"/>.
+   </para>
+
    <sect2>
     <title>Creating XML Values</title>
    <para>
diff --git a/doc/src/sgml/features.sgml b/doc/src/sgml/features.sgml
index 6c22d69..253ec87 100644
--- a/doc/src/sgml/features.sgml
+++ b/doc/src/sgml/features.sgml
@@ -16,7 +16,8 @@
   Language SQL</quote>.  A revised version of the standard is released
   from time to time; the most recent update appearing in 2011.
   The 2011 version is referred to as ISO/IEC 9075:2011, or simply as SQL:2011.
-  The versions prior to that were SQL:2008, SQL:2003, SQL:1999, and SQL-92.  Each version
+  The versions prior to that were SQL:2008, SQL:2006, SQL:2003, SQL:1999,
+  and SQL-92.  Each version
   replaces the previous one, so claims of conformance to earlier
   versions have no official merit.
   <productname>PostgreSQL</productname> development aims for
@@ -155,4 +156,382 @@
    </para>
   </sect1>
 
+  <sect1 id="xml-limits-conformance">
+   <title>XML Limits and Conformance to SQL/XML</title>
+
+   <indexterm>
+    <primary>SQL/XML</primary>
+    <secondary>limits and conformance</secondary>
+   </indexterm>
+
+   <para>
+    Significant revisions to the XML-related specifications in ISO/IEC 9075-14
+    (SQL/XML) were introduced with SQL:2006.
+    <productname>PostgreSQL</productname>'s implementation of the XML data
+    type and related functions largely follows the earlier 2003 edition,
+    with some borrowing from later editions.  In particular:
+    <itemizedlist>
+     <listitem>
+      <para>
+       Where the current standard provides a family of XML data types
+       to hold <quote>document</quote> or <quote>content</quote> in
+       untyped or XML Schema-typed variants, and a type
+       <type>XML(SEQUENCE)</type> to hold arbitrary pieces of XML content,
+       <productname>PostgreSQL</productname> provides the single
+       <type>xml</type> type, which can hold <quote>document</quote> or
+       <quote>content</quote>.  There is no equivalent of the
+       standard's <quote>sequence</quote> type.
+      </para>
+     </listitem>
+
+     <listitem>
+      <para>
+       <productname>PostgreSQL</productname> provides two functions
+       introduced in SQL:2006, but in variants that use the XPath 1.0
+       language, rather than XML Query as specified for them in the
+       standard.
+      </para>
+     </listitem>
+    </itemizedlist>
+   </para>
+
+   <para>
+    This section presents some of the resulting differences you may encounter.
+   </para>
+
+   <sect2 id="functions-xml-limits-xpath1">
+    <title>Queries are restricted to XPath 1.0</title>
+
+    <para>
+     The <productname>PostgreSQL</productname>-specific functions
+     <function>xpath()</function> and <function>xpath_exists()</function>
+     query XML documents using the XPath language.
+     <productname>PostgreSQL</productname> also provides XPath-only variants
+     of the standard functions <function>XMLEXISTS</function> and
+     <function>XMLTABLE</function>, which officially use
+     the XQuery language. For all of these functions,
+     <productname>PostgreSQL</productname> relies on the
+     <application>libxml2</application> library, which provides only XPath 1.0.
+    </para>
+
+    <para>
+     There is a strong connection between the XQuery language and XPath
+     versions 2.0 and later: any expression that is syntactically valid and
+     executes successfully in both produces the same result (with a minor
+     exception for expressions containing numeric character references or
+     predefined entity references, which XQuery replaces with the
+     corresponding character while XPath leaves them alone).  But there is
+     no such connection between these languages and XPath 1.0; it was an
+     earlier language and differs in many respects.
+    </para>
+
+    <para>
+     There are two categories of limitation to keep in mind: the restriction
+     from XQuery to XPath for the functions specified in the SQL standard, and
+     the restriction of XPath to version 1.0 for both the standard and the
+     <productname>PostgreSQL</productname>-specific functions.
+    </para>
+
+    <sect3>
+     <title>Restriction of XQuery to XPath</title>
+
+     <para>
+      Features of XQuery beyond those of XPath include:
+
+      <itemizedlist>
+       <listitem>
+        <para>
+         XQuery expressions can construct and return new XML nodes, in
+         addition to all possible XPath values.  XPath can create and return
+         values of the atomic types (numbers, strings, and so on) but can
+         only return XML nodes that were already present in documents
+         supplied as input to the expression.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         XQuery has control constructs for iteration, sorting, and grouping.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         XQuery allows declaration and use of local functions.
+        </para>
+       </listitem>
+      </itemizedlist>
+     </para>
+
+     <para>
+      Recent XPath versions begin to offer capabilities overlapping with
+      these (such as functional-style <function>for-each</function> and
+      <function>sort</function>, anonymous functions, and
+      <function>parse-xml</function> to create a node from a string),
+      but such features were not available before XPath 3.0.
+     </para>
+    </sect3>
+
+    <sect3 id="xml-xpath-1-specifics">
+     <title>Restriction of XPath to 1.0</title>
+
+     <para>
+      For developers familiar with XQuery and XPath 2.0 or later, XPath 1.0
+      presents a number of differences to contend with:
+
+      <itemizedlist>
+       <listitem>
+        <para>
+         The fundamental type of an XQuery/XPath expression, the
+         <type>sequence</type>, which can contain XML nodes, atomic values,
+         or both, does not exist in XPath 1.0. A 1.0 expression can only
+         produce a node-set (containing zero or more XML nodes), or a single
+         atomic value.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+          Unlike an XQuery/XPath sequence, which can contain any desired
+          items in any desired order, an XPath 1.0 node-set has no
+          guaranteed order and, like any set, does not allow multiple
+          appearances of the same item.
+         <note>
+          <para>
+           The <application>libxml2</application> library does seem to
+           always return node-sets to <productname>PostgreSQL</productname>
+           with their members in the same relative order they had in the
+           input document.  Its documentation does not commit to this
+           behavior, and an XPath 1.0 expression cannot control it.
+          </para>
+         </note>
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         While XQuery/XPath provides all of the types defined in XML Schema
+         and many operators and functions over those types, XPath 1.0 has only
+         node-sets and the three atomic types <type>boolean</type>,
+         <type>double</type>, and <type>string</type>.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         XPath 1.0 has no conditional operator. An XQuery/XPath expression
+         such as <literal>if ( hat ) then hat/@size else "no hat"</literal>
+         has no XPath 1.0 equivalent.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         XPath 1.0 has no ordering comparison operator for strings. Both
+         <literal>"cat" &lt; "dog"</literal> and
+         <literal>"cat" &gt; "dog"</literal> are false, because each is a
+         numeric comparison of two <literal>NaN</literal>s. In contrast,
+         <literal>=</literal> and <literal>!=</literal> do compare the strings
+         as strings.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         XPath 1.0 blurs the distinction between
+         <firstterm>value comparisons</firstterm> and
+         <firstterm>general comparisons</firstterm> as XQuery/XPath define
+         them.  Both <literal>sale/@hatsize = 7</literal> and
+         <literal>sale/@customer = "alice"</literal> are existentially
+         quantified comparisons, true if there is
+         any <literal>sale</literal> with the given value for the
+         attribute, but <literal>sale/@taxable = false()</literal> is a
+         value comparison to the
+         <firstterm>effective boolean value</firstterm> of a whole node-set.
+         It is true only if no <literal>sale</literal> has
+         a <literal>taxable</literal> attribute at all.
+        </para>
+       </listitem>
+
+       <listitem>
+        <para>
+         In the XQuery/XPath data model, a <firstterm>document
+         node</firstterm> can have either document form (i.e., exactly one
+         top-level element, with only comments and processing instructions
+         outside of it) or content form (with those constraints
+         relaxed). Its equivalent in XPath 1.0, the
+         <firstterm>root node</firstterm>, can only be in document form.
+         This is part of the reason an <type>xml</type> value passed as the
+         context item to any <productname>PostgreSQL</productname>
+         XPath-based function must be in document form.
+        </para>
+       </listitem>
+      </itemizedlist>
+     </para>
+
+     <para>
+      The differences highlighted here are not all of them. In XQuery and
+      the 2.0 and later versions of XPath, there is an XPath 1.0 compatibility
+      mode, and the W3C lists of
+      <ulink url='https://www.w3.org/TR/2010/REC-xpath-functions-20101214/#xpath1-compatibility'>function library changes</ulink>
+      and
+      <ulink url='https://www.w3.org/TR/xpath20/#id-backwards-compatibility'>language changes</ulink>
+      applied in that mode offer a more complete (but still not exhaustive)
+      account of the differences.  The compatibility mode cannot make the
+      later languages exactly equivalent to XPath 1.0.
+     </para>
+    </sect3>
+
+    <sect3 id="functions-xml-limits-casts">
+     <title>Mappings between SQL and XML data types and values</title>
+
+     <para>
+      In SQL:2006 and later, both directions of conversion between standard SQL
+      data types and the XML Schema types are specified precisely. However, the
+      rules are expressed using the types and semantics of XQuery/XPath, and
+      have no direct application to the different data model of XPath 1.0.
+     </para>
+
+     <para>
+      When <productname>PostgreSQL</productname> maps SQL data values to XML
+      (as in <function>xmlelement</function>), or XML to SQL (as in the output
+      columns of <function>xmltable</function>), except for a few cases
+      treated specially, <productname>PostgreSQL</productname> simply assumes
+      that the XML data type's XPath 1.0 string form will be valid as the
+      text-input form of the SQL datatype, and conversely. This rule has the
+      virtue of simplicity while producing, for many data types, results similar
+      to the mappings specified in the standard. In this release,
+      an explicit cast is needed if an <function>xmltable</function> column
+      expression produces a boolean or double value; see
+      <xref linkend="functions-xml-limits-postgresql"/>.
+     </para>
+
+     <para>
+      Where interoperability with other systems is a concern, for some data
+      types, it may be necessary to use data type formatting functions (such
+      as those in <xref linkend="functions-formatting"/>) explicitly to
+      produce the standard mappings.
+     </para>
+    </sect3>
+   </sect2>
+
+   <sect2 id="functions-xml-limits-postgresql">
+    <title>
+     Incidental limits of the implementation
+    </title>
+
+    <para>
+     This section concerns limits that are not inherent in the
+     <application>libxml2</application> library, but apply to the current
+     implementation in <productname>PostgreSQL</productname>.
+    </para>
+
+    <sect3>
+     <title>
+      Cast needed for <function>xmltable</function> column
+      of boolean or double type
+     </title>
+
+     <para>
+      An <function>xmltable</function> column expression evaluating to an XPath
+      boolean or number result will produce an <quote>unexpected XPath object
+      type</quote> error. The workaround is to rewrite the column expression to
+      be inside the XPath <function>string</function> function;
+      <productname>PostgreSQL</productname> will then assign the string value
+      successfully to an SQL output column of boolean or double type.
+     </para>
+    </sect3>
+
+    <sect3>
+     <title>
+      Column path result or SQL result column of XML type
+     </title>
+
+     <para>
+      In this release, a <function>xmltable</function> column expression
+      that evaluates to an XML node-set can be assigned to an SQL result
+      column of XML type, producing a concatenation of: for most types of
+      node in the node-set, a text node containing the XPath 1.0
+      <firstterm>string-value</firstterm> of the node, but for an element node,
+      a copy of the node itself. Such a node-set may be assigned to an SQL
+      column of non-XML type only if the node-set has a single node, with the
+      string-value of most node types replaced with an empty string, the
+      string-value of an element node replaced with a concatenation of only its
+      direct text-node children (excluding those of descendants), and the
+      string-value of a text or attribute node being as defined in XPath 1.0.
+      An XPath string value assigned to a result column of XML type must be
+      parsable as XML.
+     </para>
+
+     <para>
+      It is best not to develop code that relies on these behaviors, which have
+      little resemblance to the spec, and are changed in
+      <productname>PostgreSQL 12</productname>.
+     </para>
+    </sect3>
+
+    <sect3>
+     <title>Only <literal>BY VALUE</literal> passing mechanism is supported</title>
+
+     <para>
+      The SQL standard defines two <firstterm>passing mechanisms</firstterm>
+      that apply when passing an XML argument from SQL to an XML function or
+      receiving a result: <literal>BY REF</literal>, in which a particular XML
+      value retains its node identity, and <literal>BY VALUE</literal>, in which
+      the content of the XML is passed but node identity is not preserved. A
+      mechanism can be specified before a list of parameters, as the default
+      mechanism for all of them, or after any parameter, to override the
+      default.
+     </para>
+
+     <para>
+      To illustrate the difference, if
+      <replaceable>x</replaceable> is an XML value, these two queries in
+      an SQL:2006 environment would produce true and false, respectively:
+
+<programlisting>
+SELECT XMLQUERY('$a is $b' PASSING BY REF <replaceable>x</replaceable> AS a, <replaceable>x</replaceable> AS b NULL ON EMPTY);
+SELECT XMLQUERY('$a is $b' PASSING BY VALUE <replaceable>x</replaceable> AS a, <replaceable>x</replaceable> AS b NULL ON EMPTY);
+</programlisting>
+     </para>
+
+     <para>
+      In this release, <productname>PostgreSQL</productname> will accept
+      <literal>BY REF</literal> in an
+      <function>XMLEXISTS</function> or <function>XMLTABLE</function>
+      construct, but will ignore it.  The <type>xml</type> data type holds
+      a character-string serialized representation, so there is no node
+      identity to preserve, and passing is always effectively <literal>BY
+      VALUE</literal>.
+     </para>
+    </sect3>
+
+    <sect3>
+     <title>Cannot pass named parameters to queries</title>
+
+     <para>
+      The XPath-based functions support passing one parameter to serve as the
+      XPath expression's context item, but do not support passing additional
+      values to be available to the expression as named parameters.
+     </para>
+    </sect3>
+
+    <sect3>
+     <title>No <type>XML(SEQUENCE)</type> type</title>
+
+     <para>
+      The <productname>PostgreSQL</productname> <type>xml</type> data type
+      can only hold a value in <literal>DOCUMENT</literal>
+      or <literal>CONTENT</literal> form.  An XQuery/XPath expression
+      context item must be a single XML node or atomic value, but XPath 1.0
+      further restricts it to be only an XML node, and has no node type
+      allowing <literal>CONTENT</literal>.  The upshot is that a
+      well-formed <literal>DOCUMENT</literal> is the only form of XML value
+      that <productname>PostgreSQL</productname> can supply as an XPath
+      context item.
+     </para>
+    </sect3>
+   </sect2>
+  </sect1>
+
  </appendix>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 198f9c2..a7514c0 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -9903,17 +9903,26 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
 
 
  <sect1 id="functions-xml">
+
   <title>XML Functions</title>
 
+  <indexterm>
+   <primary>XML Functions</primary>
+  </indexterm>
+
   <para>
    The functions and function-like expressions described in this
-   section operate on values of type <type>xml</type>.  Check <xref
-   linkend="datatype-xml"> for information about the <type>xml</type>
+   section operate on values of type <type>xml</type>.  See <xref
+   linkend="datatype-xml"/> for information about the <type>xml</type>
    type.  The function-like expressions <function>xmlparse</function>
    and <function>xmlserialize</function> for converting to and from
-   type <type>xml</type> are not repeated here.  Use of most of these
-   functions requires the installation to have been built
-   with <command>configure --with-libxml</>.
+   type <type>xml</type> are documented there, not in this section.
+  </para>
+
+  <para>
+   Use of most of these functions
+   requires <productname>PostgreSQL</productname> to have been built
+   with <command>configure --with-libxml</command>.
   </para>
 
   <sect2 id="functions-producing-xml">
@@ -10107,8 +10116,8 @@ SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
      encoding, depending on the setting of the configuration parameter
      <xref linkend="guc-xmlbinary">.  The particular behavior for
      individual data types is expected to evolve in order to align the
-     SQL and PostgreSQL data types with the XML Schema specification,
-     at which point a more precise description will appear.
+     PostgreSQL mappings with those specified in SQL:2006 and later,
+     as discussed in <xref linkend="functions-xml-limits-casts"/>.
     </para>
    </sect3>
 
@@ -10350,10 +10359,13 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab;
 </synopsis>
 
     <para>
-     The function <function>xmlexists</function> returns true if the
-     XPath expression in the first argument returns any nodes, and
-     false otherwise.  (If either argument is null, the result is
-     null.)
+     The function <function>xmlexists</function> evaluates an XPath 1.0
+     expression (the first argument), with the passed XML value as its context
+     item.  The function returns false if the result of that evaluation
+     yields an empty node-set, true if it yields any other value.  The
+     function returns null if any argument is null.  A nonnull value
+     passed as the context item must be an XML document, not a content
+     fragment or any non-XML value.
     </para>
 
     <para>
@@ -10369,14 +10381,14 @@ SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Tor
     </para>
 
     <para>
-     The <literal>BY REF</literal> clauses have no effect in
-     PostgreSQL, but are allowed for SQL conformance and compatibility
-     with other implementations.  Per SQL standard, the
-     first <literal>BY REF</literal> is required, the second is
-     optional.  Also note that the SQL standard specifies
-     the <function>xmlexists</function> construct to take an XQuery
-     expression as first argument, but PostgreSQL currently only
-     supports XPath, which is a subset of XQuery.
+     The <literal>BY REF</literal> clauses
+     are accepted in <productname>PostgreSQL</productname>, but are ignored,
+     as discussed in <xref linkend="functions-xml-limits-postgresql"/>.
+     In the SQL standard, the <function>xmlexists</function> function
+     evaluates an expression in the XML Query language,
+     but <productname>PostgreSQL</productname> allows only an XPath 1.0
+     expression, as discussed in
+     <xref linkend="functions-xml-limits-xpath1"/>.
     </para>
    </sect3>
 
@@ -10482,12 +10494,12 @@ SELECT xml_is_well_formed_document('<pg:foo xmlns:pg="http://postgresql.org/stuf
 </synopsis>
 
     <para>
-     The function <function>xpath</function> evaluates the XPath
-     expression <replaceable>xpath</replaceable> (a <type>text</> value)
+     The function <function>xpath</function> evaluates the XPath 1.0
+     expression <replaceable>xpath</replaceable> (a <type>text</type> value)
      against the XML value
      <replaceable>xml</replaceable>.  It returns an array of XML values
-     corresponding to the node set produced by the XPath expression.
-     If the XPath expression returns a scalar value rather than a node set,
+     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>
 
@@ -10549,9 +10561,10 @@ SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a
     <para>
      The function <function>xpath_exists</function> is a specialized form
      of the <function>xpath</function> function.  Instead of returning the
-     individual XML values that satisfy the XPath, this function returns a
-     Boolean indicating whether the query was satisfied or not.  This
-     function is equivalent to the standard <literal>XMLEXISTS</> predicate,
+     individual XML values that satisfy the XPath 1.0 expression, this function
+     returns a Boolean indicating whether the query was satisfied or not
+     (specifically, whether it produced any value other than an empty node-set).
+     This function is equivalent to the <literal>XMLEXISTS</literal> predicate,
      except that it also offers support for a namespace mapping argument.
     </para>
 
@@ -10592,8 +10605,8 @@ SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</m
 
     <para>
      The <function>xmltable</function> function produces a table based
-     on the given XML value, an XPath filter to extract rows, and an
-     optional set of column definitions.
+     on the given XML value, an XPath filter to extract rows, and a
+     set of column definitions.
     </para>
 
     <para>
@@ -10604,30 +10617,34 @@ SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</m
     </para>
 
     <para>
-     The required <replaceable>row_expression</> argument is an XPath
-     expression that is evaluated against the supplied XML document to
-     obtain an ordered sequence of XML nodes. This sequence is what
-     <function>xmltable</> transforms into output rows.
+     The required <replaceable>row_expression</replaceable> argument is
+     an XPath 1.0 expression that is evaluated, passing the
+     <replaceable>document_expression</replaceable> as its context item, to
+     obtain a set of XML nodes. These nodes are what
+     <function>xmltable</function> transforms into output rows. No rows
+     will be produced if the <replaceable>document_expression</replaceable>
+     is null, nor if the <replaceable>row_expression</replaceable> produces
+     an empty node-set or any value other than a node-set.
     </para>
 
     <para>
-     <replaceable>document_expression</> provides the XML document to
-     operate on.
-     The <literal>BY REF</literal> clauses have no effect in PostgreSQL,
-     but are allowed for SQL conformance and compatibility with other
-     implementations.
-     The argument must be a well-formed XML document; fragments/forests
-     are not accepted.
+     <replaceable>document_expression</replaceable> provides the context
+     item for the <replaceable>row_expression</replaceable>. It must be a
+     well-formed XML document; fragments/forests are not accepted.
+     The <literal>BY REF</literal> clauses
+     are accepted but ignored, as discussed in
+     <xref linkend="functions-xml-limits-postgresql"/>.
+     In the SQL standard, the <function>xmltable</function> function
+     evaluates expressions in the XML Query language,
+     but <productname>PostgreSQL</productname> allows only XPath 1.0
+     expressions, as discussed in
+     <xref linkend="functions-xml-limits-xpath1"/>.
     </para>
 
     <para>
      The mandatory <literal>COLUMNS</literal> clause specifies the list
      of columns in the output table.
-     If the <literal>COLUMNS</> clause is omitted, the rows in the result
-     set contain a single column of type <literal>xml</> containing the
-     data matched by <replaceable>row_expression</>.
-     If <literal>COLUMNS</literal> is specified, each entry describes a
-     single column.
+     Each entry describes a single column.
      See the syntax summary above for the format.
      The column name and type are required; the path, default and
      nullability clauses are optional.
@@ -10635,48 +10652,57 @@ SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</m
 
     <para>
      A column marked <literal>FOR ORDINALITY</literal> will be populated
-     with row numbers matching the order in which the
-     output rows appeared in the original input XML document.
+     with row numbers, starting with 1, in the order of nodes retrieved from
+     the <replaceable>row_expression</replaceable>'s result node-set.
      At most one column may be marked <literal>FOR ORDINALITY</literal>.
     </para>
 
+    <note>
+     <para>
+      XPath 1.0 does not specify an order for nodes in a node-set, so code
+      that relies on a particular order of the results will be
+      implementation-dependent.  Details can be found in
+      <xref linkend="xml-xpath-1-specifics"/>.
+     </para>
+    </note>
+
     <para>
-     The <literal>column_expression</> for a column is an XPath expression
-     that is evaluated for each row, relative to the result of the
-     <replaceable>row_expression</>, to find the value of the column.
-     If no <literal>column_expression</> is given, then the column name
-     is used as an implicit path.
+     The <replaceable>column_expression</replaceable> for a column is an
+     XPath 1.0 expression that is evaluated for each row, with the current
+     node from the <replaceable>row_expression</replaceable> result as its
+     context item, to find the value of the column.  If
+     no <replaceable>column_expression</replaceable> is given, then the
+     column name is used as an implicit path.
     </para>
 
     <para>
-     If a column's XPath expression returns multiple elements, an error
-     is raised.
-     If the expression matches an empty tag, the result is an
-     empty string (not <literal>NULL</>).
-     Any <literal>xsi:nil</> attributes are ignored.
+     If a column's XPath expression returns a non-XML value (limited to
+     string, boolean, or double in XPath 1.0) and the column has a
+     PostgreSQL type other than <type>xml</type>, the column will be set
+     as if by assigning the value's string representation to the PostgreSQL
+     type. In this release, an XPath boolean or double result must be explicitly
+     cast to string (that is, the XPath 1.0 <function>string</function> function
+     wrapped around the original column expression);
+     <productname>PostgreSQL</productname> can then successfully assign the
+     string to an SQL result column of boolean or double type.
+     These conversion rules differ from those of the SQL
+     standard, as discussed in <xref linkend="functions-xml-limits-casts"/>.
     </para>
 
     <para>
-     The text body of the XML matched by the <replaceable>column_expression</>
-     is used as the column value. Multiple <literal>text()</literal> nodes
-     within an element are concatenated in order. Any child elements,
-     processing instructions, and comments are ignored, but the text contents
-     of child elements are concatenated to the result.
-     Note that the whitespace-only <literal>text()</> node between two non-text
-     elements is preserved, and that leading whitespace on a <literal>text()</>
-     node is not flattened.
+     In this release, SQL result columns of <type>xml</type> type, or
+     column XPath expressions evaluating to an XML type, regardless of the
+     output column SQL type, are handled as described in
+     <xref linkend="functions-xml-limits-postgresql"/>; the behavior
+     changes significantly in <productname>PostgreSQL 12</productname>.
     </para>
 
     <para>
-     If the path expression does not match for a given row but
-     <replaceable>default_expression</> is specified, the value resulting
-     from evaluating that expression is used.
-     If no <literal>DEFAULT</> clause is given for the column,
-     the field will be set to <literal>NULL</>.
-     It is possible for a <replaceable>default_expression</> to reference
-     the value of output columns that appear prior to it in the column list,
-     so the default of one column may be based on the value of another
-     column.
+     If the path expression returns an empty node-set
+     (typically, when it does not match)
+     for a given row, the column will be set to <literal>NULL</literal>, unless
+     a <replaceable>default_expression</replaceable> is specified; then the
+     value resulting from evaluating that expression is used.
     </para>
 
     <para>
@@ -10688,20 +10714,14 @@ SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</m
     </para>
 
     <para>
-     Unlike regular PostgreSQL functions, <replaceable>column_expression</>
-     and <replaceable>default_expression</> are not evaluated to a simple
-     value before calling the function.
-     <replaceable>column_expression</> is normally evaluated
-     exactly once per input row, and <replaceable>default_expression</>
-     is evaluated each time a default is needed for a field.
-     If the expression qualifies as stable or immutable the repeat
+     A <replaceable>default_expression</replaceable>, rather than being
+     evaluated immediately when <function>xmltable</function> is called,
+     is evaluated each time a default is needed for the column.
+     If the expression qualifies as stable or immutable, the repeat
      evaluation may be skipped.
-     Effectively <function>xmltable</> behaves more like a subquery than a
-     function call.
      This means that you can usefully use volatile functions like
-     <function>nextval</> in <replaceable>default_expression</>, and
-     <replaceable>column_expression</> may depend on other parts of the
-     XML document.
+     <function>nextval</function> in
+     <replaceable>default_expression</replaceable>.
     </para>
 
     <para>
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
index 8e746f3..ccd3450 100644
--- a/src/backend/catalog/sql_features.txt
+++ b/src/backend/catalog/sql_features.txt
@@ -593,7 +593,7 @@ X085	Predefined namespace prefixes			NO
 X086	XML namespace declarations in XMLTable			NO	
 X090	XML document predicate			YES	
 X091	XML content predicate			NO	
-X096	XMLExists			NO	XPath only
+X096	XMLExists			NO	XPath 1.0 only
 X100	Host language support for XML: CONTENT option			NO	
 X101	Host language support for XML: DOCUMENT option			NO	
 X110	Host language support for XML: VARCHAR mapping			NO	
@@ -661,11 +661,11 @@ X282	XMLValidate with CONTENT option			NO
 X283	XMLValidate with SEQUENCE option			NO	
 X284	XMLValidate: NAMESPACE without ELEMENT clause			NO	
 X286	XMLValidate: NO NAMESPACE with ELEMENT clause			NO	
-X300	XMLTable			NO	XPath only
+X300	XMLTable			NO	XPath 1.0 only
 X301	XMLTable: derived column list option			YES	
 X302	XMLTable: ordinality column option			YES	
 X303	XMLTable: column default option			YES	
-X304	XMLTable: passing a context item			YES	
+X304	XMLTable: passing a context item			YES	must be XML DOCUMENT
 X305	XMLTable: initializing an XQuery variable			NO	
 X400	Name and identifier mapping			YES	
 X410	Alter column data type: XML type			YES	
-- 
2.7.3


--------------060806070207090601090509--





view thread (9+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected]
  Subject: Re: [PATCH] Improve documentation about our XML functionality.
  In-Reply-To: <no-message-id-1882115@localhost>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox