OSDN Git Service

Put documentation on XML data type and functions in better positions. Add
authorPeter Eisentraut <peter_e@gmx.net>
Mon, 2 Apr 2007 15:27:02 +0000 (15:27 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Mon, 2 Apr 2007 15:27:02 +0000 (15:27 +0000)
some index terms.

doc/src/sgml/config.sgml
doc/src/sgml/datatype.sgml
doc/src/sgml/func.sgml

index 07d1a87..57a618f 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.118 2007/03/26 01:41:57 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.119 2007/04/02 15:27:02 petere Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -3591,7 +3591,7 @@ SELECT * FROM parent WHERE key = 2400;
        <primary><varname>SET XML OPTION</></primary>
       </indexterm>
       <indexterm>
-       <primary><varname>XML option</></primary>
+       <primary>XML option</primary>
       </indexterm>
       <listitem>
        <para>
index 1bf103c..9e95f95 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.192 2007/04/02 03:49:36 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.193 2007/04/02 15:27:02 petere Exp $ -->
 
  <chapter id="datatype">
   <title id="datatype-title">Data Types</title>
@@ -3190,6 +3190,144 @@ SELECT * FROM test;
 
   </sect1>
 
+  <sect1 id="datatype-xml">
+   <title><acronym>XML</> Type</title>
+
+   <indexterm zone="datatype-xml">
+    <primary>XML</primary>
+   </indexterm>
+
+   <para>
+    The data type <type>xml</type> can be used to store XML data.  Its
+    advantage over storing XML data in a <type>text</type> field is that it
+    checks the input values for well-formedness, and there are support
+    functions to perform type-safe operations on it; see <xref
+    linkend="functions-xml">.
+   </para>
+
+   <para>
+    In particular, the <type>xml</type> type can store well-formed
+    <quote>documents</quote>, as defined by the XML standard, as well
+    as <quote>content</quote> fragments, which are defined by the
+    production <literal>XMLDecl? content</literal> in the XML
+    standard.  Roughly, this means that content fragments can have
+    more than one top-level element or character node.  The expression
+    <literal><replaceable>xmlvalue</replaceable> IS DOCUMENT</literal>
+    can be used to evaluate whether a particular <type>xml</type>
+    value is a full document or only a content fragment.
+   </para>
+
+   <para>
+    To produce a value of type <type>xml</type> from character data,
+    use the function
+    <function>xmlparse</function>:<indexterm><primary>xmlparse</primary></indexterm>
+<synopsis>
+XMLPARSE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable>)
+</synopsis>
+    Examples:
+<programlisting><![CDATA[
+XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter><book>')
+XMLPARSE (CONTENT 'abc<foo>bar</bar><bar>foo</foo>')
+]]></programlisting>
+    While this is the only way to convert character strings into XML
+    values according to the SQL standard, the PostgreSQL-specific
+    syntaxes:
+<programlisting><![CDATA[
+xml '<foo>bar</foo>'
+'<foo>bar</foo>'::xml
+]]></programlisting>
+    can also be used.
+   </para>
+
+   <para>
+    The <type>xml</type> type does not validate its input values
+    against a possibly included document type declaration
+    (DTD).<indexterm><primary>DTD</primary></indexterm>
+   </para>
+
+   <para>
+    The inverse operation, producing character string type values from
+    <type>xml</type>, uses the function
+    <function>xmlserialize</function>:<indexterm><primary>xmlserialize</primary></indexterm>
+<synopsis>
+XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <replaceable>type</replaceable> )
+</synopsis>
+    <replaceable>type</replaceable> can be one of
+    <type>character</type>, <type>character varying</type>, or
+    <type>text</type> (or an alias name for those).  Again, according
+    to the SQL standard, this is the only way to convert between type
+    <type>xml</type> and character types, but PostgreSQL also allows
+    you to simply cast the value.
+   </para>
+
+   <para>
+    When character string values are cast to or from type
+    <type>xml</type> without going through <type>XMLPARSE</type> or
+    <type>XMLSERIALIZE</type>, respectively, the choice of
+    <literal>DOCUMENT</literal> versus <literal>CONTENT</literal> is
+    determined by the <quote>XML option</quote>
+    <indexterm><primary>XML option</primary></indexterm>
+    session configuration parameter, which can be set using the
+    standard command
+<synopsis>
+SET XML OPTION { DOCUMENT | CONTENT };
+</synopsis>
+    or the more PostgreSQL-like syntax
+<synopsis>
+SET xmloption TO { DOCUMENT | CONTENT };
+</synopsis>
+    The default is <literal>CONTENT</literal>, so all forms of XML
+    data are allowed.
+   </para>
+
+   <para>
+    Care must be taken when dealing with multiple character encodings
+    on the client, server, and in the XML data passed through them.
+    When using the text mode to pass queries to the server and query
+    results to the client (which is the normal mode), PostgreSQL
+    converts all character data passed between the client and the
+    server and vice versa to the character encoding of the respective
+    end; see <xref linkend="multibyte">.  This includes string
+    representations of XML values, such as in the above examples.
+    This would ordinarily mean that encoding declarations contained in
+    XML data might become invalid as the character data is converted
+    to other encodings while travelling between client and server,
+    while the embedded encoding declaration is not changed.  To cope
+    with this behavior, an encoding declaration contained in a
+    character string presented for input to the <type>xml</type> type
+    is <emphasis>ignored</emphasis>, and the content is always assumed
+    to be in the current server encoding.  Consequently, for correct
+    processing, such character strings of XML data must be sent off
+    from the client in the current client encoding.  It is the
+    responsibility of the client to either convert the document to the
+    current client encoding before sending it off to the server or to
+    adjust the client encoding appropriately.  On output, values of
+    type <type>xml</type> will not have an encoding declaration, and
+    clients must assume that the data is in the current client
+    encoding.
+   </para>
+
+   <para>
+    When using the binary mode to pass query parameters to the server
+    and query results back the the client, no character set conversion
+    is performed, so the situation is different.  In this case, an
+    encoding declaration in the XML data will be observed, and if it
+    is absent, the data will be assumed to be in UTF-8 (as required by
+    the XML standard; note that PostgreSQL does not support UTF-16 at
+    all).  On output, data will have an encoding declaration
+    specifying the client encoding, unless the client encoding is
+    UTF-8, in which case it will be omitted.
+   </para>
+
+   <para>
+    Needless to say, processing XML data with PostgreSQL will be less
+    error-prone and more efficient if data encoding, client encoding,
+    and server encoding are the same.  Since XML data is internally
+    processed in UTF-8, computations will be most efficient if the
+    server encoding is also UTF-8.
+   </para>
+  </sect1>
+
   &array;
 
   &rowtypes;
@@ -3579,138 +3717,4 @@ SELECT * FROM pg_attribute
 
   </sect1>
 
-  <sect1 id="datatype-xml">
-   <title><acronym>XML</> Type</title>
-
-   <indexterm zone="datatype-xml">
-    <primary>XML</primary>
-   </indexterm>
-
-   <para>
-    The data type <type>xml</type> can be used to store XML data.  Its
-    advantage over storing XML data in a <type>text</type> field is that it
-    checks the input values for well-formedness, and there are support
-    functions to perform type-safe operations on it; see <xref
-    linkend="functions-xml">.
-   </para>
-
-   <para>
-    In particular, the <type>xml</type> type can store well-formed
-    <quote>documents</quote>, as defined by the XML standard, as well
-    as <quote>content</quote> fragments, which are defined by the
-    production <literal>XMLDecl? content</literal> in the XML
-    standard.  Roughly, this means that content fragments can have
-    more than one top-level element or character node.  The expression
-    <literal><replaceable>xmlvalue</replaceable> IS DOCUMENT</literal>
-    can be used to evaluate whether a particular <type>xml</type>
-    value is a full document or only a content fragment.
-   </para>
-
-   <para>
-    To produce a value of type <type>xml</type> from character data,
-    use the function <function>xmlparse</function>:
-<synopsis>
-XMLPARSE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable>)
-</synopsis>
-    Examples:
-<programlisting><![CDATA[
-XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter><book>')
-XMLPARSE (CONTENT 'abc<foo>bar</bar><bar>foo</foo>')
-]]></programlisting>
-    While this is the only way to convert character strings into XML
-    values according to the SQL standard, the PostgreSQL-specific
-    syntaxes:
-<programlisting><![CDATA[
-xml '<foo>bar</foo>'
-'<foo>bar</foo>'::xml
-]]></programlisting>
-    can also be used.
-   </para>
-
-   <para>
-    The <type>xml</type> type does not validate its input values
-    against a possibly included document type declaration (DTD).
-   </para>
-
-   <para>
-    The inverse operation, producing character string type values from
-    <type>xml</type>, uses the function
-    <function>xmlserialize</function>:
-<synopsis>
-XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <replaceable>type</replaceable> )
-</synopsis>
-    <replaceable>type</replaceable> can be one of
-    <type>character</type>, <type>character varying</type>, or
-    <type>text</type> (or an alias name for those).  Again, according
-    to the SQL standard, this is the only way to convert between type
-    <type>xml</type> and character types, but PostgreSQL also allows
-    you to simply cast the value.
-   </para>
-
-   <para>
-    When character string values are cast to or from type
-    <type>xml</type> without going through <type>XMLPARSE</type> or
-    <type>XMLSERIALIZE</type>, respectively, the choice of
-    <literal>DOCUMENT</literal> versus <literal>CONTENT</literal> is
-    determined by the <quote>XML option</quote> session configuration
-    parameter, which can be set using the standard command
-<synopsis>
-SET XML OPTION { DOCUMENT | CONTENT };
-</synopsis>
-    or the more PostgreSQL-like syntax
-<synopsis>
-SET xmloption TO { DOCUMENT | CONTENT };
-</synopsis>
-    The default is <literal>CONTENT</literal>, so all forms of XML
-    data are allowed.
-   </para>
-
-   <para>
-    Care must be taken when dealing with multiple character encodings
-    on the client, server, and in the XML data passed through them.
-    When using the text mode to pass queries to the server and query
-    results to the client (which is the normal mode), PostgreSQL
-    converts all character data passed between the client and the
-    server and vice versa to the character encoding of the respective
-    end; see <xref linkend="multibyte">.  This includes string
-    representations of XML values, such as in the above examples.
-    This would ordinarily mean that encoding declarations contained in
-    XML data might become invalid as the character data is converted
-    to other encodings while travelling between client and server,
-    while the embedded encoding declaration is not changed.  To cope
-    with this behavior, an encoding declaration contained in a
-    character string presented for input to the <type>xml</type> type
-    is <emphasis>ignored</emphasis>, and the content is always assumed
-    to be in the current server encoding.  Consequently, for correct
-    processing, such character strings of XML data must be sent off
-    from the client in the current client encoding.  It is the
-    responsibility of the client to either convert the document to the
-    current client encoding before sending it off to the server or to
-    adjust the client encoding appropriately.  On output, values of
-    type <type>xml</type> will not have an encoding declaration, and
-    clients must assume that the data is in the current client
-    encoding.
-   </para>
-
-   <para>
-    When using the binary mode to pass query parameters to the server
-    and query results back the the client, no character set conversion
-    is performed, so the situation is different.  In this case, an
-    encoding declaration in the XML data will be observed, and if it
-    is absent, the data will be assumed to be in UTF-8 (as required by
-    the XML standard; note that PostgreSQL does not support UTF-16 at
-    all).  On output, data will have an encoding declaration
-    specifying the client encoding, unless the client encoding is
-    UTF-8, in which case it will be omitted.
-   </para>
-
-   <para>
-    Needless to say, processing XML data with PostgreSQL will be less
-    error-prone and more efficient if data encoding, client encoding,
-    and server encoding are the same.  Since XML data is internally
-    processed in UTF-8, computations will be most efficient if the
-    server encoding is also UTF-8.
-   </para>
-  </sect1>
-
  </chapter>
index 0baf152..cc872d8 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.373 2007/04/02 03:49:36 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.374 2007/04/02 15:27:02 petere Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -7502,4302 +7502,4308 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
   </sect1>
 
 
- <sect1 id="functions-sequence">
-  <title>Sequence Manipulation Functions</title>
-
-  <indexterm>
-   <primary>sequence</primary>
-  </indexterm>
-  <indexterm>
-   <primary>nextval</primary>
-  </indexterm>
-  <indexterm>
-   <primary>currval</primary>
-  </indexterm>
-  <indexterm>
-   <primary>lastval</primary>
-  </indexterm>
-  <indexterm>
-   <primary>setval</primary>
-  </indexterm>
+ <sect1 id="functions-xml">
+  <title>XML Functions</title>
 
   <para>
-   This section describes <productname>PostgreSQL</productname>'s functions
-   for operating on <firstterm>sequence objects</firstterm>.
-   Sequence objects (also called sequence generators or
-   just sequences) are special single-row tables created with
-   <command>CREATE SEQUENCE</command>.  A sequence object is usually used to
-   generate unique identifiers for rows of a table.  The sequence functions,
-   listed in <xref linkend="functions-sequence-table">,
-   provide simple, multiuser-safe methods for obtaining successive
-   sequence values from sequence objects.
+   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>
+   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.
   </para>
 
-   <table id="functions-sequence-table">
-    <title>Sequence Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Function</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
-
-     <tbody>
-      <row>
-        <entry><literal><function>currval</function>(<type>regclass</type>)</literal></entry>
-        <entry><type>bigint</type></entry>
-        <entry>Return value most recently obtained with
-        <function>nextval</function> for specified sequence</entry>
-      </row>
-      <row>
-        <entry><literal><function>nextval</function>(<type>regclass</type>)</literal></entry>
-        <entry><type>bigint</type></entry>
-        <entry>Advance sequence and return new value</entry>
-      </row>
-      <row>
-        <entry><literal><function>setval</function>(<type>regclass</type>, <type>bigint</type>)</literal></entry>
-        <entry><type>bigint</type></entry>
-        <entry>Set sequence's current value</entry>
-      </row>
-      <row>
-        <entry><literal><function>setval</function>(<type>regclass</type>, <type>bigint</type>, <type>boolean</type>)</literal></entry>
-        <entry><type>bigint</type></entry>
-        <entry>Set sequence's current value and <literal>is_called</literal> flag</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
-
-  <para>
-   The sequence to be operated on by a sequence-function call is specified by
-   a <type>regclass</> argument, which is just the OID of the sequence in the
-   <structname>pg_class</> system catalog.  You do not have to look up the
-   OID by hand, however, since the <type>regclass</> data type's input
-   converter will do the work for you.  Just write the sequence name enclosed
-   in single quotes, so that it looks like a literal constant.  To
-   achieve some compatibility with the handling of ordinary
-   <acronym>SQL</acronym> names, the string will be converted to lowercase
-   unless it contains double quotes around the sequence name.  Thus:
-<programlisting>
-nextval('foo')      <lineannotation>operates on sequence <literal>foo</literal></>
-nextval('FOO')      <lineannotation>operates on sequence <literal>foo</literal></>
-nextval('"Foo"')    <lineannotation>operates on sequence <literal>Foo</literal></>
-</programlisting>
-   The sequence name can be schema-qualified if necessary:
-<programlisting>
-nextval('myschema.foo')     <lineannotation>operates on <literal>myschema.foo</literal></>
-nextval('"myschema".foo')   <lineannotation>same as above</lineannotation>
-nextval('foo')              <lineannotation>searches search path for <literal>foo</literal></>
-</programlisting>
-   See <xref linkend="datatype-oid"> for more information about
-   <type>regclass</>.
-  </para>
+  <sect2>
+   <title>Producing XML Content</title>
 
-  <note>
    <para>
-    Before <productname>PostgreSQL</productname> 8.1, the arguments of the
-    sequence functions were of type <type>text</>, not <type>regclass</>, and
-    the above-described conversion from a text string to an OID value would
-    happen at run time during each call.  For backwards compatibility, this
-    facility still exists, but internally it is now handled as an implicit
-    coercion from <type>text</> to <type>regclass</> before the function is
-    invoked.
+    A set of functions and function-like expressions are available for
+    producing XML content from SQL data.  As such, they are
+    particularly suitable for formatting query results into XML
+    documents for processing in client applications.
    </para>
 
-   <para>
-    When you write the argument of a sequence function as an unadorned
-    literal string, it becomes a constant of type <type>regclass</>.
-    Since this is really just an OID, it will track the originally
-    identified sequence despite later renaming, schema reassignment,
-    etc.  This <quote>early binding</> behavior is usually desirable for
-    sequence references in column defaults and views.  But sometimes you will
-    want <quote>late binding</> where the sequence reference is resolved
-    at run time.  To get late-binding behavior, force the constant to be
-    stored as a <type>text</> constant instead of <type>regclass</>:
-<programlisting>
-nextval('foo'::text)      <lineannotation><literal>foo</literal> is looked up at runtime</>
-</programlisting>
-    Note that late binding was the only behavior supported in
-    <productname>PostgreSQL</productname> releases before 8.1, so you
-    might need to do this to preserve the semantics of old applications.
-   </para>
+   <sect3>
+    <title><literal>xmlcomment</literal></title>
 
-   <para>
-    Of course, the argument of a sequence function can be an expression
-    as well as a constant.  If it is a text expression then the implicit
-    coercion will result in a run-time lookup.
-   </para>
-  </note>
+    <indexterm>
+     <primary>xmlcomment</primary>
+    </indexterm>
 
-  <para>
-   The available sequence functions are:
+<synopsis>
+<function>xmlcomment</function>(<replaceable>text</replaceable>)
+</synopsis>
 
-    <variablelist>
-     <varlistentry>
-      <term><function>nextval</function></term>
-      <listitem>
-       <para>
-        Advance the sequence object to its next value and return that
-        value.  This is done atomically: even if multiple sessions
-        execute <function>nextval</function> concurrently, each will safely receive
-        a distinct sequence value.
-       </para>
-      </listitem>
-     </varlistentry>
+    <para>
+     The function <function>xmlcomment</function> creates an XML value
+     containing an XML comment with the specified text as content.
+     The text cannot contain <literal>--</literal> or end with a
+     <literal>-</literal> so that the resulting construct is a valid
+     XML comment.  If the argument is null, the result is null.
+    </para>
 
-     <varlistentry>
-      <term><function>currval</function></term>
-      <listitem>
-       <para>
-        Return the value most recently obtained by <function>nextval</function>
-        for this sequence in the current session.  (An error is
-        reported if <function>nextval</function> has never been called for this
-        sequence in this session.)  Notice that because this is returning
-        a session-local value, it gives a predictable answer whether or not
-        other sessions have executed <function>nextval</function> since the
-        current session did.
-       </para>
-      </listitem>
-     </varlistentry>
+    <para>
+     Example:
+<screen><![CDATA[
+SELECT xmlcomment('hello');
 
-     <varlistentry>
-      <term><function>lastval</function></term>
-      <listitem>
-       <para>
-        Return the value most recently returned by
-        <function>nextval</> in the current session. This function is
-        identical to <function>currval</function>, except that instead
-        of taking the sequence name as an argument it fetches the
-        value of the last sequence that <function>nextval</function>
-        was used on in the current session. It is an error to call
-        <function>lastval</function> if <function>nextval</function>
-        has not yet been called in the current session.
-       </para>
-      </listitem>
-     </varlistentry>
+  xmlcomment
+--------------
+ <!--hello-->
+]]></screen>
+    </para>
+   </sect3>
 
-     <varlistentry>
-      <term><function>setval</function></term>
-      <listitem>
-       <para>
-        Reset the sequence object's counter value.  The two-parameter
-        form sets the sequence's <literal>last_value</literal> field to the specified
-        value and sets its <literal>is_called</literal> field to <literal>true</literal>,
-        meaning that the next <function>nextval</function> will advance the sequence
-        before returning a value.  In the three-parameter form,
-        <literal>is_called</literal> can be set either <literal>true</literal> or
-        <literal>false</literal>.  If it's set to <literal>false</literal>,
-        the next <function>nextval</function> will return exactly the specified
-        value, and sequence advancement commences with the following
-        <function>nextval</function>.  For example,
+   <sect3>
+    <title><literal>xmlconcat</literal></title>
 
-<screen>
-SELECT setval('foo', 42);           <lineannotation>Next <function>nextval</> will return 43</lineannotation>
-SELECT setval('foo', 42, true);     <lineannotation>Same as above</lineannotation>
-SELECT setval('foo', 42, false);    <lineannotation>Next <function>nextval</> will return 42</lineannotation>
-</screen>
+    <indexterm>
+     <primary>xmlconcat</primary>
+    </indexterm>
 
-        The result returned by <function>setval</function> is just the value of its
-        second argument.
-       </para>
-      </listitem>
-     </varlistentry>
-    </variablelist>
-  </para>
+ <synopsis>
+ <function>xmlconcat</function>(<replaceable>xml</replaceable><optional>, ...</optional>)
+ </synopsis>
+    <para>
+     The function <function>xmlconcat</function> concatenates a list
+     of individual XML values to create a single value containing an
+     XML content fragment.  Null values are omitted; the result is
+     only null if there are no nonnull arguments.
+    </para>
 
-  <para>
-   If a sequence object has been created with default parameters,
-   <function>nextval</function> calls on it will return successive values
-   beginning with 1.  Other behaviors can be obtained by using
-   special parameters in the <xref linkend="sql-createsequence" endterm="sql-createsequence-title"> command;
-   see its command reference page for more information.
-  </para>
+    <para>
+     Example:
+<screen><![CDATA[
+SELECT xmlconcat('<abc/>', '<bar>foo</bar>');
 
-  <important>
-   <para>
-    To avoid blocking of concurrent transactions that obtain numbers from the
-    same sequence, a <function>nextval</function> operation is never rolled back;
-    that is, once a value has been fetched it is considered used, even if the
-    transaction that did the <function>nextval</function> later aborts.  This means
-    that aborted transactions might leave unused <quote>holes</quote> in the
-    sequence of assigned values.  <function>setval</function> operations are never
-    rolled back, either.
-   </para>
-  </important>
+      xmlconcat
+----------------------
+ <abc/><bar>foo</bar>
+]]></screen>
+    </para>
 
- </sect1>
+    <para>
+     XML declarations, if present are combined as follows.  If all
+     argument values have the same XML version declaration, that
+     version is used in the result, else no version is used.  If all
+     argument values have the standalone declaration value
+     <quote>yes</quote>, then that value is used in the result.  If
+     all argument values have a standalone declaration value and at
+     least one is <quote>no</quote>, then that is used in the result.
+     Else the result will have no standalone declaration.  If the
+     result is determined to require a standalone declaration but no
+     version declaration, a version declaration with version 1.0 will
+     be used because XML requires an XML declaration to contain a
+     version declaration.  Encoding declarations are ignored and
+     removed in all cases.
+    </para>
 
+    <para>
+     Example:
+<screen><![CDATA[
+SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone="no"?><bar/>');
 
- <sect1 id="functions-conditional">
-  <title>Conditional Expressions</title>
+             xmlconcat
+-----------------------------------
+ <?xml version="1.1"?><foo/><bar/>
+]]></screen>
+    </para>
+   </sect3>
+   <sect3>
+    <title><literal>xmlelement</literal></title>
+   <indexterm>
+    <primary>xmlelement</primary>
+   </indexterm>
+<synopsis>
+ <function>xmlelement</function>(name <replaceable>name</replaceable> <optional>, xmlattributes(<replaceable>value</replaceable> <optional>AS <replaceable>attname</replaceable></optional> <optional>, ... </optional>)</optional> <optional><replaceable>, content, ...</replaceable></optional>)
+ </synopsis>
+    <para>
+     The <function>xmlelement</function> expression produces an XML
+     element with the given name, attributes, and content.
+    </para>
 
-  <indexterm>
-   <primary>CASE</primary>
-  </indexterm>
+    <para>
+     Examples:
+<screen><![CDATA[
+SELECT xmlelement(name foo);
 
-  <indexterm>
-   <primary>conditional expression</primary>
 </indexterm>
+ xmlelement
+------------
<foo/>
 
-  <para>
-   This section describes the <acronym>SQL</acronym>-compliant conditional expressions
-   available in <productname>PostgreSQL</productname>.
-  </para>
+SELECT xmlelement(name foo, xmlattributes('xyz' as bar));
 
-  <tip>
-   <para>
-    If your needs go beyond the capabilities of these conditional
-    expressions you might want to consider writing a stored procedure
-    in a more expressive programming language.
-   </para>
-  </tip>
+    xmlelement
+------------------
+ <foo bar="xyz"/>
 
-  <sect2>
-   <title><literal>CASE</></title>
+SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'cont', 'ent');
 
-  <para>
-   The <acronym>SQL</acronym> <token>CASE</token> expression is a
-   generic conditional expression, similar to if/else statements in
-   other languages:
+             xmlelement
+-------------------------------------
+ <foo bar="2007-01-26">content</foo>
+]]></screen>
+    </para>
 
-<synopsis>
-CASE WHEN <replaceable>condition</replaceable> THEN <replaceable>result</replaceable>
-     <optional>WHEN ...</optional>
-     <optional>ELSE <replaceable>result</replaceable></optional>
-END
-</synopsis>
+    <para>
+     Element and attribute names that are not valid XML names are
+     escaped by replacing the offending characters by the sequence
+     <literal>_x<replaceable>HHHH</replaceable>_</literal>, where
+     <replaceable>HHHH</replaceable> is the character's Unicode
+     codepoint in hexadecimal notation.  For example:
+<screen><![CDATA[
+SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));
 
-   <token>CASE</token> clauses can be used wherever
-   an expression is valid.  <replaceable>condition</replaceable> is an
-   expression that returns a <type>boolean</type> result.  If the result is true
-   then the value of the <token>CASE</token> expression is the
-   <replaceable>result</replaceable> that follows the condition.  If the result is false any
-   subsequent <token>WHEN</token> clauses are searched in the same
-   manner.  If no <token>WHEN</token>
-   <replaceable>condition</replaceable> is true then the value of the
-   case expression is the <replaceable>result</replaceable> in the
-   <token>ELSE</token> clause.  If the <token>ELSE</token> clause is
-   omitted and no condition matches, the result is null.
-  </para>
+            xmlelement
+----------------------------------
+ <foo_x0024_bar a_x0026_b="xyz"/>
+]]></screen>
+    </para>
 
-   <para>
-    An example:
+    <para>
+     An explicit attribute name need not be specified if the attribute
+     value is a column reference, in which case the column's name will
+     be used as attribute name by default.  In any other case, the
+     attribute must be given an explicit name.  So this example is
+     valid:
 <screen>
-SELECT * FROM test;
+CREATE TABLE test (a xml, b xml);
+SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;
+</screen>
+     But these are not:
+<screen>
+SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test;
+SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test;
+</screen>
+    </para>
 
- a
----
- 1
- 2
- 3
+    <para>
+     Element content, if specified, will be formatted according to
+     data type.  If the content is itself of type <type>xml</type>,
+     complex XML documents can be constructed.  For example:
+<screen><![CDATA[
+SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
+                            xmlelement(name abc),
+                            xmlcomment('test'),
+                            xmlelement(name xyz));
 
+                  xmlelement
+----------------------------------------------
+ <foo bar="xyz"><abc/><!--test--><xyz/></foo>
+]]></screen>
 
-SELECT a,
-       CASE WHEN a=1 THEN 'one'
-            WHEN a=2 THEN 'two'
-            ELSE 'other'
-       END
-    FROM test;
+     Content of other types will be formatted into valid XML character
+     data.  This means in particular that the characters &lt;, &gt;,
+     and &amp; will be converted to entities.  Binary data (data type
+     <type>bytea</type>) will be represented in base64 or hex
+     encoding, depending on the setting of the configuration parameter
+     <xref linkend="guc-xmlbinary">.  The particular behavior for
+     individual data types is expected 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.
+    </para>
+   </sect3>
+   <sect3>
+    <title><literal>xmlforest</literal></title>
+   <indexterm>
+    <primary>xmlforest</primary>
+   </indexterm>
+ <synopsis>
+ <function>xmlforest</function>(<replaceable>content</replaceable> <optional>AS <replaceable>name</replaceable></optional> <optional>, ...</optional>)
+ </synopsis>
+    <para>
+     The <function>xmlforest</function> expression produces an XML
+     forest (sequence) of elements using the given names and content.
+    </para>
 
- a | case
----+-------
- 1 | one
- 2 | two
- 3 | other
-</screen>
-   </para>
+    <para>
+     Examples:
+<screen><![CDATA[
+SELECT xmlforest('abc' AS foo, 123 AS bar);
 
-  <para>
-   The data types of all the <replaceable>result</replaceable>
-   expressions must be convertible to a single output type.
-   See <xref linkend="typeconv-union-case"> for more detail.
-  </para>
+          xmlforest
+------------------------------
+ <foo>abc</foo><bar>123</bar>
 
-  <para>
-   The following <quote>simple</quote> <token>CASE</token> expression is a
-   specialized variant of the general form above:
 
-<synopsis>
-CASE <replaceable>expression</replaceable>
-    WHEN <replaceable>value</replaceable> THEN <replaceable>result</replaceable>
-    <optional>WHEN ...</optional>
-    <optional>ELSE <replaceable>result</replaceable></optional>
-END
-</synopsis>
+SELECT xmlforest(table_name, column_name) FROM information_schema.columns WHERE table_schema = 'pg_catalog';
 
-   The
-   <replaceable>expression</replaceable> is computed and compared to
-   all the <replaceable>value</replaceable> specifications in the
-   <token>WHEN</token> clauses until one is found that is equal.  If
-   no match is found, the <replaceable>result</replaceable> in the
-   <token>ELSE</token> clause (or a null value) is returned.  This is similar
-   to the <function>switch</function> statement in C.
-  </para>
+                                         xmlforest
+-------------------------------------------------------------------------------------------
+ <table_name>pg_authid</table_name><column_name>rolname</column_name>
+ <table_name>pg_authid</table_name><column_name>rolsuper</column_name>
+ ...
+]]></screen>
 
-   <para>
-    The example above can be written using the simple
-    <token>CASE</token> syntax:
-<screen>
-SELECT a,
-       CASE a WHEN 1 THEN 'one'
-              WHEN 2 THEN 'two'
-              ELSE 'other'
-       END
-    FROM test;
+     As seen in the second example, the element name can be omitted if
+     the content value is a column reference, in which case the column
+     name is used by default.  Otherwise, a name must be specified.
+    </para>
 
- a | case
----+-------
- 1 | one
- 2 | two
- 3 | other
-</screen>
-   </para>
-
-   <para>
-    A <token>CASE</token> expression does not evaluate any subexpressions
-    that are not needed to determine the result.  For example, this is a
-    possible way of avoiding a division-by-zero failure:
-<programlisting>
-SELECT ... WHERE CASE WHEN x &lt;&gt; 0 THEN y/x &gt; 1.5 ELSE false END;
-</programlisting>
-   </para>
-  </sect2>
-
-  <sect2>
-   <title><literal>COALESCE</></title>
-
-  <indexterm>
-   <primary>COALESCE</primary>
-  </indexterm>
+    <para>
+     Element names that are not valid XML names are escaped as shown
+     for <function>xmlelement</function> above.  Similarly, content
+     data is escaped to make valid XML content, unless it is already
+     of type <type>xml</type>.
+    </para>
 
-  <indexterm>
-   <primary>NVL</primary>
-  </indexterm>
+    <para>
+     Note that XML forests are not valid XML documents if they consist
+     of more than one element.  So it might be useful to wrap
+     <function>xmlforest</function> expressions in
+     <function>xmlelement</function>.
+    </para>
+   </sect3>
+   <sect3>
+    <title><literal>xmlpi</literal></title>
+   <indexterm>
+    <primary>xmlpi</primary>
+   </indexterm>
+ <synopsis>
+ <function>xmlpi</function>(name <replaceable>target</replaceable> <optional>, <replaceable>content</replaceable></optional>)
+ </synopsis>
+    <para>
+     The <function>xmlpi</function> expression creates an XML
+     processing instruction.  The content, if present, must not
+     contain the character sequence <literal>?&gt;</literal>.
+    </para>
 
-  <indexterm>
-   <primary>IFNULL</primary>
-  </indexterm>
+    <para>
+     Example:
+<screen><![CDATA[
+SELECT xmlpi(name php, 'echo "hello world";');
 
-<synopsis>
-<function>COALESCE</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
-</synopsis>
+            xmlpi
+-----------------------------
+ <?php echo "hello world";?>
+]]></screen>
+    </para>
+   </sect3>
+   <sect3>
+    <title><literal>xmlroot</literal></title>
+   <indexterm>
+    <primary>xmlroot</primary>
+   </indexterm>
+ <synopsis>
+ <function>xmlroot</function>(<replaceable>xml</replaceable>, version <replaceable>text</replaceable>|no value <optional>, standalone yes|no|no value</optional>)
+ </synopsis>
+    <para>
+     The <function>xmlroot</function> expression alters the properties
+     of the root node of an XML value.  If a version is specified,
+     this replaces the value in the version declaration, if a
+     standalone value is specified, this replaces the value in the
+     standalone declaration.
+    </para>
 
-  <para>
-   The <function>COALESCE</function> function returns the first of its
-   arguments that is not null.  Null is returned only if all arguments
-   are null.  It is often used to substitute a default value for 
-   null values when data is retrieved for display, for example:
-<programlisting>
-SELECT COALESCE(description, short_description, '(none)') ...
-</programlisting>
-  </para>
+    <para>
+<screen><![CDATA[
+SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'), version '1.0', standalone yes);
 
-   <para>
-    Like a <token>CASE</token> expression, <function>COALESCE</function> will
-    not evaluate arguments that are not needed to determine the result;
-    that is, arguments to the right of the first non-null argument are
-    not evaluated.  This SQL-standard function provides capabilities similar
-    to <function>NVL</> and <function>IFNULL</>, which are used in some other
-    database systems.
-   </para>
-  </sect2>
+                xmlroot
+----------------------------------------
+ <?xml version="1.0" standalone="yes"?>
+ <content>abc</content>
+]]></screen>
+    </para>
+   </sect3>
 
-  <sect2>
-   <title><literal>NULLIF</></title>
+   <sect3>
+    <title>XML Predicates</title>
 
-  <indexterm>
-   <primary>NULLIF</primary>
-  </indexterm>
+    <indexterm>
+     <primary>IS DOCUMENT</primary>
+    </indexterm>
 
 <synopsis>
-<function>NULLIF</function>(<replaceable>value1</replaceable>, <replaceable>value2</replaceable>)
+<replaceable>xml</replaceable> IS DOCUMENT
 </synopsis>
 
-  <para>
-   The <function>NULLIF</function> function returns a null value if
-   <replaceable>value1</replaceable> and <replaceable>value2</replaceable>
-   are equal;  otherwise it returns <replaceable>value1</replaceable>.
-   This can be used to perform the inverse operation of the
-   <function>COALESCE</function> example given above:
-<programlisting>
-SELECT NULLIF(value, '(none)') ...
-</programlisting>
-  </para>
-  <para>
-   If <replaceable>value1</replaceable> is <literal>(none)</>, return a null,
-   otherwise return <replaceable>value1</replaceable>.
-  </para>
-
+    <para>
+     The expression <literal>IS DOCUMENT</literal> returns true if the
+     argument XML value is a proper XML document, false if it is not
+     (that is, it is a content fragment), or null if the argument is
+     null.  See <xref linkend="datatype-xml"> about the difference
+     between documents and content fragments.
+    </para>
+   </sect3>
   </sect2>
 
-  <sect2>
-   <title><literal>GREATEST</literal> and <literal>LEAST</literal></title>
+  <sect2 id="functions-xml-mapping">
+   <title>Mapping Tables to XML</title>
 
-  <indexterm>
-   <primary>GREATEST</primary>
-  </indexterm>
-  <indexterm>
-   <primary>LEAST</primary>
-  </indexterm>
+   <indexterm zone="functions-xml-mapping"> 
+    <primary>XML export</primary>
+   </indexterm>
 
+   <para>
+    The following functions map the contents of relational tables to
+    XML values.  They can be thought of as XML export functionality.
 <synopsis>
-<function>GREATEST</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
-</synopsis>
-<synopsis>
-<function>LEAST</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
+table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text)
+query_to_xml(query text, nulls boolean, tableforest boolean, targetns text)
+cursor_to_xml(cursor refcursor, count int, nulls boolean, tableforest boolean, targetns text)
 </synopsis>
+    The return type of each function is <type>xml</type>.
+   </para>
 
    <para>
-    The <function>GREATEST</> and <function>LEAST</> functions select the
-    largest or smallest value from a list of any number of expressions.
-    The expressions must all be convertible to a common data type, which
-    will be the type of the result
-    (see <xref linkend="typeconv-union-case"> for details).  NULL values
-    in the list are ignored.  The result will be NULL only if all the
-    expressions evaluate to NULL.
+    <function>table_to_xml</function> maps the content of the named
+    table, passed as parameter <parameter>tbl</parameter>.  The
+    <type>regclass</type> accepts strings identifying tables using the
+    usual notation, including optional schema qualifications and
+    double quotes.  <function>query_to_xml</function> executes the
+    query whose text is passed as parameter
+    <parameter>query</parameter> and maps the result set.
+    <function>cursor_to_xml</function> fetches the indicated number of
+    rows from the cursor specified by the parameter
+    <parameter>cursor</parameter>.  This variant is recommendable if
+    large tables have to be mapped, because the result value is built
+    up in memory by each function.
    </para>
 
    <para>
-    Note that <function>GREATEST</> and <function>LEAST</> are not in
-    the SQL standard, but are a common extension.
-   </para>
-  </sect2>
- </sect1>
+    If <parameter>tableforest</parameter> is false, then the resulting
+    XML document looks like this:
+<screen><![CDATA[
+<tablename>
+  <row>
+    <columnname1>data</columnname1>
+    <columnname2>data</columnname2>
+  </row>
 
+  <row>
+    ...
+  </row>
 
- <sect1 id="functions-array">
-  <title>Array Functions and Operators</title>
+  ...
+</tablename>
+]]></screen>
 
-  <para>
-   <xref linkend="array-operators-table"> shows the operators
-   available for <type>array</type> types.
-  </para>
+    If <parameter>tableforest</parameter> is true, the result is an
+    XML content fragment that looks like this:
+<screen><![CDATA[
+<tablename>
+  <columnname1>data</columnname1>
+  <columnname2>data</columnname2>
+</tablename>
 
-    <table id="array-operators-table">
-     <title><type>array</type> Operators</title>
-     <tgroup cols="4">
-      <thead>
-       <row>
-        <entry>Operator</entry>
-        <entry>Description</entry>
-        <entry>Example</entry>
-        <entry>Result</entry>
-       </row>
-      </thead>
-      <tbody>
-       <row>
-        <entry> <literal>=</literal> </entry>
-        <entry>equal</entry>
-        <entry><literal>ARRAY[1.1,2.1,3.1]::int[] = ARRAY[1,2,3]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+<tablename>
+  ...
+</tablename>
 
-       <row>
-        <entry> <literal>&lt;&gt;</literal> </entry>
-        <entry>not equal</entry>
-        <entry><literal>ARRAY[1,2,3] &lt;&gt; ARRAY[1,2,4]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+...
+]]></screen>
 
-       <row>
-        <entry> <literal>&lt;</literal> </entry>
-        <entry>less than</entry>
-        <entry><literal>ARRAY[1,2,3] &lt; ARRAY[1,2,4]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+    If no table name is avaible, that is, when mapping a query or a
+    cursor, the string <literal>table</literal> is used in the first
+    format, <literal>row</literal> in the second format.
+   </para>
 
-       <row>
-        <entry> <literal>&gt;</literal> </entry>
-        <entry>greater than</entry>
-        <entry><literal>ARRAY[1,4,3] &gt; ARRAY[1,2,4]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+   <para>
+    The choice between these formats is up to the user.  The first
+    format is a proper XML document, which will be important in many
+    applications.  The second format tends to be more useful in the
+    <function>cursor_to_xml</function> function if the result values are to be
+    reassembled into one document later on.  The functions for
+    producing XML content discussed above, in particular
+    <function>xmlelement</function>, can be used to alter the results
+    to taste.
+   </para>
 
-       <row>
-        <entry> <literal>&lt;=</literal> </entry>
-        <entry>less than or equal</entry>
-        <entry><literal>ARRAY[1,2,3] &lt;= ARRAY[1,2,3]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+   <para>
+    The data values are mapping in the same way as described for the
+    function <function>xmlelement</function> above.
+   </para>
 
-       <row>
-        <entry> <literal>&gt;=</literal> </entry>
-        <entry>greater than or equal</entry>
-        <entry><literal>ARRAY[1,4,3] &gt;= ARRAY[1,4,3]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+   <para>
+    The parameter <parameter>nulls</parameter> determines whether null
+    values should be included in the output.  If true, null values in
+    columns are represented as
+<screen><![CDATA[
+<columnname xsi:nil="true"/>
+]]></screen>
+    where <literal>xsi</literal> is the XML namespace prefix for XML
+    Schema Instance.  An appropriate namespace declaration will be
+    added to the result value.  If false, columns containing null
+    values are simply omitted from the output.
+   </para>
 
-       <row>
-        <entry> <literal>@&gt;</literal> </entry>
-        <entry>contains</entry>
-        <entry><literal>ARRAY[1,4,3] @&gt; ARRAY[3,1]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+   <para>
+    The parameter <parameter>targetns</parameter> specifies the
+    desired XML namespace of the result.  If no particular namespace
+    is wanted, an empty string should be passed.
+   </para>
 
-       <row>
-        <entry> <literal>&lt;@</literal> </entry>
-        <entry>is contained by</entry>
-        <entry><literal>ARRAY[2,7] &lt;@ ARRAY[1,7,4,2,6]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+   <para>
+    The following functions return XML Schema documents describing the
+    mappings made by the data mappings produced by the corresponding
+    functions above.
+<synopsis>
+table_to_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
+query_to_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
+cursor_to_xmlschema(cursor refcursor, nulls boolean, tableforest boolean, targetns text)
+</synopsis>
+    It is essential that the same parameters are passed in order to
+    obtain matching XML data mappings and XML Schema documents.
+   </para>
 
-       <row>
-        <entry> <literal>&amp;&amp;</literal> </entry>
-        <entry>overlap (have elements in common)</entry>
-        <entry><literal>ARRAY[1,4,3] &amp;&amp; ARRAY[2,1]</literal></entry>
-        <entry><literal>t</literal></entry>
-       </row>
+   <para>
+    The following functions produce XML data mappings and the
+    corresponding XML Schema in one document (or forest), linked
+    together.  They can be useful where self-contained and
+    self-describing results are wanted.
+<synopsis>
+table_to_xml_and_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
+query_to_xml_and_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
+</synopsis>
+   </para>
 
-       <row>
-        <entry> <literal>||</literal> </entry>
-        <entry>array-to-array concatenation</entry>
-        <entry><literal>ARRAY[1,2,3] || ARRAY[4,5,6]</literal></entry>
-        <entry><literal>{1,2,3,4,5,6}</literal></entry>
-       </row>
+   <para>
+    In addition, the following functions are available to produce
+    analogous mappings of entire schemas or the entire current
+    database.
+<synopsis>
+schema_to_xml(schema name, nulls boolean, tableforest boolean, targetns text)
+schema_to_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
+schema_to_xml_and_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
 
-       <row>
-        <entry> <literal>||</literal> </entry>
-        <entry>array-to-array concatenation</entry>
-        <entry><literal>ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9]]</literal></entry>
-        <entry><literal>{{1,2,3},{4,5,6},{7,8,9}}</literal></entry>
-       </row>
+database_to_xml(nulls boolean, tableforest boolean, targetns text)
+database_to_xmlschema(nulls boolean, tableforest boolean, targetns text)
+database_to_xml_and_xmlschema(nulls boolean, tableforest boolean, targetns text)
+</synopsis>
 
-       <row>
-        <entry> <literal>||</literal> </entry>
-        <entry>element-to-array concatenation</entry>
-        <entry><literal>3 || ARRAY[4,5,6]</literal></entry>
-        <entry><literal>{3,4,5,6}</literal></entry>
-       </row>
+    Note that these potentially produce a lot of data, which needs to
+    be built up in memory.  When requesting content mappings of large
+    schemas or databases, it may be worthwhile to consider mapping the
+    tables separately instead, possibly even through a cursor.
+   </para>
 
-       <row>
-        <entry> <literal>||</literal> </entry>
-        <entry>array-to-element concatenation</entry>
-        <entry><literal>ARRAY[4,5,6] || 7</literal></entry>
-        <entry><literal>{4,5,6,7}</literal></entry>
-       </row>
-      </tbody>
-     </tgroup>
-    </table>
+   <para>
+    The result of a schema content mapping looks like this:
 
-  <para>
-   Array comparisons compare the array contents element-by-element,
-   using the default B-Tree comparison function for the element data type.
-   In multidimensional arrays the elements are visited in row-major order
-   (last subscript varies most rapidly).
-   If the contents of two arrays are equal but the dimensionality is
-   different, the first difference in the dimensionality information
-   determines the sort order.  (This is a change from versions of
-   <productname>PostgreSQL</> prior to 8.2: older versions would claim
-   that two arrays with the same contents were equal, even if the
-   number of dimensions or subscript ranges were different.)
-  </para>
+<screen><![CDATA[
+<schemaname>
 
-  <para>
-   See <xref linkend="arrays"> for more details about array operator
-   behavior.
-  </para>
+table1-mapping
 
-  <para>
-   <xref linkend="array-functions-table"> shows the functions
-   available for use with array types. See <xref linkend="arrays">
-   for more discussion and examples of the use of these functions.
-  </para>
+table2-mapping
 
-    <table id="array-functions-table">
-     <title><type>array</type> Functions</title>
-     <tgroup cols="5">
-      <thead>
-       <row>
-        <entry>Function</entry>
-        <entry>Return Type</entry>
-        <entry>Description</entry>
-        <entry>Example</entry>
-        <entry>Result</entry>
-       </row>
-      </thead>
-      <tbody>
-       <row>
-        <entry>
-     <literal>
-      <function>array_append</function>(<type>anyarray</type>, <type>anyelement</type>)
-     </literal>
-    </entry>
-        <entry><type>anyarray</type></entry>
-        <entry>append an element to the end of an array</entry>
-        <entry><literal>array_append(ARRAY[1,2], 3)</literal></entry>
-        <entry><literal>{1,2,3}</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>array_cat</function>(<type>anyarray</type>, <type>anyarray</type>)
-     </literal>
-    </entry>
-        <entry><type>anyarray</type></entry>
-        <entry>concatenate two arrays</entry>
-        <entry><literal>array_cat(ARRAY[1,2,3], ARRAY[4,5])</literal></entry>
-        <entry><literal>{1,2,3,4,5}</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>array_dims</function>(<type>anyarray</type>)
-     </literal>
-    </entry>
-        <entry><type>text</type></entry>
-        <entry>returns a text representation of array's dimensions</entry>
-        <entry><literal>array_dims(ARRAY[[1,2,3], [4,5,6]])</literal></entry>
-        <entry><literal>[1:2][1:3]</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>array_lower</function>(<type>anyarray</type>, <type>int</type>)
-     </literal>
-    </entry>
-        <entry><type>int</type></entry>
-        <entry>returns lower bound of the requested array dimension</entry>
-        <entry><literal>array_lower('[0:2]={1,2,3}'::int[], 1)</literal></entry>
-        <entry><literal>0</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>array_prepend</function>(<type>anyelement</type>, <type>anyarray</type>)
-     </literal>
-    </entry>
-        <entry><type>anyarray</type></entry>
-        <entry>append an element to the beginning of an array</entry>
-        <entry><literal>array_prepend(1, ARRAY[2,3])</literal></entry>
-        <entry><literal>{1,2,3}</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>array_to_string</function>(<type>anyarray</type>, <type>text</type>)
-     </literal>
-    </entry>
-        <entry><type>text</type></entry>
-        <entry>concatenates array elements using provided delimiter</entry>
-        <entry><literal>array_to_string(ARRAY[1, 2, 3], '~^~')</literal></entry>
-        <entry><literal>1~^~2~^~3</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>array_upper</function>(<type>anyarray</type>, <type>int</type>)
-     </literal>
-    </entry>
-        <entry><type>int</type></entry>
-        <entry>returns upper bound of the requested array dimension</entry>
-        <entry><literal>array_upper(ARRAY[1,2,3,4], 1)</literal></entry>
-        <entry><literal>4</literal></entry>
-       </row>
-       <row>
-        <entry>
-     <literal>
-      <function>string_to_array</function>(<type>text</type>, <type>text</type>)
-     </literal>
-    </entry>
-        <entry><type>text[]</type></entry>
-        <entry>splits string into array elements using provided delimiter</entry>
-        <entry><literal>string_to_array('xx~^~yy~^~zz', '~^~')</literal></entry>
-        <entry><literal>{xx,yy,zz}</literal></entry>
-       </row>
-      </tbody>
-     </tgroup>
-    </table>
-  </sect1>
+...
 
- <sect1 id="functions-aggregate">
-  <title>Aggregate Functions</title>
+</schemaname>]]></screen>
 
-  <indexterm zone="functions-aggregate">
-   <primary>aggregate function</primary>
-   <secondary>built-in</secondary>
-  </indexterm>
+    where the format of a table mapping depends on the
+    <parameter>tableforest</parameter> parameter as explained above.
+   </para>
 
-  <para>
-   <firstterm>Aggregate functions</firstterm> compute a single result
-   value from a set of input values.  The built-in aggregate functions
-   are listed in
-   <xref linkend="functions-aggregate-table"> and
-   <xref linkend="functions-aggregate-statistics-table">.
-   The special syntax considerations for aggregate
-   functions are explained in <xref linkend="syntax-aggregates">.
-   Consult <xref linkend="tutorial-agg"> for additional introductory
-   information.
-  </para>
+   <para>
+    The result of a database content mapping looks like this:
 
-  <table id="functions-aggregate-table">
-   <title>General-Purpose Aggregate Functions</title>
+<screen><![CDATA[
+<dbname>
 
-   <tgroup cols="4">
-    <thead>
-     <row>
-      <entry>Function</entry>
-      <entry>Argument Type</entry>
-      <entry>Return Type</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
+<schema1name>
+  ...
+</schema1name>
 
-    <tbody>
-     <row>
-      <entry>
-       <indexterm>
-        <primary>average</primary>
-       </indexterm>
-       <function>avg(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, <type>numeric</type>, or <type>interval</type>
-      </entry>
-      <entry>
-       <type>numeric</type> for any integer type argument,
-       <type>double precision</type> for a floating-point argument,
-       otherwise the same as the argument data type
-      </entry>
-      <entry>the average (arithmetic mean) of all input values</entry>
-     </row>
+<schema2name>
+  ...
+</schema2name>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>bit_and</primary>
-       </indexterm>
-       <function>bit_and(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>, <type>bigint</type>, or
-       <type>bit</type>
-      </entry>
-      <entry>
-        same as argument data type
-      </entry>
-      <entry>the bitwise AND of all non-null input values, or null if none</entry>
-     </row>
+...
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>bit_or</primary>
-       </indexterm>
-       <function>bit_or(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>, <type>bigint</type>, or
-       <type>bit</type>
-      </entry>
-      <entry>
-        same as argument data type
-      </entry>
-      <entry>the bitwise OR of all non-null input values, or null if none</entry>
-     </row>
+</dbname>]]></screen>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>bool_and</primary>
-       </indexterm>
-       <function>bool_and(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>bool</type>
-      </entry>
-      <entry>
-       <type>bool</type>
-      </entry>
-      <entry>true if all input values are true, otherwise false</entry>
-     </row>
+    where the schema mapping is as above.
+   </para>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>bool_or</primary>
-       </indexterm>
-       <function>bool_or(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>bool</type>
-      </entry>
-      <entry>
-       <type>bool</type>
-      </entry>
-      <entry>true if at least one input value is true, otherwise false</entry>
-     </row>
+   <para>
+    As an example for using the output produced by these functions,
+    <xref linkend="xslt-xml-html"> shows an XSLT stylesheet that
+    converts the output of
+    <function>table_to_xml_and_xmlschema</function> to an HTML
+    document containing a tabular rendition of the table data.  In a
+    similar manner, the result data of these functions can be
+    converted into other XML-based formats.
+   </para>
 
-     <row>
-      <entry><function>count(*)</function></entry>
-      <entry></entry>
-      <entry><type>bigint</type></entry>
-      <entry>number of input rows</entry>
-     </row>
+   <figure id="xslt-xml-html">
+    <title>XSLT stylesheet for converting SQL/XML output to HTML</title>
+<programlisting><![CDATA[
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+    xmlns="http://www.w3.org/1999/xhtml"
+>
 
-     <row>
-      <entry><function>count(<replaceable class="parameter">expression</replaceable>)</function></entry>
-      <entry>any</entry>
-      <entry><type>bigint</type></entry>
-      <entry>
-       number of input rows for which the value of <replaceable
-       class="parameter">expression</replaceable> is not null
-      </entry>
-     </row>
+  <xsl:output method="xml"
+      doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+      doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
+      indent="yes"/>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>every</primary>
-       </indexterm>
-       <function>every(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>bool</type>
-      </entry>
-      <entry>
-       <type>bool</type>
-      </entry>
-      <entry>equivalent to <function>bool_and</function></entry>
-     </row>
+  <xsl:template match="/*">
+    <xsl:variable name="schema" select="//xsd:schema"/>
+    <xsl:variable name="tabletypename"
+                  select="$schema/xsd:element[@name=name(current())]/@type"/>
+    <xsl:variable name="rowtypename"
+                  select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
 
-     <row>
-      <entry><function>max(<replaceable class="parameter">expression</replaceable>)</function></entry>
-      <entry>any array, numeric, string, or date/time type</entry>
-      <entry>same as argument type</entry>
-      <entry>
-       maximum value of <replaceable
-       class="parameter">expression</replaceable> across all input
-       values
-      </entry>
-     </row>
+    <html>
+      <head>
+        <title><xsl:value-of select="name(current())"/></title>
+      </head>
+      <body>
+        <table>
+          <tr>
+            <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
+              <th><xsl:value-of select="."/></th>
+            </xsl:for-each>
+          </tr>
 
-     <row>
-      <entry><function>min(<replaceable class="parameter">expression</replaceable>)</function></entry>
-      <entry>any array, numeric, string, or date/time type</entry>
-      <entry>same as argument type</entry>
-      <entry>
-       minimum value of <replaceable
-       class="parameter">expression</replaceable> across all input
-       values
-      </entry>
-     </row>
+          <xsl:for-each select="row">
+            <tr>
+              <xsl:for-each select="*">
+                <td><xsl:value-of select="."/></td>
+              </xsl:for-each>
+            </tr>
+          </xsl:for-each>
+        </table>
+      </body>
+    </html>
+  </xsl:template>
 
-     <row>
-      <entry><function>sum(<replaceable class="parameter">expression</replaceable>)</function></entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, <type>numeric</type>, or
-       <type>interval</type>
-      </entry>
-      <entry>
-       <type>bigint</type> for <type>smallint</type> or
-       <type>int</type> arguments, <type>numeric</type> for
-       <type>bigint</type> arguments, <type>double precision</type>
-       for floating-point arguments, otherwise the same as the
-       argument data type
-      </entry>
-      <entry>sum of <replaceable class="parameter">expression</replaceable> across all input values</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <para>
-   It should be noted that except for <function>count</function>,
-   these functions return a null value when no rows are selected.  In
-   particular, <function>sum</function> of no rows returns null, not
-   zero as one might expect.  The <function>coalesce</function> function can be
-   used to substitute zero for null when necessary.
-  </para>
+</xsl:stylesheet>
+]]></programlisting>
+   </figure>
+  </sect2>
 
-  <note>
-    <indexterm>
-      <primary>ANY</primary>
-    </indexterm>
-    <indexterm>
-      <primary>SOME</primary>
-    </indexterm>
-    <para>
-      Boolean aggregates <function>bool_and</function> and 
-      <function>bool_or</function> correspond to standard SQL aggregates
-      <function>every</function> and <function>any</function> or
-      <function>some</function>. 
-      As for <function>any</function> and <function>some</function>, 
-      it seems that there is an ambiguity built into the standard syntax:
-<programlisting>
-SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;
-</programlisting>
-      Here <function>ANY</function> can be considered both as leading
-      to a subquery or as an aggregate if the select expression returns 1 row.
-      Thus the standard name cannot be given to these aggregates.
-    </para>
-  </note>
+  <sect2>
+   <title>Processing XML</title>
 
-  <note>
    <para>
-    Users accustomed to working with other SQL database management
-    systems might be surprised by the performance of the
-    <function>count</function> aggregate when it is applied to the
-    entire table. A query like:
-<programlisting>
-SELECT count(*) FROM sometable;
-</programlisting>
-    will be executed by <productname>PostgreSQL</productname> using a
-    sequential scan of the entire table.
+    <acronym>XML</> support is not just the existence of an
+    <type>xml</type> data type, but a variety of features supported by
+    a database system.  These capabilities include import/export,
+    indexing, searching, transforming, and <acronym>XML</> to
+    <acronym>SQL</> mapping.  <productname>PostgreSQL</> supports some
+    but not all of these <acronym>XML</> capabilities.  For an
+    overview of <acronym>XML</> use in databases, see <ulink
+    url="http://www.rpbourret.com/xml/XMLAndDatabases.htm"></>.
    </para>
-  </note>
 
+   <variablelist>
+   <varlistentry>
+    <term>Indexing</term>
+    <listitem>
 
-  <para>
-   <xref linkend="functions-aggregate-statistics-table"> shows
-   aggregate functions typically used in statistical analysis.
-   (These are separated out merely to avoid cluttering the listing
-   of more-commonly-used aggregates.)  Where the description mentions
-   <replaceable class="parameter">N</replaceable>, it means the
-   number of input rows for which all the input expressions are non-null.
-   In all cases, null is returned if the computation is meaningless,
-   for example when <replaceable class="parameter">N</replaceable> is zero.
-  </para>
+     <para>
+      <filename>contrib/xml2/</> functions can be used in expression
+      indexes to index specific <acronym>XML</> fields.  To index the
+      full contents of <acronym>XML</> documents, the full-text
+      indexing tool <filename>contrib/tsearch2/</> can be used.  Of
+      course, Tsearch2 indexes have no <acronym>XML</> awareness so
+      additional <filename>contrib/xml2/</> checks should be added to
+      queries.
+     </para>
+    </listitem>
+   </varlistentry>
 
-  <indexterm>
-   <primary>statistics</primary>
-  </indexterm>
-  <indexterm>
-   <primary>linear regression</primary>
-  </indexterm>
+   <varlistentry>
+    <term>Searching</term>
+    <listitem>
 
-  <table id="functions-aggregate-statistics-table">
-   <title>Aggregate Functions for Statistics</title>
+     <para>
+      XPath searches are implemented using <filename>contrib/xml2/</>.
+      It processes <acronym>XML</> text documents and returns results
+      based on the requested query.
+     </para>
+    </listitem>
+   </varlistentry>
 
-   <tgroup cols="4">
-    <thead>
-     <row>
-      <entry>Function</entry>
-      <entry>Argument Type</entry>
-      <entry>Return Type</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
+   <varlistentry>
+    <term>Transforming</term>
+    <listitem>
 
-    <tbody>
+     <para>
+      <filename>contrib/xml2/</> supports <acronym>XSLT</> (Extensible
+      Stylesheet Language Transformation).
+     </para>
+    </listitem>
+   </varlistentry>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>correlation</primary>
-       </indexterm>
-       <function>corr(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>correlation coefficient</entry>
-     </row>
+   <varlistentry>
+    <term>XML to SQL Mapping</term>
+    <listitem>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>covariance</primary>
-        <secondary>population</secondary>
-       </indexterm>
-       <function>covar_pop(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>population covariance</entry>
-     </row>
+     <para>
+      This involves converting <acronym>XML</> data to and from
+      relational structures. <productname>PostgreSQL</> has no
+      internal support for such mapping, and relies on external tools
+      to do such conversions.
+     </para>
+    </listitem>
+   </varlistentry>
+   </variablelist>
+  </sect2>
+ </sect1>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>covariance</primary>
-        <secondary>sample</secondary>
-       </indexterm>
-       <function>covar_samp(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>sample covariance</entry>
-     </row>
 
-     <row>
-      <entry>
-       <function>regr_avgx(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>average of the independent variable
-      (<literal>sum(<replaceable class="parameter">X</replaceable>)/<replaceable class="parameter">N</replaceable></literal>)</entry>
-     </row>
+ <sect1 id="functions-sequence">
+  <title>Sequence Manipulation Functions</title>
 
-     <row>
-      <entry>
-       <function>regr_avgy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>average of the dependent variable
-      (<literal>sum(<replaceable class="parameter">Y</replaceable>)/<replaceable class="parameter">N</replaceable></literal>)</entry>
-     </row>
+  <indexterm>
+   <primary>sequence</primary>
+  </indexterm>
+  <indexterm>
+   <primary>nextval</primary>
+  </indexterm>
+  <indexterm>
+   <primary>currval</primary>
+  </indexterm>
+  <indexterm>
+   <primary>lastval</primary>
+  </indexterm>
+  <indexterm>
+   <primary>setval</primary>
+  </indexterm>
 
-     <row>
-      <entry>
-       <function>regr_count(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>bigint</type>
-      </entry>
-      <entry>number of input rows in which both expressions are nonnull</entry>
-     </row>
+  <para>
+   This section describes <productname>PostgreSQL</productname>'s functions
+   for operating on <firstterm>sequence objects</firstterm>.
+   Sequence objects (also called sequence generators or
+   just sequences) are special single-row tables created with
+   <command>CREATE SEQUENCE</command>.  A sequence object is usually used to
+   generate unique identifiers for rows of a table.  The sequence functions,
+   listed in <xref linkend="functions-sequence-table">,
+   provide simple, multiuser-safe methods for obtaining successive
+   sequence values from sequence objects.
+  </para>
 
-     <row>
-      <entry>
-       <indexterm>
-        <primary>regression intercept</primary>
-       </indexterm>
-       <function>regr_intercept(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>y-intercept of the least-squares-fit linear equation
-      determined by the (<replaceable
-      class="parameter">X</replaceable>, <replaceable
-      class="parameter">Y</replaceable>) pairs</entry>
-     </row>
-
-     <row>
-      <entry>
-       <function>regr_r2(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>square of the correlation coefficient</entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>regression slope</primary>
-       </indexterm>
-       <function>regr_slope(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>slope of the least-squares-fit linear equation determined
-      by the (<replaceable class="parameter">X</replaceable>,
-      <replaceable class="parameter">Y</replaceable>) pairs</entry>
-     </row>
-
-     <row>
-      <entry>
-       <function>regr_sxx(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry><literal>sum(<replaceable
-      class="parameter">X</replaceable>^2) - sum(<replaceable
-      class="parameter">X</replaceable>)^2/<replaceable
-      class="parameter">N</replaceable></literal> (<quote>sum of
-      squares</quote> of the independent variable)</entry>
-     </row>
-
-     <row>
-      <entry>
-       <function>regr_sxy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry><literal>sum(<replaceable
-      class="parameter">X</replaceable>*<replaceable
-      class="parameter">Y</replaceable>) - sum(<replaceable
-      class="parameter">X</replaceable>) * sum(<replaceable
-      class="parameter">Y</replaceable>)/<replaceable
-      class="parameter">N</replaceable></literal> (<quote>sum of
-      products</quote> of independent times dependent
-      variable)</entry>
-     </row>
-
-     <row>
-      <entry>
-       <function>regr_syy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry>
-       <type>double precision</type>
-      </entry>
-      <entry><literal>sum(<replaceable
-      class="parameter">Y</replaceable>^2) - sum(<replaceable
-      class="parameter">Y</replaceable>)^2/<replaceable
-      class="parameter">N</replaceable></literal> (<quote>sum of
-      squares</quote> of the dependent variable)</entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>standard deviation</primary>
-       </indexterm>
-       <function>stddev(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, or <type>numeric</type>
-      </entry>
-      <entry>
-       <type>double precision</type> for floating-point arguments,
-       otherwise <type>numeric</type>
-      </entry>
-      <entry>historical alias for <function>stddev_samp</function></entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>standard deviation</primary>
-        <secondary>population</secondary>
-       </indexterm>
-       <function>stddev_pop(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, or <type>numeric</type>
-      </entry>
-      <entry>
-       <type>double precision</type> for floating-point arguments,
-       otherwise <type>numeric</type>
-      </entry>
-      <entry>population standard deviation of the input values</entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>standard deviation</primary>
-        <secondary>sample</secondary>
-       </indexterm>
-       <function>stddev_samp(<replaceable class="parameter">expression</replaceable>)</function>
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, or <type>numeric</type>
-      </entry>
-      <entry>
-       <type>double precision</type> for floating-point arguments,
-       otherwise <type>numeric</type>
-      </entry>
-      <entry>sample standard deviation of the input values</entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>variance</primary>
-       </indexterm>
-       <function>variance</function>(<replaceable class="parameter">expression</replaceable>)
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, or <type>numeric</type>
-      </entry>
-      <entry>
-       <type>double precision</type> for floating-point arguments,
-       otherwise <type>numeric</type>
-      </entry>
-      <entry>historical alias for <function>var_samp</function></entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>variance</primary>
-        <secondary>population</secondary>
-       </indexterm>
-       <function>var_pop</function>(<replaceable class="parameter">expression</replaceable>)
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, or <type>numeric</type>
-      </entry>
-      <entry>
-       <type>double precision</type> for floating-point arguments,
-       otherwise <type>numeric</type>
-      </entry>
-      <entry>population variance of the input values (square of the population standard deviation)</entry>
-     </row>
-
-     <row>
-      <entry>
-       <indexterm>
-        <primary>variance</primary>
-        <secondary>sample</secondary>
-       </indexterm>
-       <function>var_samp</function>(<replaceable class="parameter">expression</replaceable>)
-      </entry>
-      <entry>
-       <type>smallint</type>, <type>int</type>,
-       <type>bigint</type>, <type>real</type>, <type>double
-       precision</type>, or <type>numeric</type>
-      </entry>
-      <entry>
-       <type>double precision</type> for floating-point arguments,
-       otherwise <type>numeric</type>
-      </entry>
-      <entry>sample variance of the input values (square of the sample standard deviation)</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
- </sect1>
-
-
- <sect1 id="functions-subquery">
-  <title>Subquery Expressions</title>
-
-  <indexterm>
-   <primary>EXISTS</primary>
-  </indexterm>
-
-  <indexterm>
-   <primary>IN</primary>
-  </indexterm>
-
-  <indexterm>
-   <primary>NOT IN</primary>
-  </indexterm>
-
-  <indexterm>
-   <primary>ANY</primary>
-  </indexterm>
-
-  <indexterm>
-   <primary>ALL</primary>
-  </indexterm>
-
-  <indexterm>
-   <primary>SOME</primary>
-  </indexterm>
+   <table id="functions-sequence-table">
+    <title>Sequence Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Function</entry> <entry>Return Type</entry> <entry>Description</entry></row>
+     </thead>
 
-  <indexterm>
-   <primary>subquery</primary>
-  </indexterm>
+     <tbody>
+      <row>
+        <entry><literal><function>currval</function>(<type>regclass</type>)</literal></entry>
+        <entry><type>bigint</type></entry>
+        <entry>Return value most recently obtained with
+        <function>nextval</function> for specified sequence</entry>
+      </row>
+      <row>
+        <entry><literal><function>nextval</function>(<type>regclass</type>)</literal></entry>
+        <entry><type>bigint</type></entry>
+        <entry>Advance sequence and return new value</entry>
+      </row>
+      <row>
+        <entry><literal><function>setval</function>(<type>regclass</type>, <type>bigint</type>)</literal></entry>
+        <entry><type>bigint</type></entry>
+        <entry>Set sequence's current value</entry>
+      </row>
+      <row>
+        <entry><literal><function>setval</function>(<type>regclass</type>, <type>bigint</type>, <type>boolean</type>)</literal></entry>
+        <entry><type>bigint</type></entry>
+        <entry>Set sequence's current value and <literal>is_called</literal> flag</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
 
   <para>
-   This section describes the <acronym>SQL</acronym>-compliant subquery
-   expressions available in <productname>PostgreSQL</productname>.
-   All of the expression forms documented in this section return
-   Boolean (true/false) results.
+   The sequence to be operated on by a sequence-function call is specified by
+   a <type>regclass</> argument, which is just the OID of the sequence in the
+   <structname>pg_class</> system catalog.  You do not have to look up the
+   OID by hand, however, since the <type>regclass</> data type's input
+   converter will do the work for you.  Just write the sequence name enclosed
+   in single quotes, so that it looks like a literal constant.  To
+   achieve some compatibility with the handling of ordinary
+   <acronym>SQL</acronym> names, the string will be converted to lowercase
+   unless it contains double quotes around the sequence name.  Thus:
+<programlisting>
+nextval('foo')      <lineannotation>operates on sequence <literal>foo</literal></>
+nextval('FOO')      <lineannotation>operates on sequence <literal>foo</literal></>
+nextval('"Foo"')    <lineannotation>operates on sequence <literal>Foo</literal></>
+</programlisting>
+   The sequence name can be schema-qualified if necessary:
+<programlisting>
+nextval('myschema.foo')     <lineannotation>operates on <literal>myschema.foo</literal></>
+nextval('"myschema".foo')   <lineannotation>same as above</lineannotation>
+nextval('foo')              <lineannotation>searches search path for <literal>foo</literal></>
+</programlisting>
+   See <xref linkend="datatype-oid"> for more information about
+   <type>regclass</>.
   </para>
 
-  <sect2>
-   <title><literal>EXISTS</literal></title>
+  <note>
+   <para>
+    Before <productname>PostgreSQL</productname> 8.1, the arguments of the
+    sequence functions were of type <type>text</>, not <type>regclass</>, and
+    the above-described conversion from a text string to an OID value would
+    happen at run time during each call.  For backwards compatibility, this
+    facility still exists, but internally it is now handled as an implicit
+    coercion from <type>text</> to <type>regclass</> before the function is
+    invoked.
+   </para>
 
-<synopsis>
-EXISTS (<replaceable>subquery</replaceable>)
-</synopsis>
+   <para>
+    When you write the argument of a sequence function as an unadorned
+    literal string, it becomes a constant of type <type>regclass</>.
+    Since this is really just an OID, it will track the originally
+    identified sequence despite later renaming, schema reassignment,
+    etc.  This <quote>early binding</> behavior is usually desirable for
+    sequence references in column defaults and views.  But sometimes you will
+    want <quote>late binding</> where the sequence reference is resolved
+    at run time.  To get late-binding behavior, force the constant to be
+    stored as a <type>text</> constant instead of <type>regclass</>:
+<programlisting>
+nextval('foo'::text)      <lineannotation><literal>foo</literal> is looked up at runtime</>
+</programlisting>
+    Note that late binding was the only behavior supported in
+    <productname>PostgreSQL</productname> releases before 8.1, so you
+    might need to do this to preserve the semantics of old applications.
+   </para>
 
-  <para>
-   The argument of <token>EXISTS</token> is an arbitrary <command>SELECT</> statement,
-   or <firstterm>subquery</firstterm>.  The
-   subquery is evaluated to determine whether it returns any rows.
-   If it returns at least one row, the result of <token>EXISTS</token> is
-   <quote>true</>; if the subquery returns no rows, the result of <token>EXISTS</token> 
-   is <quote>false</>.
-  </para>
+   <para>
+    Of course, the argument of a sequence function can be an expression
+    as well as a constant.  If it is a text expression then the implicit
+    coercion will result in a run-time lookup.
+   </para>
+  </note>
 
   <para>
-   The subquery can refer to variables from the surrounding query,
-   which will act as constants during any one evaluation of the subquery.
-  </para>
+   The available sequence functions are:
+
+    <variablelist>
+     <varlistentry>
+      <term><function>nextval</function></term>
+      <listitem>
+       <para>
+        Advance the sequence object to its next value and return that
+        value.  This is done atomically: even if multiple sessions
+        execute <function>nextval</function> concurrently, each will safely receive
+        a distinct sequence value.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><function>currval</function></term>
+      <listitem>
+       <para>
+        Return the value most recently obtained by <function>nextval</function>
+        for this sequence in the current session.  (An error is
+        reported if <function>nextval</function> has never been called for this
+        sequence in this session.)  Notice that because this is returning
+        a session-local value, it gives a predictable answer whether or not
+        other sessions have executed <function>nextval</function> since the
+        current session did.
+       </para>
+      </listitem>
+     </varlistentry>
 
-  <para>
-   The subquery will generally only be executed far enough to determine
-   whether at least one row is returned, not all the way to completion.
-   It is unwise to write a subquery that has any side effects (such as
-   calling sequence functions); whether the side effects occur or not
-   might be difficult to predict.
-  </para>
+     <varlistentry>
+      <term><function>lastval</function></term>
+      <listitem>
+       <para>
+        Return the value most recently returned by
+        <function>nextval</> in the current session. This function is
+        identical to <function>currval</function>, except that instead
+        of taking the sequence name as an argument it fetches the
+        value of the last sequence that <function>nextval</function>
+        was used on in the current session. It is an error to call
+        <function>lastval</function> if <function>nextval</function>
+        has not yet been called in the current session.
+       </para>
+      </listitem>
+     </varlistentry>
 
-  <para>
-   Since the result depends only on whether any rows are returned,
-   and not on the contents of those rows, the output list of the
-   subquery is normally uninteresting.  A common coding convention is
-   to write all <literal>EXISTS</> tests in the form
-   <literal>EXISTS(SELECT 1 WHERE ...)</literal>.  There are exceptions to
-   this rule however, such as subqueries that use <token>INTERSECT</token>.
-  </para>
+     <varlistentry>
+      <term><function>setval</function></term>
+      <listitem>
+       <para>
+        Reset the sequence object's counter value.  The two-parameter
+        form sets the sequence's <literal>last_value</literal> field to the specified
+        value and sets its <literal>is_called</literal> field to <literal>true</literal>,
+        meaning that the next <function>nextval</function> will advance the sequence
+        before returning a value.  In the three-parameter form,
+        <literal>is_called</literal> can be set either <literal>true</literal> or
+        <literal>false</literal>.  If it's set to <literal>false</literal>,
+        the next <function>nextval</function> will return exactly the specified
+        value, and sequence advancement commences with the following
+        <function>nextval</function>.  For example,
 
-  <para>
-   This simple example is like an inner join on <literal>col2</>, but
-   it produces at most one output row for each <literal>tab1</> row,
-   even if there are multiple matching <literal>tab2</> rows:
 <screen>
-SELECT col1 FROM tab1
-    WHERE EXISTS(SELECT 1 FROM tab2 WHERE col2 = tab1.col2);
+SELECT setval('foo', 42);           <lineannotation>Next <function>nextval</> will return 43</lineannotation>
+SELECT setval('foo', 42, true);     <lineannotation>Same as above</lineannotation>
+SELECT setval('foo', 42, false);    <lineannotation>Next <function>nextval</> will return 42</lineannotation>
 </screen>
-  </para>
-  </sect2>
-
-  <sect2>
-   <title><literal>IN</literal></title>
-
-<synopsis>
-<replaceable>expression</replaceable> IN (<replaceable>subquery</replaceable>)
-</synopsis>
 
-  <para>
-   The right-hand side is a parenthesized
-   subquery, which must return exactly one column.  The left-hand expression
-   is evaluated and compared to each row of the subquery result.
-   The result of <token>IN</token> is <quote>true</> if any equal subquery row is found.
-   The result is <quote>false</> if no equal row is found (including the special
-   case where the subquery returns no rows).
+        The result returned by <function>setval</function> is just the value of its
+        second argument.
+       </para>
+      </listitem>
+     </varlistentry>
+    </variablelist>
   </para>
 
   <para>
-   Note that if the left-hand expression yields null, or if there are
-   no equal right-hand values and at least one right-hand row yields
-   null, the result of the <token>IN</token> construct will be null, not false.
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
+   If a sequence object has been created with default parameters,
+   <function>nextval</function> calls on it will return successive values
+   beginning with 1.  Other behaviors can be obtained by using
+   special parameters in the <xref linkend="sql-createsequence" endterm="sql-createsequence-title"> command;
+   see its command reference page for more information.
   </para>
 
-  <para>
-   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
-   be evaluated completely.
-  </para>
+  <important>
+   <para>
+    To avoid blocking of concurrent transactions that obtain numbers from the
+    same sequence, a <function>nextval</function> operation is never rolled back;
+    that is, once a value has been fetched it is considered used, even if the
+    transaction that did the <function>nextval</function> later aborts.  This means
+    that aborted transactions might leave unused <quote>holes</quote> in the
+    sequence of assigned values.  <function>setval</function> operations are never
+    rolled back, either.
+   </para>
+  </important>
 
-<synopsis>
-<replaceable>row_constructor</replaceable> IN (<replaceable>subquery</replaceable>)
-</synopsis>
+ </sect1>
 
-  <para>
-   The left-hand side of this form of <token>IN</token> is a row constructor,
-   as described in <xref linkend="sql-syntax-row-constructors">.
-   The right-hand side is a parenthesized
-   subquery, which must return exactly as many columns as there are
-   expressions in the left-hand row.  The left-hand expressions are
-   evaluated and compared row-wise to each row of the subquery result.
-   The result of <token>IN</token> is <quote>true</> if any equal subquery row is found.
-   The result is <quote>false</> if no equal row is found (including the special
-   case where the subquery returns no rows).
-  </para>
 
-  <para>
-   As usual, null values in the rows are combined per
-   the normal rules of SQL Boolean expressions.  Two rows are considered
-   equal if all their corresponding members are non-null and equal; the rows
-   are unequal if any corresponding members are non-null and unequal;
-   otherwise the result of that row comparison is unknown (null).
-   If all the per-row results are either unequal or null, with at least one
-   null, then the result of <token>IN</token> is null.
-  </para>
-  </sect2>
+ <sect1 id="functions-conditional">
+  <title>Conditional Expressions</title>
 
-  <sect2>
-   <title><literal>NOT IN</literal></title>
+  <indexterm>
+   <primary>CASE</primary>
+  </indexterm>
 
-<synopsis>
-<replaceable>expression</replaceable> NOT IN (<replaceable>subquery</replaceable>)
-</synopsis>
+  <indexterm>
+   <primary>conditional expression</primary>
+  </indexterm>
 
   <para>
-   The right-hand side is a parenthesized
-   subquery, which must return exactly one column.  The left-hand expression
-   is evaluated and compared to each row of the subquery result.
-   The result of <token>NOT IN</token> is <quote>true</> if only unequal subquery rows
-   are found (including the special case where the subquery returns no rows).
-   The result is <quote>false</> if any equal row is found.
+   This section describes the <acronym>SQL</acronym>-compliant conditional expressions
+   available in <productname>PostgreSQL</productname>.
   </para>
 
-  <para>
-   Note that if the left-hand expression yields null, or if there are
-   no equal right-hand values and at least one right-hand row yields
-   null, the result of the <token>NOT IN</token> construct will be null, not true.
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
-  </para>
+  <tip>
+   <para>
+    If your needs go beyond the capabilities of these conditional
+    expressions you might want to consider writing a stored procedure
+    in a more expressive programming language.
+   </para>
+  </tip>
+
+  <sect2>
+   <title><literal>CASE</></title>
 
   <para>
-   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
-   be evaluated completely.
-  </para>
+   The <acronym>SQL</acronym> <token>CASE</token> expression is a
+   generic conditional expression, similar to if/else statements in
+   other languages:
 
 <synopsis>
-<replaceable>row_constructor</replaceable> NOT IN (<replaceable>subquery</replaceable>)
+CASE WHEN <replaceable>condition</replaceable> THEN <replaceable>result</replaceable>
+     <optional>WHEN ...</optional>
+     <optional>ELSE <replaceable>result</replaceable></optional>
+END
 </synopsis>
 
-  <para>
-   The left-hand side of this form of <token>NOT IN</token> is a row constructor,
-   as described in <xref linkend="sql-syntax-row-constructors">.
-   The right-hand side is a parenthesized
-   subquery, which must return exactly as many columns as there are
-   expressions in the left-hand row.  The left-hand expressions are
-   evaluated and compared row-wise to each row of the subquery result.
-   The result of <token>NOT IN</token> is <quote>true</> if only unequal subquery rows
-   are found (including the special case where the subquery returns no rows).
-   The result is <quote>false</> if any equal row is found.
-  </para>
-
-  <para>
-   As usual, null values in the rows are combined per
-   the normal rules of SQL Boolean expressions.  Two rows are considered
-   equal if all their corresponding members are non-null and equal; the rows
-   are unequal if any corresponding members are non-null and unequal;
-   otherwise the result of that row comparison is unknown (null).
-   If all the per-row results are either unequal or null, with at least one
-   null, then the result of <token>NOT IN</token> is null.
+   <token>CASE</token> clauses can be used wherever
+   an expression is valid.  <replaceable>condition</replaceable> is an
+   expression that returns a <type>boolean</type> result.  If the result is true
+   then the value of the <token>CASE</token> expression is the
+   <replaceable>result</replaceable> that follows the condition.  If the result is false any
+   subsequent <token>WHEN</token> clauses are searched in the same
+   manner.  If no <token>WHEN</token>
+   <replaceable>condition</replaceable> is true then the value of the
+   case expression is the <replaceable>result</replaceable> in the
+   <token>ELSE</token> clause.  If the <token>ELSE</token> clause is
+   omitted and no condition matches, the result is null.
   </para>
-  </sect2>
 
-  <sect2>
-   <title><literal>ANY</literal>/<literal>SOME</literal></title>
+   <para>
+    An example:
+<screen>
+SELECT * FROM test;
 
-<synopsis>
-<replaceable>expression</replaceable> <replaceable>operator</replaceable> ANY (<replaceable>subquery</replaceable>)
-<replaceable>expression</replaceable> <replaceable>operator</replaceable> SOME (<replaceable>subquery</replaceable>)
-</synopsis>
+ a
+---
+ 1
+ 2
+ 3
 
-  <para>
-   The right-hand side is a parenthesized
-   subquery, which must return exactly one column.  The left-hand expression
-   is evaluated and compared to each row of the subquery result using the
-   given <replaceable>operator</replaceable>, which must yield a Boolean
-   result.
-   The result of <token>ANY</token> is <quote>true</> if any true result is obtained.
-   The result is <quote>false</> if no true result is found (including the special
-   case where the subquery returns no rows).
-  </para>
 
-  <para>
-   <token>SOME</token> is a synonym for <token>ANY</token>.
-   <token>IN</token> is equivalent to <literal>= ANY</literal>.
-  </para>
+SELECT a,
+       CASE WHEN a=1 THEN 'one'
+            WHEN a=2 THEN 'two'
+            ELSE 'other'
+       END
+    FROM test;
 
-  <para>
-   Note that if there are no successes and at least one right-hand row yields
-   null for the operator's result, the result of the <token>ANY</token> construct
-   will be null, not false.
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
-  </para>
+ a | case
+---+-------
+ 1 | one
+ 2 | two
+ 3 | other
+</screen>
+   </para>
 
   <para>
-   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
-   be evaluated completely.
+   The data types of all the <replaceable>result</replaceable>
+   expressions must be convertible to a single output type.
+   See <xref linkend="typeconv-union-case"> for more detail.
   </para>
 
+  <para>
+   The following <quote>simple</quote> <token>CASE</token> expression is a
+   specialized variant of the general form above:
+
 <synopsis>
-<replaceable>row_constructor</replaceable> <replaceable>operator</> ANY (<replaceable>subquery</replaceable>)
-<replaceable>row_constructor</replaceable> <replaceable>operator</> SOME (<replaceable>subquery</replaceable>)
+CASE <replaceable>expression</replaceable>
+    WHEN <replaceable>value</replaceable> THEN <replaceable>result</replaceable>
+    <optional>WHEN ...</optional>
+    <optional>ELSE <replaceable>result</replaceable></optional>
+END
 </synopsis>
 
-  <para>
-   The left-hand side of this form of <token>ANY</token> is a row constructor,
-   as described in <xref linkend="sql-syntax-row-constructors">.
-   The right-hand side is a parenthesized
-   subquery, which must return exactly as many columns as there are
-   expressions in the left-hand row.  The left-hand expressions are
-   evaluated and compared row-wise to each row of the subquery result,
-   using the given <replaceable>operator</replaceable>.
-   The result of <token>ANY</token> is <quote>true</> if the comparison
-   returns true for any subquery row.
-   The result is <quote>false</> if the comparison returns false for every
-   subquery row (including the special case where the subquery returns no
-   rows).
-   The result is NULL if the comparison does not return true for any row,
-   and it returns NULL for at least one row.
+   The
+   <replaceable>expression</replaceable> is computed and compared to
+   all the <replaceable>value</replaceable> specifications in the
+   <token>WHEN</token> clauses until one is found that is equal.  If
+   no match is found, the <replaceable>result</replaceable> in the
+   <token>ELSE</token> clause (or a null value) is returned.  This is similar
+   to the <function>switch</function> statement in C.
   </para>
 
-  <para>
-   See <xref linkend="row-wise-comparison"> for details about the meaning
-   of a row-wise comparison.
-  </para>
+   <para>
+    The example above can be written using the simple
+    <token>CASE</token> syntax:
+<screen>
+SELECT a,
+       CASE a WHEN 1 THEN 'one'
+              WHEN 2 THEN 'two'
+              ELSE 'other'
+       END
+    FROM test;
+
+ a | case
+---+-------
+ 1 | one
+ 2 | two
+ 3 | other
+</screen>
+   </para>
+
+   <para>
+    A <token>CASE</token> expression does not evaluate any subexpressions
+    that are not needed to determine the result.  For example, this is a
+    possible way of avoiding a division-by-zero failure:
+<programlisting>
+SELECT ... WHERE CASE WHEN x &lt;&gt; 0 THEN y/x &gt; 1.5 ELSE false END;
+</programlisting>
+   </para>
   </sect2>
 
   <sect2>
-   <title><literal>ALL</literal></title>
+   <title><literal>COALESCE</></title>
+
+  <indexterm>
+   <primary>COALESCE</primary>
+  </indexterm>
+
+  <indexterm>
+   <primary>NVL</primary>
+  </indexterm>
+
+  <indexterm>
+   <primary>IFNULL</primary>
+  </indexterm>
 
 <synopsis>
-<replaceable>expression</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>)
+<function>COALESCE</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
 </synopsis>
 
   <para>
-   The right-hand side is a parenthesized
-   subquery, which must return exactly one column.  The left-hand expression
-   is evaluated and compared to each row of the subquery result using the
-   given <replaceable>operator</replaceable>, which must yield a Boolean
-   result.
-   The result of <token>ALL</token> is <quote>true</> if all rows yield true
-   (including the special case where the subquery returns no rows).
-   The result is <quote>false</> if any false result is found.
-   The result is NULL if the comparison does not return false for any row,
-   and it returns NULL for at least one row.
+   The <function>COALESCE</function> function returns the first of its
+   arguments that is not null.  Null is returned only if all arguments
+   are null.  It is often used to substitute a default value for 
+   null values when data is retrieved for display, for example:
+<programlisting>
+SELECT COALESCE(description, short_description, '(none)') ...
+</programlisting>
   </para>
 
-  <para>
-   <token>NOT IN</token> is equivalent to <literal>&lt;&gt; ALL</literal>.
-  </para>
+   <para>
+    Like a <token>CASE</token> expression, <function>COALESCE</function> will
+    not evaluate arguments that are not needed to determine the result;
+    that is, arguments to the right of the first non-null argument are
+    not evaluated.  This SQL-standard function provides capabilities similar
+    to <function>NVL</> and <function>IFNULL</>, which are used in some other
+    database systems.
+   </para>
+  </sect2>
 
-  <para>
-   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
-   be evaluated completely.
-  </para>
+  <sect2>
+   <title><literal>NULLIF</></title>
+
+  <indexterm>
+   <primary>NULLIF</primary>
+  </indexterm>
 
 <synopsis>
-<replaceable>row_constructor</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>)
+<function>NULLIF</function>(<replaceable>value1</replaceable>, <replaceable>value2</replaceable>)
 </synopsis>
 
   <para>
-   The left-hand side of this form of <token>ALL</token> is a row constructor,
-   as described in <xref linkend="sql-syntax-row-constructors">.
-   The right-hand side is a parenthesized
-   subquery, which must return exactly as many columns as there are
-   expressions in the left-hand row.  The left-hand expressions are
-   evaluated and compared row-wise to each row of the subquery result,
-   using the given <replaceable>operator</replaceable>.
-   The result of <token>ALL</token> is <quote>true</> if the comparison
-   returns true for all subquery rows (including the special
-   case where the subquery returns no rows).
-   The result is <quote>false</> if the comparison returns false for any
-   subquery row.
-   The result is NULL if the comparison does not return false for any
-   subquery row, and it returns NULL for at least one row.
+   The <function>NULLIF</function> function returns a null value if
+   <replaceable>value1</replaceable> and <replaceable>value2</replaceable>
+   are equal;  otherwise it returns <replaceable>value1</replaceable>.
+   This can be used to perform the inverse operation of the
+   <function>COALESCE</function> example given above:
+<programlisting>
+SELECT NULLIF(value, '(none)') ...
+</programlisting>
   </para>
-
   <para>
-   See <xref linkend="row-wise-comparison"> for details about the meaning
-   of a row-wise comparison.
+   If <replaceable>value1</replaceable> is <literal>(none)</>, return a null,
+   otherwise return <replaceable>value1</replaceable>.
   </para>
+
   </sect2>
 
   <sect2>
-   <title>Row-wise Comparison</title>
+   <title><literal>GREATEST</literal> and <literal>LEAST</literal></title>
 
-   <indexterm zone="functions-subquery">
-    <primary>comparison</primary>
-    <secondary>subquery result row</secondary>
-   </indexterm>
+  <indexterm>
+   <primary>GREATEST</primary>
+  </indexterm>
+  <indexterm>
+   <primary>LEAST</primary>
+  </indexterm>
 
 <synopsis>
-<replaceable>row_constructor</replaceable> <replaceable>operator</replaceable> (<replaceable>subquery</replaceable>)
+<function>GREATEST</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
+</synopsis>
+<synopsis>
+<function>LEAST</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
 </synopsis>
 
-  <para>
-   The left-hand side is a row constructor,
-   as described in <xref linkend="sql-syntax-row-constructors">.
-   The right-hand side is a parenthesized subquery, which must return exactly
-   as many columns as there are expressions in the left-hand row. Furthermore,
-   the subquery cannot return more than one row.  (If it returns zero rows,
-   the result is taken to be null.)  The left-hand side is evaluated and
-   compared row-wise to the single subquery result row.
-  </para>
+   <para>
+    The <function>GREATEST</> and <function>LEAST</> functions select the
+    largest or smallest value from a list of any number of expressions.
+    The expressions must all be convertible to a common data type, which
+    will be the type of the result
+    (see <xref linkend="typeconv-union-case"> for details).  NULL values
+    in the list are ignored.  The result will be NULL only if all the
+    expressions evaluate to NULL.
+   </para>
 
-  <para>
-   See <xref linkend="row-wise-comparison"> for details about the meaning
-   of a row-wise comparison.
-  </para>
+   <para>
+    Note that <function>GREATEST</> and <function>LEAST</> are not in
+    the SQL standard, but are a common extension.
+   </para>
   </sect2>
  </sect1>
 
 
- <sect1 id="functions-comparisons">
-  <title>Row and Array Comparisons</title>
+ <sect1 id="functions-array">
+  <title>Array Functions and Operators</title>
 
-  <indexterm>
-   <primary>IN</primary>
-  </indexterm>
+  <para>
+   <xref linkend="array-operators-table"> shows the operators
+   available for <type>array</type> types.
+  </para>
+
+    <table id="array-operators-table">
+     <title><type>array</type> Operators</title>
+     <tgroup cols="4">
+      <thead>
+       <row>
+        <entry>Operator</entry>
+        <entry>Description</entry>
+        <entry>Example</entry>
+        <entry>Result</entry>
+       </row>
+      </thead>
+      <tbody>
+       <row>
+        <entry> <literal>=</literal> </entry>
+        <entry>equal</entry>
+        <entry><literal>ARRAY[1.1,2.1,3.1]::int[] = ARRAY[1,2,3]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
+
+       <row>
+        <entry> <literal>&lt;&gt;</literal> </entry>
+        <entry>not equal</entry>
+        <entry><literal>ARRAY[1,2,3] &lt;&gt; ARRAY[1,2,4]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
+
+       <row>
+        <entry> <literal>&lt;</literal> </entry>
+        <entry>less than</entry>
+        <entry><literal>ARRAY[1,2,3] &lt; ARRAY[1,2,4]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
+
+       <row>
+        <entry> <literal>&gt;</literal> </entry>
+        <entry>greater than</entry>
+        <entry><literal>ARRAY[1,4,3] &gt; ARRAY[1,2,4]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
+
+       <row>
+        <entry> <literal>&lt;=</literal> </entry>
+        <entry>less than or equal</entry>
+        <entry><literal>ARRAY[1,2,3] &lt;= ARRAY[1,2,3]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>NOT IN</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>&gt;=</literal> </entry>
+        <entry>greater than or equal</entry>
+        <entry><literal>ARRAY[1,4,3] &gt;= ARRAY[1,4,3]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>ANY</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>@&gt;</literal> </entry>
+        <entry>contains</entry>
+        <entry><literal>ARRAY[1,4,3] @&gt; ARRAY[3,1]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>ALL</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>&lt;@</literal> </entry>
+        <entry>is contained by</entry>
+        <entry><literal>ARRAY[2,7] &lt;@ ARRAY[1,7,4,2,6]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>SOME</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>&amp;&amp;</literal> </entry>
+        <entry>overlap (have elements in common)</entry>
+        <entry><literal>ARRAY[1,4,3] &amp;&amp; ARRAY[2,1]</literal></entry>
+        <entry><literal>t</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>row-wise comparison</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>||</literal> </entry>
+        <entry>array-to-array concatenation</entry>
+        <entry><literal>ARRAY[1,2,3] || ARRAY[4,5,6]</literal></entry>
+        <entry><literal>{1,2,3,4,5,6}</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>comparison</primary>
-   <secondary>row-wise</secondary>
-  </indexterm>
+       <row>
+        <entry> <literal>||</literal> </entry>
+        <entry>array-to-array concatenation</entry>
+        <entry><literal>ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9]]</literal></entry>
+        <entry><literal>{{1,2,3},{4,5,6},{7,8,9}}</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>IS DISTINCT FROM</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>||</literal> </entry>
+        <entry>element-to-array concatenation</entry>
+        <entry><literal>3 || ARRAY[4,5,6]</literal></entry>
+        <entry><literal>{3,4,5,6}</literal></entry>
+       </row>
 
-  <indexterm>
-   <primary>IS NOT DISTINCT FROM</primary>
-  </indexterm>
+       <row>
+        <entry> <literal>||</literal> </entry>
+        <entry>array-to-element concatenation</entry>
+        <entry><literal>ARRAY[4,5,6] || 7</literal></entry>
+        <entry><literal>{4,5,6,7}</literal></entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
 
   <para>
-   This section describes several specialized constructs for making
-   multiple comparisons between groups of values.  These forms are
-   syntactically related to the subquery forms of the previous section,
-   but do not involve subqueries.
-   The forms involving array subexpressions are
-   <productname>PostgreSQL</productname> extensions; the rest are
-   <acronym>SQL</acronym>-compliant.
-   All of the expression forms documented in this section return
-   Boolean (true/false) results.
+   Array comparisons compare the array contents element-by-element,
+   using the default B-Tree comparison function for the element data type.
+   In multidimensional arrays the elements are visited in row-major order
+   (last subscript varies most rapidly).
+   If the contents of two arrays are equal but the dimensionality is
+   different, the first difference in the dimensionality information
+   determines the sort order.  (This is a change from versions of
+   <productname>PostgreSQL</> prior to 8.2: older versions would claim
+   that two arrays with the same contents were equal, even if the
+   number of dimensions or subscript ranges were different.)
   </para>
 
-  <sect2>
-   <title><literal>IN</literal></title>
-
-<synopsis>
-<replaceable>expression</replaceable> IN (<replaceable>value</replaceable> <optional>, ...</optional>)
-</synopsis>
-
   <para>
-   The right-hand side is a parenthesized list
-   of scalar expressions.  The result is <quote>true</> if the left-hand expression's
-   result is equal to any of the right-hand expressions.  This is a shorthand
-   notation for
-
-<synopsis>
-<replaceable>expression</replaceable> = <replaceable>value1</replaceable>
-OR
-<replaceable>expression</replaceable> = <replaceable>value2</replaceable>
-OR
-...
-</synopsis>
+   See <xref linkend="arrays"> for more details about array operator
+   behavior.
   </para>
 
   <para>
-   Note that if the left-hand expression yields null, or if there are
-   no equal right-hand values and at least one right-hand expression yields
-   null, the result of the <token>IN</token> construct will be null, not false.
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
+   <xref linkend="array-functions-table"> shows the functions
+   available for use with array types. See <xref linkend="arrays">
+   for more discussion and examples of the use of these functions.
   </para>
-  </sect2>
-
-  <sect2>
-   <title><literal>NOT IN</literal></title>
 
-<synopsis>
-<replaceable>expression</replaceable> NOT IN (<replaceable>value</replaceable> <optional>, ...</optional>)
-</synopsis>
+    <table id="array-functions-table">
+     <title><type>array</type> Functions</title>
+     <tgroup cols="5">
+      <thead>
+       <row>
+        <entry>Function</entry>
+        <entry>Return Type</entry>
+        <entry>Description</entry>
+        <entry>Example</entry>
+        <entry>Result</entry>
+       </row>
+      </thead>
+      <tbody>
+       <row>
+        <entry>
+     <literal>
+      <function>array_append</function>(<type>anyarray</type>, <type>anyelement</type>)
+     </literal>
+    </entry>
+        <entry><type>anyarray</type></entry>
+        <entry>append an element to the end of an array</entry>
+        <entry><literal>array_append(ARRAY[1,2], 3)</literal></entry>
+        <entry><literal>{1,2,3}</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>array_cat</function>(<type>anyarray</type>, <type>anyarray</type>)
+     </literal>
+    </entry>
+        <entry><type>anyarray</type></entry>
+        <entry>concatenate two arrays</entry>
+        <entry><literal>array_cat(ARRAY[1,2,3], ARRAY[4,5])</literal></entry>
+        <entry><literal>{1,2,3,4,5}</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>array_dims</function>(<type>anyarray</type>)
+     </literal>
+    </entry>
+        <entry><type>text</type></entry>
+        <entry>returns a text representation of array's dimensions</entry>
+        <entry><literal>array_dims(ARRAY[[1,2,3], [4,5,6]])</literal></entry>
+        <entry><literal>[1:2][1:3]</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>array_lower</function>(<type>anyarray</type>, <type>int</type>)
+     </literal>
+    </entry>
+        <entry><type>int</type></entry>
+        <entry>returns lower bound of the requested array dimension</entry>
+        <entry><literal>array_lower('[0:2]={1,2,3}'::int[], 1)</literal></entry>
+        <entry><literal>0</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>array_prepend</function>(<type>anyelement</type>, <type>anyarray</type>)
+     </literal>
+    </entry>
+        <entry><type>anyarray</type></entry>
+        <entry>append an element to the beginning of an array</entry>
+        <entry><literal>array_prepend(1, ARRAY[2,3])</literal></entry>
+        <entry><literal>{1,2,3}</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>array_to_string</function>(<type>anyarray</type>, <type>text</type>)
+     </literal>
+    </entry>
+        <entry><type>text</type></entry>
+        <entry>concatenates array elements using provided delimiter</entry>
+        <entry><literal>array_to_string(ARRAY[1, 2, 3], '~^~')</literal></entry>
+        <entry><literal>1~^~2~^~3</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>array_upper</function>(<type>anyarray</type>, <type>int</type>)
+     </literal>
+    </entry>
+        <entry><type>int</type></entry>
+        <entry>returns upper bound of the requested array dimension</entry>
+        <entry><literal>array_upper(ARRAY[1,2,3,4], 1)</literal></entry>
+        <entry><literal>4</literal></entry>
+       </row>
+       <row>
+        <entry>
+     <literal>
+      <function>string_to_array</function>(<type>text</type>, <type>text</type>)
+     </literal>
+    </entry>
+        <entry><type>text[]</type></entry>
+        <entry>splits string into array elements using provided delimiter</entry>
+        <entry><literal>string_to_array('xx~^~yy~^~zz', '~^~')</literal></entry>
+        <entry><literal>{xx,yy,zz}</literal></entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
+  </sect1>
 
-  <para>
-   The right-hand side is a parenthesized list
-   of scalar expressions.  The result is <quote>true</quote> if the left-hand expression's
-   result is unequal to all of the right-hand expressions.  This is a shorthand
-   notation for
+ <sect1 id="functions-aggregate">
+  <title>Aggregate Functions</title>
 
-<synopsis>
-<replaceable>expression</replaceable> &lt;&gt; <replaceable>value1</replaceable>
-AND
-<replaceable>expression</replaceable> &lt;&gt; <replaceable>value2</replaceable>
-AND
-...
-</synopsis>
-  </para>
+  <indexterm zone="functions-aggregate">
+   <primary>aggregate function</primary>
+   <secondary>built-in</secondary>
+  </indexterm>
 
   <para>
-   Note that if the left-hand expression yields null, or if there are
-   no equal right-hand values and at least one right-hand expression yields
-   null, the result of the <token>NOT IN</token> construct will be null, not true
-   as one might naively expect.
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
+   <firstterm>Aggregate functions</firstterm> compute a single result
+   value from a set of input values.  The built-in aggregate functions
+   are listed in
+   <xref linkend="functions-aggregate-table"> and
+   <xref linkend="functions-aggregate-statistics-table">.
+   The special syntax considerations for aggregate
+   functions are explained in <xref linkend="syntax-aggregates">.
+   Consult <xref linkend="tutorial-agg"> for additional introductory
+   information.
   </para>
 
-  <tip>
-  <para>
-   <literal>x NOT IN y</literal> is equivalent to <literal>NOT (x IN y)</literal> in all
-   cases.  However, null values are much more likely to trip up the novice when
-   working with <token>NOT IN</token> than when working with <token>IN</token>.
-   It's best to express your condition positively if possible.
-  </para>
-  </tip>
-  </sect2>
+  <table id="functions-aggregate-table">
+   <title>General-Purpose Aggregate Functions</title>
 
-  <sect2>
-   <title><literal>ANY</literal>/<literal>SOME</literal> (array)</title>
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Function</entry>
+      <entry>Argument Type</entry>
+      <entry>Return Type</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
 
-<synopsis>
-<replaceable>expression</replaceable> <replaceable>operator</replaceable> ANY (<replaceable>array expression</replaceable>)
-<replaceable>expression</replaceable> <replaceable>operator</replaceable> SOME (<replaceable>array expression</replaceable>)
-</synopsis>
+    <tbody>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>average</primary>
+       </indexterm>
+       <function>avg(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, <type>numeric</type>, or <type>interval</type>
+      </entry>
+      <entry>
+       <type>numeric</type> for any integer type argument,
+       <type>double precision</type> for a floating-point argument,
+       otherwise the same as the argument data type
+      </entry>
+      <entry>the average (arithmetic mean) of all input values</entry>
+     </row>
 
-  <para>
-   The right-hand side is a parenthesized expression, which must yield an
-   array value.
-   The left-hand expression
-   is evaluated and compared to each element of the array using the
-   given <replaceable>operator</replaceable>, which must yield a Boolean
-   result.
-   The result of <token>ANY</token> is <quote>true</> if any true result is obtained.
-   The result is <quote>false</> if no true result is found (including the special
-   case where the array has zero elements).
-  </para>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>bit_and</primary>
+       </indexterm>
+       <function>bit_and(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>, <type>bigint</type>, or
+       <type>bit</type>
+      </entry>
+      <entry>
+        same as argument data type
+      </entry>
+      <entry>the bitwise AND of all non-null input values, or null if none</entry>
+     </row>
 
-  <para>
-   If the array expression yields a null array, the result of
-   <token>ANY</token> will be null.  If the left-hand expression yields null,
-   the result of <token>ANY</token> is ordinarily null (though a non-strict
-   comparison operator could possibly yield a different result).
-   Also, if the right-hand array contains any null elements and no true
-   comparison result is obtained, the result of <token>ANY</token>
-   will be null, not false (again, assuming a strict comparison operator).
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
-  </para>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>bit_or</primary>
+       </indexterm>
+       <function>bit_or(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>, <type>bigint</type>, or
+       <type>bit</type>
+      </entry>
+      <entry>
+        same as argument data type
+      </entry>
+      <entry>the bitwise OR of all non-null input values, or null if none</entry>
+     </row>
 
-  <para>
-   <token>SOME</token> is a synonym for <token>ANY</token>.
-  </para>
-  </sect2>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>bool_and</primary>
+       </indexterm>
+       <function>bool_and(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>bool</type>
+      </entry>
+      <entry>
+       <type>bool</type>
+      </entry>
+      <entry>true if all input values are true, otherwise false</entry>
+     </row>
 
-  <sect2>
-   <title><literal>ALL</literal> (array)</title>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>bool_or</primary>
+       </indexterm>
+       <function>bool_or(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>bool</type>
+      </entry>
+      <entry>
+       <type>bool</type>
+      </entry>
+      <entry>true if at least one input value is true, otherwise false</entry>
+     </row>
 
-<synopsis>
-<replaceable>expression</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>array expression</replaceable>)
-</synopsis>
+     <row>
+      <entry><function>count(*)</function></entry>
+      <entry></entry>
+      <entry><type>bigint</type></entry>
+      <entry>number of input rows</entry>
+     </row>
 
-  <para>
-   The right-hand side is a parenthesized expression, which must yield an
-   array value.
-   The left-hand expression
-   is evaluated and compared to each element of the array using the
-   given <replaceable>operator</replaceable>, which must yield a Boolean
-   result.
-   The result of <token>ALL</token> is <quote>true</> if all comparisons yield true
-   (including the special case where the array has zero elements).
-   The result is <quote>false</> if any false result is found.
-  </para>
+     <row>
+      <entry><function>count(<replaceable class="parameter">expression</replaceable>)</function></entry>
+      <entry>any</entry>
+      <entry><type>bigint</type></entry>
+      <entry>
+       number of input rows for which the value of <replaceable
+       class="parameter">expression</replaceable> is not null
+      </entry>
+     </row>
 
-  <para>
-   If the array expression yields a null array, the result of
-   <token>ALL</token> will be null.  If the left-hand expression yields null,
-   the result of <token>ALL</token> is ordinarily null (though a non-strict
-   comparison operator could possibly yield a different result).
-   Also, if the right-hand array contains any null elements and no false
-   comparison result is obtained, the result of <token>ALL</token>
-   will be null, not true (again, assuming a strict comparison operator).
-   This is in accordance with SQL's normal rules for Boolean combinations
-   of null values.
-  </para>
-  </sect2>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>every</primary>
+       </indexterm>
+       <function>every(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>bool</type>
+      </entry>
+      <entry>
+       <type>bool</type>
+      </entry>
+      <entry>equivalent to <function>bool_and</function></entry>
+     </row>
 
-  <sect2 id="row-wise-comparison">
-   <title>Row-wise Comparison</title>
+     <row>
+      <entry><function>max(<replaceable class="parameter">expression</replaceable>)</function></entry>
+      <entry>any array, numeric, string, or date/time type</entry>
+      <entry>same as argument type</entry>
+      <entry>
+       maximum value of <replaceable
+       class="parameter">expression</replaceable> across all input
+       values
+      </entry>
+     </row>
 
-<synopsis>
-<replaceable>row_constructor</replaceable> <replaceable>operator</replaceable> <replaceable>row_constructor</replaceable>
-</synopsis>
+     <row>
+      <entry><function>min(<replaceable class="parameter">expression</replaceable>)</function></entry>
+      <entry>any array, numeric, string, or date/time type</entry>
+      <entry>same as argument type</entry>
+      <entry>
+       minimum value of <replaceable
+       class="parameter">expression</replaceable> across all input
+       values
+      </entry>
+     </row>
 
-  <para>
-   Each side is a row constructor,
-   as described in <xref linkend="sql-syntax-row-constructors">.
-   The two row values must have the same number of fields.
-   Each side is evaluated and they are compared row-wise.  Row comparisons
-   are allowed when the <replaceable>operator</replaceable> is
-   <literal>=</>,
-   <literal>&lt;&gt;</>,
-   <literal>&lt;</>,
-   <literal>&lt;=</>,
-   <literal>&gt;</> or
-   <literal>&gt;=</>,
-   or has semantics similar to one of these.  (To be specific, an operator
-   can be a row comparison operator if it is a member of a B-Tree operator
-   class, or is the negator of the <literal>=</> member of a B-Tree operator
-   class.)
-  </para>
+     <row>
+      <entry><function>sum(<replaceable class="parameter">expression</replaceable>)</function></entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, <type>numeric</type>, or
+       <type>interval</type>
+      </entry>
+      <entry>
+       <type>bigint</type> for <type>smallint</type> or
+       <type>int</type> arguments, <type>numeric</type> for
+       <type>bigint</type> arguments, <type>double precision</type>
+       for floating-point arguments, otherwise the same as the
+       argument data type
+      </entry>
+      <entry>sum of <replaceable class="parameter">expression</replaceable> across all input values</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
 
   <para>
-   The <literal>=</> and <literal>&lt;&gt;</> cases work slightly differently
-   from the others.  Two rows are considered
-   equal if all their corresponding members are non-null and equal; the rows
-   are unequal if any corresponding members are non-null and unequal;
-   otherwise the result of the row comparison is unknown (null).
+   It should be noted that except for <function>count</function>,
+   these functions return a null value when no rows are selected.  In
+   particular, <function>sum</function> of no rows returns null, not
+   zero as one might expect.  The <function>coalesce</function> function can be
+   used to substitute zero for null when necessary.
   </para>
 
-  <para>
-   For the <literal>&lt;</>, <literal>&lt;=</>, <literal>&gt;</> and
-   <literal>&gt;=</> cases, the row elements are compared left-to-right,
-   stopping as soon as an unequal or null pair of elements is found.
-   If either of this pair of elements is null, the result of the
-   row comparison is unknown (null); otherwise comparison of this pair
-   of elements determines the result.  For example,
-   <literal>ROW(1,2,NULL) &lt; ROW(1,3,0)</>
-   yields true, not null, because the third pair of elements are not
-   considered.
-  </para>
+  <note>
+    <indexterm>
+      <primary>ANY</primary>
+    </indexterm>
+    <indexterm>
+      <primary>SOME</primary>
+    </indexterm>
+    <para>
+      Boolean aggregates <function>bool_and</function> and 
+      <function>bool_or</function> correspond to standard SQL aggregates
+      <function>every</function> and <function>any</function> or
+      <function>some</function>. 
+      As for <function>any</function> and <function>some</function>, 
+      it seems that there is an ambiguity built into the standard syntax:
+<programlisting>
+SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;
+</programlisting>
+      Here <function>ANY</function> can be considered both as leading
+      to a subquery or as an aggregate if the select expression returns 1 row.
+      Thus the standard name cannot be given to these aggregates.
+    </para>
+  </note>
 
   <note>
    <para>
-    Prior to <productname>PostgreSQL</productname> 8.2, the
-    <literal>&lt;</>, <literal>&lt;=</>, <literal>&gt;</> and <literal>&gt;=</>
-    cases were not handled per SQL specification.  A comparison like
-    <literal>ROW(a,b) &lt; ROW(c,d)</>
-    was implemented as
-    <literal>a &lt; c AND b &lt; d</>
-    whereas the correct behavior is equivalent to
-    <literal>a &lt; c OR (a = c AND b &lt; d)</>.
+    Users accustomed to working with other SQL database management
+    systems might be surprised by the performance of the
+    <function>count</function> aggregate when it is applied to the
+    entire table. A query like:
+<programlisting>
+SELECT count(*) FROM sometable;
+</programlisting>
+    will be executed by <productname>PostgreSQL</productname> using a
+    sequential scan of the entire table.
    </para>
   </note>
 
-<synopsis>
-<replaceable>row_constructor</replaceable> IS DISTINCT FROM <replaceable>row_constructor</replaceable>
-</synopsis>
 
   <para>
-   This construct is similar to a <literal>&lt;&gt;</literal> row comparison,
-   but it does not yield null for null inputs.  Instead, any null value is
-   considered unequal to (distinct from) any non-null value, and any two
-   nulls are considered equal (not distinct).  Thus the result will always
-   be either true or false, never null.
+   <xref linkend="functions-aggregate-statistics-table"> shows
+   aggregate functions typically used in statistical analysis.
+   (These are separated out merely to avoid cluttering the listing
+   of more-commonly-used aggregates.)  Where the description mentions
+   <replaceable class="parameter">N</replaceable>, it means the
+   number of input rows for which all the input expressions are non-null.
+   In all cases, null is returned if the computation is meaningless,
+   for example when <replaceable class="parameter">N</replaceable> is zero.
   </para>
 
-<synopsis>
-<replaceable>row_constructor</replaceable> IS NOT DISTINCT FROM <replaceable>row_constructor</replaceable>
-</synopsis>
+  <indexterm>
+   <primary>statistics</primary>
+  </indexterm>
+  <indexterm>
+   <primary>linear regression</primary>
+  </indexterm>
 
-  <para>
-   This construct is similar to a <literal>=</literal> row comparison,
-   but it does not yield null for null inputs.  Instead, any null value is
-   considered unequal to (distinct from) any non-null value, and any two
-   nulls are considered equal (not distinct).  Thus the result will always
-   be either true or false, never null.
-  </para>
+  <table id="functions-aggregate-statistics-table">
+   <title>Aggregate Functions for Statistics</title>
+
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Function</entry>
+      <entry>Argument Type</entry>
+      <entry>Return Type</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+
+     <row>
+      <entry>
+       <indexterm>
+        <primary>correlation</primary>
+       </indexterm>
+       <function>corr(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>correlation coefficient</entry>
+     </row>
+
+     <row>
+      <entry>
+       <indexterm>
+        <primary>covariance</primary>
+        <secondary>population</secondary>
+       </indexterm>
+       <function>covar_pop(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>population covariance</entry>
+     </row>
+
+     <row>
+      <entry>
+       <indexterm>
+        <primary>covariance</primary>
+        <secondary>sample</secondary>
+       </indexterm>
+       <function>covar_samp(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>sample covariance</entry>
+     </row>
+
+     <row>
+      <entry>
+       <function>regr_avgx(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>average of the independent variable
+      (<literal>sum(<replaceable class="parameter">X</replaceable>)/<replaceable class="parameter">N</replaceable></literal>)</entry>
+     </row>
+
+     <row>
+      <entry>
+       <function>regr_avgy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>average of the dependent variable
+      (<literal>sum(<replaceable class="parameter">Y</replaceable>)/<replaceable class="parameter">N</replaceable></literal>)</entry>
+     </row>
+
+     <row>
+      <entry>
+       <function>regr_count(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>bigint</type>
+      </entry>
+      <entry>number of input rows in which both expressions are nonnull</entry>
+     </row>
+
+     <row>
+      <entry>
+       <indexterm>
+        <primary>regression intercept</primary>
+       </indexterm>
+       <function>regr_intercept(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>y-intercept of the least-squares-fit linear equation
+      determined by the (<replaceable
+      class="parameter">X</replaceable>, <replaceable
+      class="parameter">Y</replaceable>) pairs</entry>
+     </row>
+
+     <row>
+      <entry>
+       <function>regr_r2(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>square of the correlation coefficient</entry>
+     </row>
+
+     <row>
+      <entry>
+       <indexterm>
+        <primary>regression slope</primary>
+       </indexterm>
+       <function>regr_slope(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>slope of the least-squares-fit linear equation determined
+      by the (<replaceable class="parameter">X</replaceable>,
+      <replaceable class="parameter">Y</replaceable>) pairs</entry>
+     </row>
 
-  </sect2>
- </sect1>
+     <row>
+      <entry>
+       <function>regr_sxx(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry><literal>sum(<replaceable
+      class="parameter">X</replaceable>^2) - sum(<replaceable
+      class="parameter">X</replaceable>)^2/<replaceable
+      class="parameter">N</replaceable></literal> (<quote>sum of
+      squares</quote> of the independent variable)</entry>
+     </row>
 
- <sect1 id="functions-srf">
-  <title>Set Returning Functions</title>
+     <row>
+      <entry>
+       <function>regr_sxy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry><literal>sum(<replaceable
+      class="parameter">X</replaceable>*<replaceable
+      class="parameter">Y</replaceable>) - sum(<replaceable
+      class="parameter">X</replaceable>) * sum(<replaceable
+      class="parameter">Y</replaceable>)/<replaceable
+      class="parameter">N</replaceable></literal> (<quote>sum of
+      products</quote> of independent times dependent
+      variable)</entry>
+     </row>
 
-  <indexterm zone="functions-srf">
-   <primary>set returning functions</primary>
-   <secondary>functions</secondary>
-  </indexterm>
+     <row>
+      <entry>
+       <function>regr_syy(<replaceable class="parameter">Y</replaceable>, <replaceable class="parameter">X</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry>
+       <type>double precision</type>
+      </entry>
+      <entry><literal>sum(<replaceable
+      class="parameter">Y</replaceable>^2) - sum(<replaceable
+      class="parameter">Y</replaceable>)^2/<replaceable
+      class="parameter">N</replaceable></literal> (<quote>sum of
+      squares</quote> of the dependent variable)</entry>
+     </row>
 
-  <indexterm>
-   <primary>generate_series</primary>
-  </indexterm>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>standard deviation</primary>
+       </indexterm>
+       <function>stddev(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, or <type>numeric</type>
+      </entry>
+      <entry>
+       <type>double precision</type> for floating-point arguments,
+       otherwise <type>numeric</type>
+      </entry>
+      <entry>historical alias for <function>stddev_samp</function></entry>
+     </row>
 
-  <para>
-   This section describes functions that possibly return more than one row.
-   Currently the only functions in this class are series generating functions,
-   as detailed in <xref linkend="functions-srf-series">.
-  </para>
+     <row>
+      <entry>
+       <indexterm>
+        <primary>standard deviation</primary>
+        <secondary>population</secondary>
+       </indexterm>
+       <function>stddev_pop(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, or <type>numeric</type>
+      </entry>
+      <entry>
+       <type>double precision</type> for floating-point arguments,
+       otherwise <type>numeric</type>
+      </entry>
+      <entry>population standard deviation of the input values</entry>
+     </row>
 
-  <table id="functions-srf-series">
-   <title>Series Generating Functions</title>
-   <tgroup cols="4">
-    <thead>
      <row>
-      <entry>Function</entry>
-      <entry>Argument Type</entry>
-      <entry>Return Type</entry>
-      <entry>Description</entry>
+      <entry>
+       <indexterm>
+        <primary>standard deviation</primary>
+        <secondary>sample</secondary>
+       </indexterm>
+       <function>stddev_samp(<replaceable class="parameter">expression</replaceable>)</function>
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, or <type>numeric</type>
+      </entry>
+      <entry>
+       <type>double precision</type> for floating-point arguments,
+       otherwise <type>numeric</type>
+      </entry>
+      <entry>sample standard deviation of the input values</entry>
      </row>
-    </thead>
 
-    <tbody>
      <row>
-      <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>)</literal></entry>
-      <entry><type>int</type> or <type>bigint</type></entry>
-      <entry><type>setof int</type> or <type>setof bigint</type> (same as argument type)</entry>
       <entry>
-       Generate a series of values, from <parameter>start</parameter> to <parameter>stop</parameter>
-       with a step size of one
+       <indexterm>
+        <primary>variance</primary>
+       </indexterm>
+       <function>variance</function>(<replaceable class="parameter">expression</replaceable>)
       </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, or <type>numeric</type>
+      </entry>
+      <entry>
+       <type>double precision</type> for floating-point arguments,
+       otherwise <type>numeric</type>
+      </entry>
+      <entry>historical alias for <function>var_samp</function></entry>
      </row>
 
      <row>
-      <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>, <parameter>step</parameter>)</literal></entry>
-      <entry><type>int</type> or <type>bigint</type></entry>
-      <entry><type>setof int</type> or <type>setof bigint</type> (same as argument type)</entry>
       <entry>
-       Generate a series of values, from <parameter>start</parameter> to <parameter>stop</parameter>
-       with a step size of <parameter>step</parameter>
+       <indexterm>
+        <primary>variance</primary>
+        <secondary>population</secondary>
+       </indexterm>
+       <function>var_pop</function>(<replaceable class="parameter">expression</replaceable>)
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, or <type>numeric</type>
+      </entry>
+      <entry>
+       <type>double precision</type> for floating-point arguments,
+       otherwise <type>numeric</type>
       </entry>
+      <entry>population variance of the input values (square of the population standard deviation)</entry>
      </row>
 
+     <row>
+      <entry>
+       <indexterm>
+        <primary>variance</primary>
+        <secondary>sample</secondary>
+       </indexterm>
+       <function>var_samp</function>(<replaceable class="parameter">expression</replaceable>)
+      </entry>
+      <entry>
+       <type>smallint</type>, <type>int</type>,
+       <type>bigint</type>, <type>real</type>, <type>double
+       precision</type>, or <type>numeric</type>
+      </entry>
+      <entry>
+       <type>double precision</type> for floating-point arguments,
+       otherwise <type>numeric</type>
+      </entry>
+      <entry>sample variance of the input values (square of the sample standard deviation)</entry>
+     </row>
     </tbody>
    </tgroup>
-  </table>
-
-  <para>
-   When <parameter>step</parameter> is positive, zero rows are returned if
-   <parameter>start</parameter> is greater than <parameter>stop</parameter>.
-   Conversely, when <parameter>step</parameter> is negative, zero rows are
-   returned if <parameter>start</parameter> is less than <parameter>stop</parameter>.
-   Zero rows are also returned for <literal>NULL</literal> inputs. It is an error
-   for <parameter>step</parameter> to be zero. Some examples follow:
-<programlisting>
-select * from generate_series(2,4);
- generate_series
------------------
-               2
-               3
-               4
-(3 rows)
-
-select * from generate_series(5,1,-2);
- generate_series
------------------
-               5
-               3
-               1
-(3 rows)
-
-select * from generate_series(4,3);
- generate_series
------------------
-(0 rows)
-
-select current_date + s.a as dates from generate_series(0,14,7) as s(a);
-   dates
-------------
- 2004-02-05
- 2004-02-12
- 2004-02-19
-(3 rows)
-</programlisting>
-  </para>
- </sect1>
-
- <sect1 id="functions-info">
-  <title>System Information Functions</title>
-
-  <para>
-   <xref linkend="functions-info-session-table"> shows several
-   functions that extract session and system information.
-  </para>
-
-   <table id="functions-info-session-table">
-    <title>Session Information Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
-
-     <tbody>
-      <row>
-       <entry><literal><function>current_database</function>()</literal></entry>
-       <entry><type>name</type></entry>
-       <entry>name of current database</entry>
-      </row>
+  </table>
 
-      <row>
-       <entry><literal><function>current_schema</function>()</literal></entry>
-       <entry><type>name</type></entry>
-       <entry>name of current schema</entry>
-      </row>
+ </sect1>
 
-      <row>
-       <entry><literal><function>current_schemas</function>(<type>boolean</type>)</literal></entry>
-       <entry><type>name[]</type></entry>
-       <entry>names of schemas in search path optionally including implicit schemas</entry>
-      </row>
 
-      <row>
-       <entry><literal><function>current_user</function></literal></entry>
-       <entry><type>name</type></entry>
-       <entry>user name of current execution context</entry>
-      </row>
+ <sect1 id="functions-subquery">
+  <title>Subquery Expressions</title>
 
-      <row>
-       <entry><literal><function>inet_client_addr</function>()</literal></entry>
-       <entry><type>inet</type></entry>
-       <entry>address of the remote connection</entry>
-      </row>
+  <indexterm>
+   <primary>EXISTS</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>inet_client_port</function>()</literal></entry>
-       <entry><type>int</type></entry>
-       <entry>port of the remote connection</entry>
-      </row>
+  <indexterm>
+   <primary>IN</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>inet_server_addr</function>()</literal></entry>
-       <entry><type>inet</type></entry>
-       <entry>address of the local connection</entry>
-      </row>
+  <indexterm>
+   <primary>NOT IN</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>inet_server_port</function>()</literal></entry>
-       <entry><type>int</type></entry>
-       <entry>port of the local connection</entry>
-      </row>
+  <indexterm>
+   <primary>ANY</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>pg_my_temp_schema</function>()</literal></entry>
-       <entry><type>oid</type></entry>
-       <entry>OID of session's temporary schema, or 0 if none</entry>
-      </row>
+  <indexterm>
+   <primary>ALL</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>pg_is_other_temp_schema</function>(<type>oid</type>)</literal></entry>
-       <entry><type>boolean</type></entry>
-       <entry>is schema another session's temporary schema?</entry>
-      </row>
+  <indexterm>
+   <primary>SOME</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>pg_postmaster_start_time</function>()</literal></entry>
-       <entry><type>timestamp with time zone</type></entry>
-       <entry>server start time</entry>
-      </row>
+  <indexterm>
+   <primary>subquery</primary>
+  </indexterm>
 
-      <row>
-       <entry><literal><function>session_user</function></literal></entry>
-       <entry><type>name</type></entry>
-       <entry>session user name</entry>
-      </row>
+  <para>
+   This section describes the <acronym>SQL</acronym>-compliant subquery
+   expressions available in <productname>PostgreSQL</productname>.
+   All of the expression forms documented in this section return
+   Boolean (true/false) results.
+  </para>
 
-      <row>
-       <entry><literal><function>user</function></literal></entry>
-       <entry><type>name</type></entry>
-       <entry>equivalent to <function>current_user</function></entry>
-      </row>
+  <sect2>
+   <title><literal>EXISTS</literal></title>
 
-      <row>
-       <entry><literal><function>version</function>()</literal></entry>
-       <entry><type>text</type></entry>
-       <entry><productname>PostgreSQL</> version information</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
+<synopsis>
+EXISTS (<replaceable>subquery</replaceable>)
+</synopsis>
 
-   <indexterm zone="functions-info">
-    <primary>user</primary>
-    <secondary>current</secondary>
-   </indexterm>
+  <para>
+   The argument of <token>EXISTS</token> is an arbitrary <command>SELECT</> statement,
+   or <firstterm>subquery</firstterm>.  The
+   subquery is evaluated to determine whether it returns any rows.
+   If it returns at least one row, the result of <token>EXISTS</token> is
+   <quote>true</>; if the subquery returns no rows, the result of <token>EXISTS</token> 
+   is <quote>false</>.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>schema</primary>
-    <secondary>current</secondary>
-   </indexterm>
+  <para>
+   The subquery can refer to variables from the surrounding query,
+   which will act as constants during any one evaluation of the subquery.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>search path</primary>
-    <secondary>current</secondary>
-   </indexterm>
+  <para>
+   The subquery will generally only be executed far enough to determine
+   whether at least one row is returned, not all the way to completion.
+   It is unwise to write a subquery that has any side effects (such as
+   calling sequence functions); whether the side effects occur or not
+   might be difficult to predict.
+  </para>
 
-   <para>
-    The <function>session_user</function> is normally the user who initiated
-    the current database connection; but superusers can change this setting
-    with <xref linkend="sql-set-session-authorization" endterm="sql-set-session-authorization-title">.
-    The <function>current_user</function> is the user identifier
-    that is applicable for permission checking. Normally, it is equal
-    to the session user, but it can be changed with
-    <xref linkend="sql-set-role" endterm="sql-set-role-title">.
-    It also changes during the execution of
-    functions with the attribute <literal>SECURITY DEFINER</literal>.
-    In Unix parlance, the session user is the <quote>real user</quote> and
-    the current user is the <quote>effective user</quote>.
-   </para>
+  <para>
+   Since the result depends only on whether any rows are returned,
+   and not on the contents of those rows, the output list of the
+   subquery is normally uninteresting.  A common coding convention is
+   to write all <literal>EXISTS</> tests in the form
+   <literal>EXISTS(SELECT 1 WHERE ...)</literal>.  There are exceptions to
+   this rule however, such as subqueries that use <token>INTERSECT</token>.
+  </para>
 
-   <note>
-    <para>
-     <function>current_user</function>, <function>session_user</function>, and
-     <function>user</function> have special syntactic status in <acronym>SQL</acronym>:
-     they must be called without trailing parentheses.
-    </para>
-   </note>
+  <para>
+   This simple example is like an inner join on <literal>col2</>, but
+   it produces at most one output row for each <literal>tab1</> row,
+   even if there are multiple matching <literal>tab2</> rows:
+<screen>
+SELECT col1 FROM tab1
+    WHERE EXISTS(SELECT 1 FROM tab2 WHERE col2 = tab1.col2);
+</screen>
+  </para>
+  </sect2>
 
-   <para>
-    <function>current_schema</function> returns the name of the schema that is
-    at the front of the search path (or a null value if the search path is
-    empty).  This is the schema that will be used for any tables or
-    other named objects that are created without specifying a target schema.
-    <function>current_schemas(boolean)</function> returns an array of the names of all
-    schemas presently in the search path.  The Boolean option determines whether or not
-    implicitly included system schemas such as <literal>pg_catalog</> are included in the search 
-    path returned.
-   </para>
+  <sect2>
+   <title><literal>IN</literal></title>
 
-   <note>
-    <para>
-     The search path can be altered at run time.  The command is:
-<programlisting>
-SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ...</optional>
-</programlisting>
-    </para>
-   </note>
+<synopsis>
+<replaceable>expression</replaceable> IN (<replaceable>subquery</replaceable>)
+</synopsis>
 
-   <indexterm zone="functions-info">
-    <primary>inet_client_addr</primary>
-   </indexterm>
+  <para>
+   The right-hand side is a parenthesized
+   subquery, which must return exactly one column.  The left-hand expression
+   is evaluated and compared to each row of the subquery result.
+   The result of <token>IN</token> is <quote>true</> if any equal subquery row is found.
+   The result is <quote>false</> if no equal row is found (including the special
+   case where the subquery returns no rows).
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>inet_client_port</primary>
-   </indexterm>
+  <para>
+   Note that if the left-hand expression yields null, or if there are
+   no equal right-hand values and at least one right-hand row yields
+   null, the result of the <token>IN</token> construct will be null, not false.
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>inet_server_addr</primary>
-   </indexterm>
+  <para>
+   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
+   be evaluated completely.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>inet_server_port</primary>
-   </indexterm>
+<synopsis>
+<replaceable>row_constructor</replaceable> IN (<replaceable>subquery</replaceable>)
+</synopsis>
+
+  <para>
+   The left-hand side of this form of <token>IN</token> is a row constructor,
+   as described in <xref linkend="sql-syntax-row-constructors">.
+   The right-hand side is a parenthesized
+   subquery, which must return exactly as many columns as there are
+   expressions in the left-hand row.  The left-hand expressions are
+   evaluated and compared row-wise to each row of the subquery result.
+   The result of <token>IN</token> is <quote>true</> if any equal subquery row is found.
+   The result is <quote>false</> if no equal row is found (including the special
+   case where the subquery returns no rows).
+  </para>
+
+  <para>
+   As usual, null values in the rows are combined per
+   the normal rules of SQL Boolean expressions.  Two rows are considered
+   equal if all their corresponding members are non-null and equal; the rows
+   are unequal if any corresponding members are non-null and unequal;
+   otherwise the result of that row comparison is unknown (null).
+   If all the per-row results are either unequal or null, with at least one
+   null, then the result of <token>IN</token> is null.
+  </para>
+  </sect2>
+
+  <sect2>
+   <title><literal>NOT IN</literal></title>
 
-   <para>
-     <function>inet_client_addr</function> returns the IP address of the
-     current client, and <function>inet_client_port</function> returns the
-     port number.
-     <function>inet_server_addr</function> returns the IP address on which
-     the server accepted the current connection, and
-     <function>inet_server_port</function> returns the port number.
-     All these functions return NULL if the current connection is via a
-     Unix-domain socket.
-   </para>
+<synopsis>
+<replaceable>expression</replaceable> NOT IN (<replaceable>subquery</replaceable>)
+</synopsis>
 
-   <indexterm zone="functions-info">
-    <primary>pg_my_temp_schema</primary>
-   </indexterm>
+  <para>
+   The right-hand side is a parenthesized
+   subquery, which must return exactly one column.  The left-hand expression
+   is evaluated and compared to each row of the subquery result.
+   The result of <token>NOT IN</token> is <quote>true</> if only unequal subquery rows
+   are found (including the special case where the subquery returns no rows).
+   The result is <quote>false</> if any equal row is found.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>pg_is_other_temp_schema</primary>
-   </indexterm>
+  <para>
+   Note that if the left-hand expression yields null, or if there are
+   no equal right-hand values and at least one right-hand row yields
+   null, the result of the <token>NOT IN</token> construct will be null, not true.
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
+  </para>
 
-   <para>
-    <function>pg_my_temp_schema</function> returns the OID of the current
-    session's temporary schema, or 0 if it has none (because it has not
-    created any temporary tables).
-    <function>pg_is_other_temp_schema</function> returns true if the
-    given OID is the OID of any other session's temporary schema.
-    (This can be useful, for example, to exclude other sessions' temporary
-    tables from a catalog display.)
-   </para>
+  <para>
+   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
+   be evaluated completely.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>pg_postmaster_start_time</primary>
-   </indexterm>
+<synopsis>
+<replaceable>row_constructor</replaceable> NOT IN (<replaceable>subquery</replaceable>)
+</synopsis>
 
-   <para>
-     <function>pg_postmaster_start_time</function> returns the
-     <type>timestamp with time zone</type> when the
-     server started.
-   </para>
+  <para>
+   The left-hand side of this form of <token>NOT IN</token> is a row constructor,
+   as described in <xref linkend="sql-syntax-row-constructors">.
+   The right-hand side is a parenthesized
+   subquery, which must return exactly as many columns as there are
+   expressions in the left-hand row.  The left-hand expressions are
+   evaluated and compared row-wise to each row of the subquery result.
+   The result of <token>NOT IN</token> is <quote>true</> if only unequal subquery rows
+   are found (including the special case where the subquery returns no rows).
+   The result is <quote>false</> if any equal row is found.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>version</primary>
-   </indexterm>
+  <para>
+   As usual, null values in the rows are combined per
+   the normal rules of SQL Boolean expressions.  Two rows are considered
+   equal if all their corresponding members are non-null and equal; the rows
+   are unequal if any corresponding members are non-null and unequal;
+   otherwise the result of that row comparison is unknown (null).
+   If all the per-row results are either unequal or null, with at least one
+   null, then the result of <token>NOT IN</token> is null.
+  </para>
+  </sect2>
 
-   <para>
-    <function>version</function> returns a string describing the
-    <productname>PostgreSQL</productname> server's version.
-   </para>
+  <sect2>
+   <title><literal>ANY</literal>/<literal>SOME</literal></title>
 
-  <indexterm>
-   <primary>privilege</primary>
-   <secondary>querying</secondary>
-  </indexterm>
+<synopsis>
+<replaceable>expression</replaceable> <replaceable>operator</replaceable> ANY (<replaceable>subquery</replaceable>)
+<replaceable>expression</replaceable> <replaceable>operator</replaceable> SOME (<replaceable>subquery</replaceable>)
+</synopsis>
 
   <para>
-   <xref linkend="functions-info-access-table"> lists functions that
-   allow the user to query object access privileges programmatically.
-   See <xref linkend="ddl-priv"> for more information about
-   privileges.
+   The right-hand side is a parenthesized
+   subquery, which must return exactly one column.  The left-hand expression
+   is evaluated and compared to each row of the subquery result using the
+   given <replaceable>operator</replaceable>, which must yield a Boolean
+   result.
+   The result of <token>ANY</token> is <quote>true</> if any true result is obtained.
+   The result is <quote>false</> if no true result is found (including the special
+   case where the subquery returns no rows).
   </para>
 
-   <table id="functions-info-access-table">
-    <title>Access Privilege Inquiry Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
+  <para>
+   <token>SOME</token> is a synonym for <token>ANY</token>.
+   <token>IN</token> is equivalent to <literal>= ANY</literal>.
+  </para>
 
-     <tbody>
-      <row>
-       <entry><literal><function>has_database_privilege</function>(<parameter>user</parameter>,
-                                  <parameter>database</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for database</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_database_privilege</function>(<parameter>database</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for database</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_function_privilege</function>(<parameter>user</parameter>,
-                                  <parameter>function</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for function</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_function_privilege</function>(<parameter>function</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for function</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_language_privilege</function>(<parameter>user</parameter>,
-                                  <parameter>language</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for language</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_language_privilege</function>(<parameter>language</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for language</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_schema_privilege</function>(<parameter>user</parameter>,
-                                  <parameter>schema</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for schema</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_schema_privilege</function>(<parameter>schema</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for schema</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_table_privilege</function>(<parameter>user</parameter>,
-                                  <parameter>table</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for table</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_table_privilege</function>(<parameter>table</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for table</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_tablespace_privilege</function>(<parameter>user</parameter>,
-                                  <parameter>tablespace</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for tablespace</entry>
-      </row>
-      <row>
-       <entry><literal><function>has_tablespace_privilege</function>(<parameter>tablespace</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for tablespace</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_has_role</function>(<parameter>user</parameter>,
-                                  <parameter>role</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does user have privilege for role</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_has_role</function>(<parameter>role</parameter>,
-                                  <parameter>privilege</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>does current user have privilege for role</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
+  <para>
+   Note that if there are no successes and at least one right-hand row yields
+   null for the operator's result, the result of the <token>ANY</token> construct
+   will be null, not false.
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
+  </para>
 
-   <indexterm zone="functions-info">
-    <primary>has_database_privilege</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>has_function_privilege</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>has_language_privilege</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>has_schema_privilege</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>has_table_privilege</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>has_tablespace_privilege</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>pg_has_role</primary>
-   </indexterm>
+  <para>
+   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
+   be evaluated completely.
+  </para>
 
-   <para>
-    <function>has_database_privilege</function> checks whether a user
-    can access a database in a particular way.  The possibilities for its
-    arguments are analogous to <function>has_table_privilege</function>.
-    The desired access privilege type must evaluate to
-    <literal>CREATE</literal>,
-    <literal>CONNECT</literal>,
-    <literal>TEMPORARY</literal>, or
-    <literal>TEMP</literal> (which is equivalent to
-    <literal>TEMPORARY</literal>).
-   </para>
+<synopsis>
+<replaceable>row_constructor</replaceable> <replaceable>operator</> ANY (<replaceable>subquery</replaceable>)
+<replaceable>row_constructor</replaceable> <replaceable>operator</> SOME (<replaceable>subquery</replaceable>)
+</synopsis>
 
-   <para>
-    <function>has_function_privilege</function> checks whether a user
-    can access a function in a particular way.  The possibilities for its
-    arguments are analogous to <function>has_table_privilege</function>.
-    When specifying a function by a text string rather than by OID,
-    the allowed input is the same as for the <type>regprocedure</> data type
-    (see <xref linkend="datatype-oid">).
-    The desired access privilege type must evaluate to
-    <literal>EXECUTE</literal>.
-    An example is:
-<programlisting>
-SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
-</programlisting>
-   </para>
+  <para>
+   The left-hand side of this form of <token>ANY</token> is a row constructor,
+   as described in <xref linkend="sql-syntax-row-constructors">.
+   The right-hand side is a parenthesized
+   subquery, which must return exactly as many columns as there are
+   expressions in the left-hand row.  The left-hand expressions are
+   evaluated and compared row-wise to each row of the subquery result,
+   using the given <replaceable>operator</replaceable>.
+   The result of <token>ANY</token> is <quote>true</> if the comparison
+   returns true for any subquery row.
+   The result is <quote>false</> if the comparison returns false for every
+   subquery row (including the special case where the subquery returns no
+   rows).
+   The result is NULL if the comparison does not return true for any row,
+   and it returns NULL for at least one row.
+  </para>
 
-   <para>
-    <function>has_language_privilege</function> checks whether a user
-    can access a procedural language in a particular way.  The possibilities
-    for its arguments are analogous to <function>has_table_privilege</function>.
-    The desired access privilege type must evaluate to
-    <literal>USAGE</literal>.
-   </para>
+  <para>
+   See <xref linkend="row-wise-comparison"> for details about the meaning
+   of a row-wise comparison.
+  </para>
+  </sect2>
 
-   <para>
-    <function>has_schema_privilege</function> checks whether a user
-    can access a schema in a particular way.  The possibilities for its
-    arguments are analogous to <function>has_table_privilege</function>.
-    The desired access privilege type must evaluate to
-    <literal>CREATE</literal> or
-    <literal>USAGE</literal>.
-   </para>
+  <sect2>
+   <title><literal>ALL</literal></title>
 
-   <para>
-    <function>has_table_privilege</function> checks whether a user
-    can access a table in a particular way.  The user can be
-    specified by name or by OID
-    (<literal>pg_authid.oid</literal>), or if the argument is
-    omitted
-    <function>current_user</function> is assumed.  The table can be specified
-    by name or by OID.  (Thus, there are actually six variants of
-    <function>has_table_privilege</function>, which can be distinguished by
-    the number and types of their arguments.)  When specifying by name,
-    the name can be schema-qualified if necessary.
-    The desired access privilege type
-    is specified by a text string, which must evaluate to one of the
-    values <literal>SELECT</literal>, <literal>INSERT</literal>,
-    <literal>UPDATE</literal>, <literal>DELETE</literal>,
-    <literal>REFERENCES</literal>, or <literal>TRIGGER</literal>.
-    (Case of the string is not significant, however.)
-    An example is:
-<programlisting>
-SELECT has_table_privilege('myschema.mytable', 'select');
-</programlisting>
-   </para>
+<synopsis>
+<replaceable>expression</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>)
+</synopsis>
 
-   <para>
-    <function>has_tablespace_privilege</function> checks whether a user
-    can access a tablespace in a particular way.  The possibilities for its
-    arguments are analogous to <function>has_table_privilege</function>.
-    The desired access privilege type must evaluate to
-    <literal>CREATE</literal>.
-   </para>
+  <para>
+   The right-hand side is a parenthesized
+   subquery, which must return exactly one column.  The left-hand expression
+   is evaluated and compared to each row of the subquery result using the
+   given <replaceable>operator</replaceable>, which must yield a Boolean
+   result.
+   The result of <token>ALL</token> is <quote>true</> if all rows yield true
+   (including the special case where the subquery returns no rows).
+   The result is <quote>false</> if any false result is found.
+   The result is NULL if the comparison does not return false for any row,
+   and it returns NULL for at least one row.
+  </para>
 
-   <para>
-    <function>pg_has_role</function> checks whether a user
-    can access a role in a particular way.  The possibilities for its
-    arguments are analogous to <function>has_table_privilege</function>.
-    The desired access privilege type must evaluate to
-    <literal>MEMBER</literal> or
-    <literal>USAGE</literal>.
-    <literal>MEMBER</literal> denotes direct or indirect membership in
-    the role (that is, the right to do <command>SET ROLE</>), while
-    <literal>USAGE</literal> denotes whether the privileges of the role
-    are immediately available without doing <command>SET ROLE</>.
-   </para>
+  <para>
+   <token>NOT IN</token> is equivalent to <literal>&lt;&gt; ALL</literal>.
+  </para>
 
   <para>
-   To test whether a user holds a grant option on the privilege,
-   append <literal>WITH GRANT OPTION</literal> to the privilege key
-   word; for example <literal>'UPDATE WITH GRANT OPTION'</literal>.
+   As with <token>EXISTS</token>, it's unwise to assume that the subquery will
+   be evaluated completely.
   </para>
 
+<synopsis>
+<replaceable>row_constructor</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>)
+</synopsis>
+
   <para>
-   <xref linkend="functions-info-schema-table"> shows functions that
-   determine whether a certain object is <firstterm>visible</> in the
-   current schema search path.  A table is said to be visible if its
-   containing schema is in the search path and no table of the same
-   name appears earlier in the search path.  This is equivalent to the
-   statement that the table can be referenced by name without explicit
-   schema qualification.  For example, to list the names of all
-   visible tables:
-<programlisting>
-SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
-</programlisting>
+   The left-hand side of this form of <token>ALL</token> is a row constructor,
+   as described in <xref linkend="sql-syntax-row-constructors">.
+   The right-hand side is a parenthesized
+   subquery, which must return exactly as many columns as there are
+   expressions in the left-hand row.  The left-hand expressions are
+   evaluated and compared row-wise to each row of the subquery result,
+   using the given <replaceable>operator</replaceable>.
+   The result of <token>ALL</token> is <quote>true</> if the comparison
+   returns true for all subquery rows (including the special
+   case where the subquery returns no rows).
+   The result is <quote>false</> if the comparison returns false for any
+   subquery row.
+   The result is NULL if the comparison does not return false for any
+   subquery row, and it returns NULL for at least one row.
   </para>
 
-   <table id="functions-info-schema-table">
-    <title>Schema Visibility Inquiry Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
+  <para>
+   See <xref linkend="row-wise-comparison"> for details about the meaning
+   of a row-wise comparison.
+  </para>
+  </sect2>
 
-     <tbody>
-      <row>
-       <entry><literal><function>pg_conversion_is_visible</function>(<parameter>conversion_oid</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>is conversion visible in search path</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_function_is_visible</function>(<parameter>function_oid</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>is function visible in search path</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_operator_is_visible</function>(<parameter>operator_oid</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>is operator visible in search path</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_opclass_is_visible</function>(<parameter>opclass_oid</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>is operator class visible in search path</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_table_is_visible</function>(<parameter>table_oid</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>is table visible in search path</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_type_is_visible</function>(<parameter>type_oid</parameter>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>is type (or domain) visible in search path</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
+  <sect2>
+   <title>Row-wise Comparison</title>
 
-   <indexterm zone="functions-info">
-    <primary>pg_conversion_is_visible</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>pg_function_is_visible</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>pg_operator_is_visible</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>pg_opclass_is_visible</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>pg_table_is_visible</primary>
-   </indexterm>
-   <indexterm zone="functions-info">
-    <primary>pg_type_is_visible</primary>
+   <indexterm zone="functions-subquery">
+    <primary>comparison</primary>
+    <secondary>subquery result row</secondary>
    </indexterm>
 
-   <para>
-    <function>pg_conversion_is_visible</function>,
-    <function>pg_function_is_visible</function>,
-    <function>pg_operator_is_visible</function>,
-    <function>pg_opclass_is_visible</function>,
-    <function>pg_table_is_visible</function>, and
-    <function>pg_type_is_visible</function> perform the visibility check for
-    conversions, functions, operators, operator classes, tables, and
-    types. Note that <function>pg_table_is_visible</function> can also be used
-    with views, indexes and sequences; <function>pg_type_is_visible</function>
-    can also be used with domains. For functions and operators, an object in
-    the search path is visible if there is no object of the same name
-    <emphasis>and argument data type(s)</> earlier in the path.  For operator
-    classes, both name and associated index access method are considered.
-   </para>
+<synopsis>
+<replaceable>row_constructor</replaceable> <replaceable>operator</replaceable> (<replaceable>subquery</replaceable>)
+</synopsis>
+
+  <para>
+   The left-hand side is a row constructor,
+   as described in <xref linkend="sql-syntax-row-constructors">.
+   The right-hand side is a parenthesized subquery, which must return exactly
+   as many columns as there are expressions in the left-hand row. Furthermore,
+   the subquery cannot return more than one row.  (If it returns zero rows,
+   the result is taken to be null.)  The left-hand side is evaluated and
+   compared row-wise to the single subquery result row.
+  </para>
+
+  <para>
+   See <xref linkend="row-wise-comparison"> for details about the meaning
+   of a row-wise comparison.
+  </para>
+  </sect2>
+ </sect1>
+
 
-   <para>
-    All these functions require object OIDs to identify the object to be
-    checked.  If you want to test an object by name, it is convenient to use
-    the OID alias types (<type>regclass</>, <type>regtype</>,
-    <type>regprocedure</>, or <type>regoperator</>), for example:
-<programlisting>
-SELECT pg_type_is_visible('myschema.widget'::regtype);
-</programlisting>
-    Note that it would not make much sense to test an unqualified name in
-    this way &mdash; if the name can be recognized at all, it must be visible.
-   </para>
+ <sect1 id="functions-comparisons">
+  <title>Row and Array Comparisons</title>
 
-   <indexterm zone="functions-info">
-    <primary>format_type</primary>
-   </indexterm>
+  <indexterm>
+   <primary>IN</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_viewdef</primary>
-   </indexterm>
+  <indexterm>
+   <primary>NOT IN</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_ruledef</primary>
-   </indexterm>
+  <indexterm>
+   <primary>ANY</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_indexdef</primary>
-   </indexterm>
+  <indexterm>
+   <primary>ALL</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_triggerdef</primary>
-   </indexterm>
+  <indexterm>
+   <primary>SOME</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_constraintdef</primary>
-   </indexterm>
+  <indexterm>
+   <primary>row-wise comparison</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_expr</primary>
-   </indexterm>
+  <indexterm>
+   <primary>comparison</primary>
+   <secondary>row-wise</secondary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_userbyid</primary>
-   </indexterm>
+  <indexterm>
+   <primary>IS DISTINCT FROM</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_get_serial_sequence</primary>
-   </indexterm>
+  <indexterm>
+   <primary>IS NOT DISTINCT FROM</primary>
+  </indexterm>
 
-   <indexterm zone="functions-info">
-    <primary>pg_tablespace_databases</primary>
-   </indexterm>
+  <para>
+   This section describes several specialized constructs for making
+   multiple comparisons between groups of values.  These forms are
+   syntactically related to the subquery forms of the previous section,
+   but do not involve subqueries.
+   The forms involving array subexpressions are
+   <productname>PostgreSQL</productname> extensions; the rest are
+   <acronym>SQL</acronym>-compliant.
+   All of the expression forms documented in this section return
+   Boolean (true/false) results.
+  </para>
+
+  <sect2>
+   <title><literal>IN</literal></title>
+
+<synopsis>
+<replaceable>expression</replaceable> IN (<replaceable>value</replaceable> <optional>, ...</optional>)
+</synopsis>
 
   <para>
-   <xref linkend="functions-info-catalog-table"> lists functions that
-   extract information from the system catalogs.
+   The right-hand side is a parenthesized list
+   of scalar expressions.  The result is <quote>true</> if the left-hand expression's
+   result is equal to any of the right-hand expressions.  This is a shorthand
+   notation for
+
+<synopsis>
+<replaceable>expression</replaceable> = <replaceable>value1</replaceable>
+OR
+<replaceable>expression</replaceable> = <replaceable>value2</replaceable>
+OR
+...
+</synopsis>
   </para>
 
-   <table id="functions-info-catalog-table">
-    <title>System Catalog Information Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
+  <para>
+   Note that if the left-hand expression yields null, or if there are
+   no equal right-hand values and at least one right-hand expression yields
+   null, the result of the <token>IN</token> construct will be null, not false.
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
+  </para>
+  </sect2>
 
-     <tbody>
-      <row>
-       <entry><literal><function>format_type</function>(<parameter>type_oid</parameter>, <parameter>typemod</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get SQL name of a data type</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get definition of a constraint</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get definition of a constraint</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>decompile internal form of an expression, assuming that any Vars
-       in it refer to the relation indicated by the second parameter</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>decompile internal form of an expression, assuming that any Vars
-       in it refer to the relation indicated by the second parameter</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get <command>CREATE INDEX</> command for index</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>, <parameter>column_no</>, <parameter>pretty_bool</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get <command>CREATE INDEX</> command for index,
-       or definition of just one index column when
-       <parameter>column_no</> is not zero</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get <command>CREATE RULE</> command for rule</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get <command>CREATE RULE</> command for rule</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_serial_sequence</function>(<parameter>table_name</parameter>, <parameter>column_name</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get name of the sequence that a <type>serial</type> or <type>bigserial</type> column
-       uses</entry>
-      </row>
-      <row>
-       <entry><function>pg_get_triggerdef</function>(<parameter>trigger_oid</parameter>)</entry>
-       <entry><type>text</type></entry>
-       <entry>get <command>CREATE [ CONSTRAINT ] TRIGGER</> command for trigger</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_userbyid</function>(<parameter>roleid</parameter>)</literal></entry>
-       <entry><type>name</type></entry>
-       <entry>get role name with given ID</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>, <parameter>pretty_bool</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get underlying <command>SELECT</command> command for view</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get underlying <command>SELECT</command> command for view</entry>
-      </row>
-      <row>
-       <entry><literal><function>pg_tablespace_databases</function>(<parameter>tablespace_oid</parameter>)</literal></entry>
-       <entry><type>setof oid</type></entry>
-       <entry>get the set of database OIDs that have objects in the tablespace</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
+  <sect2>
+   <title><literal>NOT IN</literal></title>
+
+<synopsis>
+<replaceable>expression</replaceable> NOT IN (<replaceable>value</replaceable> <optional>, ...</optional>)
+</synopsis>
+
+  <para>
+   The right-hand side is a parenthesized list
+   of scalar expressions.  The result is <quote>true</quote> if the left-hand expression's
+   result is unequal to all of the right-hand expressions.  This is a shorthand
+   notation for
+
+<synopsis>
+<replaceable>expression</replaceable> &lt;&gt; <replaceable>value1</replaceable>
+AND
+<replaceable>expression</replaceable> &lt;&gt; <replaceable>value2</replaceable>
+AND
+...
+</synopsis>
+  </para>
+
+  <para>
+   Note that if the left-hand expression yields null, or if there are
+   no equal right-hand values and at least one right-hand expression yields
+   null, the result of the <token>NOT IN</token> construct will be null, not true
+   as one might naively expect.
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
+  </para>
 
+  <tip>
   <para>
-   <function>format_type</function> returns the SQL name of a data type that
-   is identified by its type OID and possibly a type modifier.  Pass NULL
-   for the type modifier if no specific modifier is known.
+   <literal>x NOT IN y</literal> is equivalent to <literal>NOT (x IN y)</literal> in all
+   cases.  However, null values are much more likely to trip up the novice when
+   working with <token>NOT IN</token> than when working with <token>IN</token>.
+   It's best to express your condition positively if possible.
   </para>
+  </tip>
+  </sect2>
+
+  <sect2>
+   <title><literal>ANY</literal>/<literal>SOME</literal> (array)</title>
+
+<synopsis>
+<replaceable>expression</replaceable> <replaceable>operator</replaceable> ANY (<replaceable>array expression</replaceable>)
+<replaceable>expression</replaceable> <replaceable>operator</replaceable> SOME (<replaceable>array expression</replaceable>)
+</synopsis>
 
   <para>
-   <function>pg_get_constraintdef</function>,
-   <function>pg_get_indexdef</function>, <function>pg_get_ruledef</function>,
-   and <function>pg_get_triggerdef</function>, respectively reconstruct the
-   creating command for a constraint, index, rule, or trigger. (Note that this
-   is a decompiled reconstruction, not the original text of the command.)
-   <function>pg_get_expr</function> decompiles the internal form of an
-   individual expression, such as the default value for a column.  It can be
-   useful when examining the contents of system catalogs.
-   <function>pg_get_viewdef</function> reconstructs the <command>SELECT</>
-   query that defines a view. Most of these functions come in two variants,
-   one of which can optionally <quote>pretty-print</> the result.  The
-   pretty-printed format is more readable, but the default format is more
-   likely to be interpreted the same way by future versions of
-   <productname>PostgreSQL</>; avoid using pretty-printed output for dump
-   purposes.  Passing <literal>false</> for the pretty-print parameter yields
-   the same result as the variant that does not have the parameter at all.
+   The right-hand side is a parenthesized expression, which must yield an
+   array value.
+   The left-hand expression
+   is evaluated and compared to each element of the array using the
+   given <replaceable>operator</replaceable>, which must yield a Boolean
+   result.
+   The result of <token>ANY</token> is <quote>true</> if any true result is obtained.
+   The result is <quote>false</> if no true result is found (including the special
+   case where the array has zero elements).
   </para>
 
   <para>
-   <function>pg_get_serial_sequence</function> returns the name of the
-   sequence associated with a column, or NULL if no sequence is associated
-   with the column.  The first input parameter is a table name with
-   optional schema, and the second parameter is a column name.  Because
-   the first parameter is potentially a schema and table, it is not treated
-   as a double-quoted identifier, meaning it is lowercased by default,
-   while the second parameter, being just a column name, is treated as
-   double-quoted and has its case preserved.  The function returns a value
-   suitably formatted for passing to the sequence functions (see <xref
-   linkend="functions-sequence">).  This association can be modified or
-   removed with <command>ALTER SEQUENCE OWNED BY</>.  (The function
-   probably should have been called
-   <function>pg_get_owned_sequence</function>; its name reflects the fact
-   that it's typically used with <type>serial</> or <type>bigserial</>
-   columns.)
+   If the array expression yields a null array, the result of
+   <token>ANY</token> will be null.  If the left-hand expression yields null,
+   the result of <token>ANY</token> is ordinarily null (though a non-strict
+   comparison operator could possibly yield a different result).
+   Also, if the right-hand array contains any null elements and no true
+   comparison result is obtained, the result of <token>ANY</token>
+   will be null, not false (again, assuming a strict comparison operator).
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
   </para>
 
   <para>
-   <function>pg_get_userbyid</function> extracts a role's name given
-   its OID.
+   <token>SOME</token> is a synonym for <token>ANY</token>.
   </para>
+  </sect2>
+
+  <sect2>
+   <title><literal>ALL</literal> (array)</title>
+
+<synopsis>
+<replaceable>expression</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>array expression</replaceable>)
+</synopsis>
 
   <para>
-   <function>pg_tablespace_databases</function> allows a tablespace to be
-   examined. It returns the set of OIDs of databases that have objects stored
-   in the tablespace. If this function returns any rows, the tablespace is not
-   empty and cannot be dropped. To display the specific objects populating the
-   tablespace, you will need to connect to the databases identified by
-   <function>pg_tablespace_databases</function> and query their
-   <structname>pg_class</> catalogs.
+   The right-hand side is a parenthesized expression, which must yield an
+   array value.
+   The left-hand expression
+   is evaluated and compared to each element of the array using the
+   given <replaceable>operator</replaceable>, which must yield a Boolean
+   result.
+   The result of <token>ALL</token> is <quote>true</> if all comparisons yield true
+   (including the special case where the array has zero elements).
+   The result is <quote>false</> if any false result is found.
   </para>
 
-   <indexterm zone="functions-info">
-    <primary>col_description</primary>
-   </indexterm>
+  <para>
+   If the array expression yields a null array, the result of
+   <token>ALL</token> will be null.  If the left-hand expression yields null,
+   the result of <token>ALL</token> is ordinarily null (though a non-strict
+   comparison operator could possibly yield a different result).
+   Also, if the right-hand array contains any null elements and no false
+   comparison result is obtained, the result of <token>ALL</token>
+   will be null, not true (again, assuming a strict comparison operator).
+   This is in accordance with SQL's normal rules for Boolean combinations
+   of null values.
+  </para>
+  </sect2>
 
-   <indexterm zone="functions-info">
-    <primary>obj_description</primary>
-   </indexterm>
+  <sect2 id="row-wise-comparison">
+   <title>Row-wise Comparison</title>
 
-   <indexterm zone="functions-info">
-    <primary>shobj_description</primary>
-   </indexterm>
+<synopsis>
+<replaceable>row_constructor</replaceable> <replaceable>operator</replaceable> <replaceable>row_constructor</replaceable>
+</synopsis>
 
-   <indexterm zone="functions-info">
-    <primary>comment</primary>
-    <secondary sortas="database objects">about database objects</secondary>
-   </indexterm>
+  <para>
+   Each side is a row constructor,
+   as described in <xref linkend="sql-syntax-row-constructors">.
+   The two row values must have the same number of fields.
+   Each side is evaluated and they are compared row-wise.  Row comparisons
+   are allowed when the <replaceable>operator</replaceable> is
+   <literal>=</>,
+   <literal>&lt;&gt;</>,
+   <literal>&lt;</>,
+   <literal>&lt;=</>,
+   <literal>&gt;</> or
+   <literal>&gt;=</>,
+   or has semantics similar to one of these.  (To be specific, an operator
+   can be a row comparison operator if it is a member of a B-Tree operator
+   class, or is the negator of the <literal>=</> member of a B-Tree operator
+   class.)
+  </para>
+
+  <para>
+   The <literal>=</> and <literal>&lt;&gt;</> cases work slightly differently
+   from the others.  Two rows are considered
+   equal if all their corresponding members are non-null and equal; the rows
+   are unequal if any corresponding members are non-null and unequal;
+   otherwise the result of the row comparison is unknown (null).
+  </para>
+
+  <para>
+   For the <literal>&lt;</>, <literal>&lt;=</>, <literal>&gt;</> and
+   <literal>&gt;=</> cases, the row elements are compared left-to-right,
+   stopping as soon as an unequal or null pair of elements is found.
+   If either of this pair of elements is null, the result of the
+   row comparison is unknown (null); otherwise comparison of this pair
+   of elements determines the result.  For example,
+   <literal>ROW(1,2,NULL) &lt; ROW(1,3,0)</>
+   yields true, not null, because the third pair of elements are not
+   considered.
+  </para>
 
+  <note>
    <para>
-    The functions shown in <xref linkend="functions-info-comment-table">
-    extract comments previously stored with the <xref linkend="sql-comment"
-    endterm="sql-comment-title"> command.  A null value is returned if no
-    comment could be found matching the specified parameters.
+    Prior to <productname>PostgreSQL</productname> 8.2, the
+    <literal>&lt;</>, <literal>&lt;=</>, <literal>&gt;</> and <literal>&gt;=</>
+    cases were not handled per SQL specification.  A comparison like
+    <literal>ROW(a,b) &lt; ROW(c,d)</>
+    was implemented as
+    <literal>a &lt; c AND b &lt; d</>
+    whereas the correct behavior is equivalent to
+    <literal>a &lt; c OR (a = c AND b &lt; d)</>.
    </para>
+  </note>
 
-   <table id="functions-info-comment-table">
-    <title>Comment Information Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
+<synopsis>
+<replaceable>row_constructor</replaceable> IS DISTINCT FROM <replaceable>row_constructor</replaceable>
+</synopsis>
 
-     <tbody>
-      <row>
-       <entry><literal><function>col_description</function>(<parameter>table_oid</parameter>, <parameter>column_number</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get comment for a table column</entry>
-      </row>
-      <row>
-       <entry><literal><function>obj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get comment for a database object</entry>
-      </row>
-      <row>
-       <entry><literal><function>obj_description</function>(<parameter>object_oid</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get comment for a database object (<emphasis>deprecated</emphasis>)</entry>
-      </row>
-      <row>
-       <entry><literal><function>shobj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry>
-       <entry><type>text</type></entry>
-       <entry>get comment for a shared database object</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
+  <para>
+   This construct is similar to a <literal>&lt;&gt;</literal> row comparison,
+   but it does not yield null for null inputs.  Instead, any null value is
+   considered unequal to (distinct from) any non-null value, and any two
+   nulls are considered equal (not distinct).  Thus the result will always
+   be either true or false, never null.
+  </para>
 
-   <para>
-    <function>col_description</function> returns the comment for a table column,
-    which is specified by the OID of its table and its column number.
-    <function>obj_description</function> cannot be used for table columns since
-    columns do not have OIDs of their own.
-   </para>
+<synopsis>
+<replaceable>row_constructor</replaceable> IS NOT DISTINCT FROM <replaceable>row_constructor</replaceable>
+</synopsis>
 
-   <para>
-    The two-parameter form of <function>obj_description</function> returns the
-    comment for a database object specified by its OID and the name of the
-    containing system catalog.  For example,
-    <literal>obj_description(123456,'pg_class')</literal>
-    would retrieve the comment for a table with OID 123456.
-    The one-parameter form of <function>obj_description</function> requires only
-    the object OID.  It is now deprecated since there is no guarantee that
-    OIDs are unique across different system catalogs; therefore, the wrong
-    comment could be returned.
-   </para>
+  <para>
+   This construct is similar to a <literal>=</literal> row comparison,
+   but it does not yield null for null inputs.  Instead, any null value is
+   considered unequal to (distinct from) any non-null value, and any two
+   nulls are considered equal (not distinct).  Thus the result will always
+   be either true or false, never null.
+  </para>
 
-   <para>
-    <function>shobj_description</function> is used just like
-    <function>obj_description</function> only that it is used for retrieving
-    comments on shared objects.  Some system catalogs are global to all
-    databases within each cluster and their descriptions are stored globally
-    as well.
-   </para>
-  </sect1>
+  </sect2>
+ </sect1>
+
+ <sect1 id="functions-srf">
+  <title>Set Returning Functions</title>
 
- <sect1 id="functions-admin">
-  <title>System Administration Functions</title>
+  <indexterm zone="functions-srf">
+   <primary>set returning functions</primary>
+   <secondary>functions</secondary>
+  </indexterm>
+
+  <indexterm>
+   <primary>generate_series</primary>
+  </indexterm>
 
   <para>
-   <xref linkend="functions-admin-set-table"> shows the functions
-   available to query and alter run-time configuration parameters.
+   This section describes functions that possibly return more than one row.
+   Currently the only functions in this class are series generating functions,
+   as detailed in <xref linkend="functions-srf-series">.
   </para>
 
-   <table id="functions-admin-set-table">
-    <title>Configuration Settings Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
-     </thead>
-
-     <tbody>
-      <row>
-       <entry>
-        <literal><function>current_setting</function>(<parameter>setting_name</parameter>)</literal>
-       </entry>
-       <entry><type>text</type></entry>
-       <entry>current value of setting</entry>
-      </row>
-      <row>
-       <entry>
-        <literal><function>set_config(<parameter>setting_name</parameter>,
-                             <parameter>new_value</parameter>,
-                             <parameter>is_local</parameter>)</function></literal>
-       </entry>
-       <entry><type>text</type></entry>
-       <entry>set parameter and return new value</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
+  <table id="functions-srf-series">
+   <title>Series Generating Functions</title>
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Function</entry>
+      <entry>Argument Type</entry>
+      <entry>Return Type</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
 
-   <indexterm zone="functions-admin">
-    <primary>SET</primary>
-   </indexterm>
+    <tbody>
+     <row>
+      <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>)</literal></entry>
+      <entry><type>int</type> or <type>bigint</type></entry>
+      <entry><type>setof int</type> or <type>setof bigint</type> (same as argument type)</entry>
+      <entry>
+       Generate a series of values, from <parameter>start</parameter> to <parameter>stop</parameter>
+       with a step size of one
+      </entry>
+     </row>
 
-   <indexterm zone="functions-admin">
-    <primary>SHOW</primary>
-   </indexterm>
+     <row>
+      <entry><literal><function>generate_series</function>(<parameter>start</parameter>, <parameter>stop</parameter>, <parameter>step</parameter>)</literal></entry>
+      <entry><type>int</type> or <type>bigint</type></entry>
+      <entry><type>setof int</type> or <type>setof bigint</type> (same as argument type)</entry>
+      <entry>
+       Generate a series of values, from <parameter>start</parameter> to <parameter>stop</parameter>
+       with a step size of <parameter>step</parameter>
+      </entry>
+     </row>
 
-   <indexterm zone="functions-admin">
-    <primary>configuration</primary>
-    <secondary sortas="server">of the server</secondary>
-    <tertiary>functions</tertiary>
-   </indexterm>
+    </tbody>
+   </tgroup>
+  </table>
 
-   <para>
-    The function <function>current_setting</function> yields the
-    current value of the setting <parameter>setting_name</parameter>.
-    It corresponds to the <acronym>SQL</acronym> command
-    <command>SHOW</command>.  An example:
+  <para>
+   When <parameter>step</parameter> is positive, zero rows are returned if
+   <parameter>start</parameter> is greater than <parameter>stop</parameter>.
+   Conversely, when <parameter>step</parameter> is negative, zero rows are
+   returned if <parameter>start</parameter> is less than <parameter>stop</parameter>.
+   Zero rows are also returned for <literal>NULL</literal> inputs. It is an error
+   for <parameter>step</parameter> to be zero. Some examples follow:
 <programlisting>
-SELECT current_setting('datestyle');
+select * from generate_series(2,4);
+ generate_series
+-----------------
+               2
+               3
+               4
+(3 rows)
 
- current_setting
+select * from generate_series(5,1,-2);
+ generate_series
 -----------------
- ISO, MDY
-(1 row)
-</programlisting>
-   </para>
+               5
+               3
+               1
+(3 rows)
 
-   <para>
-    <function>set_config</function> sets the parameter
-    <parameter>setting_name</parameter> to
-    <parameter>new_value</parameter>.  If
-    <parameter>is_local</parameter> is <literal>true</literal>, the
-    new value will only apply to the current transaction. If you want
-    the new value to apply for the current session, use
-    <literal>false</literal> instead. The function corresponds to the
-    SQL command <command>SET</command>. An example:
-<programlisting>
-SELECT set_config('log_statement_stats', 'off', false);
+select * from generate_series(4,3);
+ generate_series
+-----------------
+(0 rows)
 
- set_config
+select current_date + s.a as dates from generate_series(0,14,7) as s(a);
+   dates
 ------------
- off
-(1 row)
+ 2004-02-05
+ 2004-02-12
+ 2004-02-19
+(3 rows)
 </programlisting>
-   </para>
-
-   <indexterm zone="functions-admin">
-    <primary>pg_cancel_backend</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_reload_conf</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_rotate_logfile</primary>
-   </indexterm>
+  </para>
+ </sect1>
 
-   <indexterm zone="functions-admin">
-    <primary>signal</primary>
-    <secondary sortas="backend">backend processes</secondary>
-   </indexterm>
+ <sect1 id="functions-info">
+  <title>System Information Functions</title>
 
-   <para>
-    The functions shown in <xref
-    linkend="functions-admin-signal-table"> send control signals to
-    other server processes.  Use of these functions is restricted
-    to superusers.
-   </para>
+  <para>
+   <xref linkend="functions-info-session-table"> shows several
+   functions that extract session and system information.
+  </para>
 
-   <table id="functions-admin-signal-table">
-    <title>Server Signalling Functions</title>
+   <table id="functions-info-session-table">
+    <title>Session Information Functions</title>
     <tgroup cols="3">
      <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
-      </row>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
      </thead>
 
      <tbody>
       <row>
-       <entry>
-        <literal><function>pg_cancel_backend</function>(<parameter>pid</parameter> <type>int</>)</literal>
-        </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Cancel a backend's current query</entry>
-      </row>
-      <row>
-       <entry>
-        <literal><function>pg_reload_conf</function>()</literal>
-        </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Cause server processes to reload their configuration files</entry>
-      </row>
-      <row>
-       <entry>
-        <literal><function>pg_rotate_logfile</function>()</literal>
-        </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Rotate server's log file</entry>
+       <entry><literal><function>current_database</function>()</literal></entry>
+       <entry><type>name</type></entry>
+       <entry>name of current database</entry>
       </row>
-     </tbody>
-    </tgroup>
-   </table>
-
-   <para>
-    Each of these functions returns <literal>true</literal> if
-    successful and <literal>false</literal> otherwise.
-   </para>
-
-   <para>
-    <function>pg_cancel_backend</> sends a query cancel
-    (<systemitem>SIGINT</>) signal to a backend process identified by
-    process ID.  The process ID of an active backend can be found from
-    the <structfield>procpid</structfield> column in the
-    <structname>pg_stat_activity</structname> view, or by listing the
-    <command>postgres</command> processes on the server with
-    <application>ps</>.
-   </para>
-
-   <para>
-    <function>pg_reload_conf</> sends a <systemitem>SIGHUP</> signal
-    to the server, causing the configuration files
-    to be reloaded by all server processes.
-   </para>
-
-   <para>
-    <function>pg_rotate_logfile</> signals the log-file manager to switch
-    to a new output file immediately.  This works only when
-    <varname>redirect_stderr</> is used for logging, since otherwise there
-    is no log-file manager subprocess.
-   </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_start_backup</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_stop_backup</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_switch_xlog</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_current_xlog_location</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_current_xlog_insert_location</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_xlogfile_name_offset</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_xlogfile_name</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>backup</primary>
-   </indexterm>
+      <row>
+       <entry><literal><function>current_schema</function>()</literal></entry>
+       <entry><type>name</type></entry>
+       <entry>name of current schema</entry>
+      </row>
 
-   <para>
-    The functions shown in <xref
-    linkend="functions-admin-backup-table"> assist in making on-line backups.
-    Use of the first three functions is restricted to superusers.
-   </para>
+      <row>
+       <entry><literal><function>current_schemas</function>(<type>boolean</type>)</literal></entry>
+       <entry><type>name[]</type></entry>
+       <entry>names of schemas in search path optionally including implicit schemas</entry>
+      </row>
 
-   <table id="functions-admin-backup-table">
-    <title>Backup Control Functions</title>
-    <tgroup cols="3">
-     <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      <row>
+       <entry><literal><function>current_user</function></literal></entry>
+       <entry><type>name</type></entry>
+       <entry>user name of current execution context</entry>
       </row>
-     </thead>
 
-     <tbody>
       <row>
-       <entry>
-        <literal><function>pg_start_backup</function>(<parameter>label</> <type>text</>)</literal>
-        </entry>
-       <entry><type>text</type></entry>
-       <entry>Set up for performing on-line backup</entry>
+       <entry><literal><function>inet_client_addr</function>()</literal></entry>
+       <entry><type>inet</type></entry>
+       <entry>address of the remote connection</entry>
       </row>
+
       <row>
-       <entry>
-        <literal><function>pg_stop_backup</function>()</literal>
-        </entry>
-       <entry><type>text</type></entry>
-       <entry>Finish performing on-line backup</entry>
+       <entry><literal><function>inet_client_port</function>()</literal></entry>
+       <entry><type>int</type></entry>
+       <entry>port of the remote connection</entry>
       </row>
+
       <row>
-       <entry>
-        <literal><function>pg_switch_xlog</function>()</literal>
-        </entry>
-       <entry><type>text</type></entry>
-       <entry>Force switch to a new transaction log file</entry>
+       <entry><literal><function>inet_server_addr</function>()</literal></entry>
+       <entry><type>inet</type></entry>
+       <entry>address of the local connection</entry>
       </row>
+
       <row>
-       <entry>
-        <literal><function>pg_current_xlog_location</function>()</literal>
-        </entry>
-       <entry><type>text</type></entry>
-       <entry>Get current transaction log write location</entry>
+       <entry><literal><function>inet_server_port</function>()</literal></entry>
+       <entry><type>int</type></entry>
+       <entry>port of the local connection</entry>
       </row>
+
       <row>
-       <entry>
-        <literal><function>pg_current_xlog_insert_location</function>()</literal>
-        </entry>
-       <entry><type>text</type></entry>
-       <entry>Get current transaction log insert location</entry>
+       <entry><literal><function>pg_my_temp_schema</function>()</literal></entry>
+       <entry><type>oid</type></entry>
+       <entry>OID of session's temporary schema, or 0 if none</entry>
       </row>
+
       <row>
-       <entry>
-        <literal><function>pg_xlogfile_name_offset</function>(<parameter>location</> <type>text</>)</literal>
-        </entry>
-       <entry><type>text</>, <type>integer</></entry>
-       <entry>Convert transaction log location string to file name and decimal byte offset within file</entry>
+       <entry><literal><function>pg_is_other_temp_schema</function>(<type>oid</type>)</literal></entry>
+       <entry><type>boolean</type></entry>
+       <entry>is schema another session's temporary schema?</entry>
       </row>
+
       <row>
-       <entry>
-        <literal><function>pg_xlogfile_name</function>(<parameter>location</> <type>text</>)</literal>
-        </entry>
+       <entry><literal><function>pg_postmaster_start_time</function>()</literal></entry>
+       <entry><type>timestamp with time zone</type></entry>
+       <entry>server start time</entry>
+      </row>
+
+      <row>
+       <entry><literal><function>session_user</function></literal></entry>
+       <entry><type>name</type></entry>
+       <entry>session user name</entry>
+      </row>
+
+      <row>
+       <entry><literal><function>user</function></literal></entry>
+       <entry><type>name</type></entry>
+       <entry>equivalent to <function>current_user</function></entry>
+      </row>
+
+      <row>
+       <entry><literal><function>version</function>()</literal></entry>
        <entry><type>text</type></entry>
-       <entry>Convert transaction log location string to file name</entry>
+       <entry><productname>PostgreSQL</> version information</entry>
       </row>
      </tbody>
     </tgroup>
    </table>
 
-   <para>
-    <function>pg_start_backup</> accepts a single parameter which is an
-    arbitrary user-defined label for the backup.  (Typically this would be
-    the name under which the backup dump file will be stored.)  The function
-    writes a backup label file into the database cluster's data directory,
-    and then returns the backup's starting transaction log location as text.  The user
-    need not pay any attention to this result value, but it is provided in
-    case it is of use. 
-<programlisting>
-postgres=# select pg_start_backup('label_goes_here');
- pg_start_backup
------------------
- 0/D4445B8
-(1 row)
-</programlisting>
-   </para>
+   <indexterm zone="functions-info">
+    <primary>user</primary>
+    <secondary>current</secondary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>schema</primary>
+    <secondary>current</secondary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>search path</primary>
+    <secondary>current</secondary>
+   </indexterm>
 
    <para>
-    <function>pg_stop_backup</> removes the label file created by
-    <function>pg_start_backup</>, and instead creates a backup history file in
-    the transaction log archive area.  The history file includes the label given to
-    <function>pg_start_backup</>, the starting and ending transaction log locations for
-    the backup, and the starting and ending times of the backup.  The return
-    value is the backup's ending transaction log location (which again might be of little
-    interest).  After noting the ending location, the current transaction log insertion
-    point is automatically advanced to the next transaction log file, so that the
-    ending transaction log file can be archived immediately to complete the backup.
+    The <function>session_user</function> is normally the user who initiated
+    the current database connection; but superusers can change this setting
+    with <xref linkend="sql-set-session-authorization" endterm="sql-set-session-authorization-title">.
+    The <function>current_user</function> is the user identifier
+    that is applicable for permission checking. Normally, it is equal
+    to the session user, but it can be changed with
+    <xref linkend="sql-set-role" endterm="sql-set-role-title">.
+    It also changes during the execution of
+    functions with the attribute <literal>SECURITY DEFINER</literal>.
+    In Unix parlance, the session user is the <quote>real user</quote> and
+    the current user is the <quote>effective user</quote>.
    </para>
 
+   <note>
+    <para>
+     <function>current_user</function>, <function>session_user</function>, and
+     <function>user</function> have special syntactic status in <acronym>SQL</acronym>:
+     they must be called without trailing parentheses.
+    </para>
+   </note>
+
    <para>
-    <function>pg_switch_xlog</> moves to the next transaction log file, allowing the 
-    current file to be archived (assuming you are using continuous archiving).
-    The result is the ending transaction log location within the just-completed transaction log file.
-    If there has been no transaction log activity since the last transaction log switch,
-    <function>pg_switch_xlog</> does nothing and returns the end location
-    of the previous transaction log file.
+    <function>current_schema</function> returns the name of the schema that is
+    at the front of the search path (or a null value if the search path is
+    empty).  This is the schema that will be used for any tables or
+    other named objects that are created without specifying a target schema.
+    <function>current_schemas(boolean)</function> returns an array of the names of all
+    schemas presently in the search path.  The Boolean option determines whether or not
+    implicitly included system schemas such as <literal>pg_catalog</> are included in the search 
+    path returned.
    </para>
 
+   <note>
+    <para>
+     The search path can be altered at run time.  The command is:
+<programlisting>
+SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ...</optional>
+</programlisting>
+    </para>
+   </note>
+
+   <indexterm zone="functions-info">
+    <primary>inet_client_addr</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>inet_client_port</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>inet_server_addr</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>inet_server_port</primary>
+   </indexterm>
+
    <para>
-    <function>pg_current_xlog_location</> displays the current transaction log write
-    location in the same format used by the above functions.  Similarly
-    <function>pg_current_xlog_insert_location</> displays the current transaction log
-    insertion point.  The insertion point is the <quote>logical</> end of transaction log
-    at any instant, while the write location is the end of what has actually
-    been written out from the server's internal buffers.  The write location
-    is the end of what can be examined from outside the server, and is usually
-    what you want if you are interested in archiving partially-complete transaction log
-    files.  The insertion point is made available primarily for server
-    debugging purposes.  These are both read-only operations and do not
-    require superuser permissions.
+     <function>inet_client_addr</function> returns the IP address of the
+     current client, and <function>inet_client_port</function> returns the
+     port number.
+     <function>inet_server_addr</function> returns the IP address on which
+     the server accepted the current connection, and
+     <function>inet_server_port</function> returns the port number.
+     All these functions return NULL if the current connection is via a
+     Unix-domain socket.
    </para>
 
+   <indexterm zone="functions-info">
+    <primary>pg_my_temp_schema</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_is_other_temp_schema</primary>
+   </indexterm>
+
    <para>
-    You can use <function>pg_xlogfile_name_offset</> to extract the
-    corresponding transaction log file name and byte offset from the results of any of the
-    above functions.  For example:
-<programlisting>
-postgres=# select * from pg_xlogfile_name_offset(pg_stop_backup());
-        file_name         | file_offset 
---------------------------+-------------
- 00000001000000000000000D |     4039624
-(1 row)
-</programlisting>
-    Similarly, <function>pg_xlogfile_name</> extracts just the transaction log file name.
-    When the given transction log location is exactly at an transaction log file boundary, both
-    these functions return the name of the preceding transaction log file.
-    This is usually the desired behavior for managing transaction log archiving
-    behavior, since the preceding file is the last one that currently
-    needs to be archived.
+    <function>pg_my_temp_schema</function> returns the OID of the current
+    session's temporary schema, or 0 if it has none (because it has not
+    created any temporary tables).
+    <function>pg_is_other_temp_schema</function> returns true if the
+    given OID is the OID of any other session's temporary schema.
+    (This can be useful, for example, to exclude other sessions' temporary
+    tables from a catalog display.)
    </para>
 
+   <indexterm zone="functions-info">
+    <primary>pg_postmaster_start_time</primary>
+   </indexterm>
+
    <para>
-    For details about proper usage of these functions, see
-    <xref linkend="continuous-archiving">.
+     <function>pg_postmaster_start_time</function> returns the
+     <type>timestamp with time zone</type> when the
+     server started.
    </para>
 
+   <indexterm zone="functions-info">
+    <primary>version</primary>
+   </indexterm>
+
    <para>
-    The functions shown in <xref linkend="functions-admin-dbsize"> calculate
-    the actual disk space usage of database objects.
+    <function>version</function> returns a string describing the
+    <productname>PostgreSQL</productname> server's version.
    </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_column_size</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_database_size</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_relation_size</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_size_pretty</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_tablespace_size</primary>
-   </indexterm>
-   <indexterm zone="functions-admin">
-    <primary>pg_total_relation_size</primary>
-   </indexterm>
+  <indexterm>
+   <primary>privilege</primary>
+   <secondary>querying</secondary>
+  </indexterm>
 
-   <table id="functions-admin-dbsize">
-    <title>Database Object Size Functions</title>
+  <para>
+   <xref linkend="functions-info-access-table"> lists functions that
+   allow the user to query object access privileges programmatically.
+   See <xref linkend="ddl-priv"> for more information about
+   privileges.
+  </para>
+
+   <table id="functions-info-access-table">
+    <title>Access Privilege Inquiry Functions</title>
     <tgroup cols="3">
      <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
-      </row>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
      </thead>
 
      <tbody>
       <row>
-       <entry><function>pg_column_size</function>(<type>any</type>)</entry>
-       <entry><type>int</type></entry>
-       <entry>Number of bytes used to store a particular value (possibly compressed)</entry>
+       <entry><literal><function>has_database_privilege</function>(<parameter>user</parameter>,
+                                  <parameter>database</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for database</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_database_size</function>(<type>oid</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>Disk space used by the database with the specified OID</entry>
+       <entry><literal><function>has_database_privilege</function>(<parameter>database</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for database</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_database_size</function>(<type>name</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>Disk space used by the database with the specified name</entry>
+       <entry><literal><function>has_function_privilege</function>(<parameter>user</parameter>,
+                                  <parameter>function</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for function</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_relation_size</function>(<type>oid</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>Disk space used by the table or index with the specified OID</entry>
+       <entry><literal><function>has_function_privilege</function>(<parameter>function</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for function</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_relation_size</function>(<type>text</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>
-        Disk space used by the table or index with the specified name.
-        The table name can be qualified with a schema name
+       <entry><literal><function>has_language_privilege</function>(<parameter>user</parameter>,
+                                  <parameter>language</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for language</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_size_pretty</function>(<type>bigint</type>)</literal>
-        </entry>
-       <entry><type>text</type></entry>
-       <entry>Converts a size in bytes into a human-readable format with size units</entry>
+       <entry><literal><function>has_language_privilege</function>(<parameter>language</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for language</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_tablespace_size</function>(<type>oid</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>Disk space used by the tablespace with the specified OID</entry>
+       <entry><literal><function>has_schema_privilege</function>(<parameter>user</parameter>,
+                                  <parameter>schema</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for schema</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_tablespace_size</function>(<type>name</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>Disk space used by the tablespace with the specified name</entry>
+       <entry><literal><function>has_schema_privilege</function>(<parameter>schema</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for schema</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_total_relation_size</function>(<type>oid</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>
-        Total disk space used by the table with the specified OID,
-        including indexes and toasted data
+       <entry><literal><function>has_table_privilege</function>(<parameter>user</parameter>,
+                                  <parameter>table</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for table</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_total_relation_size</function>(<type>text</type>)</literal>
-        </entry>
-       <entry><type>bigint</type></entry>
-       <entry>
-        Total disk space used by the table with the specified name,
-        including indexes and toasted data.  The table name can be
-        qualified with a schema name
+       <entry><literal><function>has_table_privilege</function>(<parameter>table</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for table</entry>
+      </row>
+      <row>
+       <entry><literal><function>has_tablespace_privilege</function>(<parameter>user</parameter>,
+                                  <parameter>tablespace</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for tablespace</entry>
+      </row>
+      <row>
+       <entry><literal><function>has_tablespace_privilege</function>(<parameter>tablespace</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for tablespace</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_has_role</function>(<parameter>user</parameter>,
+                                  <parameter>role</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does user have privilege for role</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_has_role</function>(<parameter>role</parameter>,
+                                  <parameter>privilege</parameter>)</literal>
        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>does current user have privilege for role</entry>
       </row>
      </tbody>
     </tgroup>
    </table>
 
+   <indexterm zone="functions-info">
+    <primary>has_database_privilege</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>has_function_privilege</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>has_language_privilege</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>has_schema_privilege</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>has_table_privilege</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>has_tablespace_privilege</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>pg_has_role</primary>
+   </indexterm>
+
    <para>
-    <function>pg_column_size</> shows the space used to store any individual
-    data value.
+    <function>has_database_privilege</function> checks whether a user
+    can access a database in a particular way.  The possibilities for its
+    arguments are analogous to <function>has_table_privilege</function>.
+    The desired access privilege type must evaluate to
+    <literal>CREATE</literal>,
+    <literal>CONNECT</literal>,
+    <literal>TEMPORARY</literal>, or
+    <literal>TEMP</literal> (which is equivalent to
+    <literal>TEMPORARY</literal>).
    </para>
 
    <para>
-    <function>pg_database_size</function> and <function>pg_tablespace_size</>
-    accept the OID or name of a database or tablespace, and return the total
-    disk space used therein.
+    <function>has_function_privilege</function> checks whether a user
+    can access a function in a particular way.  The possibilities for its
+    arguments are analogous to <function>has_table_privilege</function>.
+    When specifying a function by a text string rather than by OID,
+    the allowed input is the same as for the <type>regprocedure</> data type
+    (see <xref linkend="datatype-oid">).
+    The desired access privilege type must evaluate to
+    <literal>EXECUTE</literal>.
+    An example is:
+<programlisting>
+SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
+</programlisting>
+   </para>
+
+   <para>
+    <function>has_language_privilege</function> checks whether a user
+    can access a procedural language in a particular way.  The possibilities
+    for its arguments are analogous to <function>has_table_privilege</function>.
+    The desired access privilege type must evaluate to
+    <literal>USAGE</literal>.
+   </para>
+
+   <para>
+    <function>has_schema_privilege</function> checks whether a user
+    can access a schema in a particular way.  The possibilities for its
+    arguments are analogous to <function>has_table_privilege</function>.
+    The desired access privilege type must evaluate to
+    <literal>CREATE</literal> or
+    <literal>USAGE</literal>.
+   </para>
+
+   <para>
+    <function>has_table_privilege</function> checks whether a user
+    can access a table in a particular way.  The user can be
+    specified by name or by OID
+    (<literal>pg_authid.oid</literal>), or if the argument is
+    omitted
+    <function>current_user</function> is assumed.  The table can be specified
+    by name or by OID.  (Thus, there are actually six variants of
+    <function>has_table_privilege</function>, which can be distinguished by
+    the number and types of their arguments.)  When specifying by name,
+    the name can be schema-qualified if necessary.
+    The desired access privilege type
+    is specified by a text string, which must evaluate to one of the
+    values <literal>SELECT</literal>, <literal>INSERT</literal>,
+    <literal>UPDATE</literal>, <literal>DELETE</literal>,
+    <literal>REFERENCES</literal>, or <literal>TRIGGER</literal>.
+    (Case of the string is not significant, however.)
+    An example is:
+<programlisting>
+SELECT has_table_privilege('myschema.mytable', 'select');
+</programlisting>
    </para>
 
    <para>
-    <function>pg_relation_size</> accepts the OID or name of a table, index or
-    toast table, and returns the size in bytes.
+    <function>has_tablespace_privilege</function> checks whether a user
+    can access a tablespace in a particular way.  The possibilities for its
+    arguments are analogous to <function>has_table_privilege</function>.
+    The desired access privilege type must evaluate to
+    <literal>CREATE</literal>.
    </para>
 
    <para>
-    <function>pg_size_pretty</> can be used to format the result of one of
-    the other functions in a human-readable way, using kB, MB, GB or TB as
-    appropriate.
+    <function>pg_has_role</function> checks whether a user
+    can access a role in a particular way.  The possibilities for its
+    arguments are analogous to <function>has_table_privilege</function>.
+    The desired access privilege type must evaluate to
+    <literal>MEMBER</literal> or
+    <literal>USAGE</literal>.
+    <literal>MEMBER</literal> denotes direct or indirect membership in
+    the role (that is, the right to do <command>SET ROLE</>), while
+    <literal>USAGE</literal> denotes whether the privileges of the role
+    are immediately available without doing <command>SET ROLE</>.
    </para>
 
-   <para>
-    <function>pg_total_relation_size</> accepts the OID or name of a
-    table or toast table, and returns the size in bytes of the data
-    and all associated indexes and toast tables.
-   </para>
+  <para>
+   To test whether a user holds a grant option on the privilege,
+   append <literal>WITH GRANT OPTION</literal> to the privilege key
+   word; for example <literal>'UPDATE WITH GRANT OPTION'</literal>.
+  </para>
 
-   <para>
-    The functions shown in <xref
-    linkend="functions-admin-genfile"> provide native file access to
-    files on the machine hosting the server. Only files within the
-    database cluster directory and the <varname>log_directory</> can be
-    accessed.  Use a relative path for files within the cluster directory,
-    and a path matching the <varname>log_directory</> configuration setting
-    for log files.  Use of these functions is restricted to superusers.
-   </para>
+  <para>
+   <xref linkend="functions-info-schema-table"> shows functions that
+   determine whether a certain object is <firstterm>visible</> in the
+   current schema search path.  A table is said to be visible if its
+   containing schema is in the search path and no table of the same
+   name appears earlier in the search path.  This is equivalent to the
+   statement that the table can be referenced by name without explicit
+   schema qualification.  For example, to list the names of all
+   visible tables:
+<programlisting>
+SELECT relname FROM pg_class WHERE pg_table_is_visible(oid);
+</programlisting>
+  </para>
 
-   <table id="functions-admin-genfile">
-    <title>Generic File Access Functions</title>
+   <table id="functions-info-schema-table">
+    <title>Schema Visibility Inquiry Functions</title>
     <tgroup cols="3">
      <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
-      </row>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
      </thead>
 
      <tbody>
       <row>
-       <entry>
-        <literal><function>pg_ls_dir</function>(<parameter>dirname</> <type>text</>)</literal>
+       <entry><literal><function>pg_conversion_is_visible</function>(<parameter>conversion_oid</parameter>)</literal>
        </entry>
-       <entry><type>setof text</type></entry>
-       <entry>List the contents of a directory</entry>
+       <entry><type>boolean</type></entry>
+       <entry>is conversion visible in search path</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_read_file</function>(<parameter>filename</> <type>text</>, <parameter>offset</> <type>bigint</>, <parameter>length</> <type>bigint</>)</literal>
+       <entry><literal><function>pg_function_is_visible</function>(<parameter>function_oid</parameter>)</literal>
        </entry>
-       <entry><type>text</type></entry>
-       <entry>Return the contents of a text file</entry>
+       <entry><type>boolean</type></entry>
+       <entry>is function visible in search path</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_stat_file</function>(<parameter>filename</> <type>text</>)</literal>
+       <entry><literal><function>pg_operator_is_visible</function>(<parameter>operator_oid</parameter>)</literal>
        </entry>
-       <entry><type>record</type></entry>
-       <entry>Return information about a file</entry>
+       <entry><type>boolean</type></entry>
+       <entry>is operator visible in search path</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_opclass_is_visible</function>(<parameter>opclass_oid</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>is operator class visible in search path</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_table_is_visible</function>(<parameter>table_oid</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>is table visible in search path</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_type_is_visible</function>(<parameter>type_oid</parameter>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>is type (or domain) visible in search path</entry>
       </row>
      </tbody>
     </tgroup>
    </table>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_ls_dir</primary>
+   <indexterm zone="functions-info">
+    <primary>pg_conversion_is_visible</primary>
    </indexterm>
-   <para>
-    <function>pg_ls_dir</> returns all the names in the specified
-    directory, except the special entries <quote><literal>.</></> and
-    <quote><literal>..</></>.
-   </para>
-
-   <indexterm zone="functions-admin">
-    <primary>pg_read_file</primary>
+   <indexterm zone="functions-info">
+    <primary>pg_function_is_visible</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>pg_operator_is_visible</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>pg_opclass_is_visible</primary>
+   </indexterm>
+   <indexterm zone="functions-info">
+    <primary>pg_table_is_visible</primary>
    </indexterm>
+   <indexterm zone="functions-info">
+    <primary>pg_type_is_visible</primary>
+   </indexterm>
+
    <para>
-    <function>pg_read_file</> returns part of a text file, starting
-    at the given <parameter>offset</>, returning at most <parameter>length</>
-    bytes (less if the end of file is reached first).  If <parameter>offset</>
-    is negative, it is relative to the end of the file.
+    <function>pg_conversion_is_visible</function>,
+    <function>pg_function_is_visible</function>,
+    <function>pg_operator_is_visible</function>,
+    <function>pg_opclass_is_visible</function>,
+    <function>pg_table_is_visible</function>, and
+    <function>pg_type_is_visible</function> perform the visibility check for
+    conversions, functions, operators, operator classes, tables, and
+    types. Note that <function>pg_table_is_visible</function> can also be used
+    with views, indexes and sequences; <function>pg_type_is_visible</function>
+    can also be used with domains. For functions and operators, an object in
+    the search path is visible if there is no object of the same name
+    <emphasis>and argument data type(s)</> earlier in the path.  For operator
+    classes, both name and associated index access method are considered.
    </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_stat_file</primary>
-   </indexterm>
    <para>
-    <function>pg_stat_file</> returns a record containing the file
-    size, last accessed time stamp, last modified time stamp,
-    last file status change time stamp (Unix platforms only),
-    file creation time stamp (Windows only), and a <type>boolean</type>
-    indicating if it is a directory.  Typical usages include:
+    All these functions require object OIDs to identify the object to be
+    checked.  If you want to test an object by name, it is convenient to use
+    the OID alias types (<type>regclass</>, <type>regtype</>,
+    <type>regprocedure</>, or <type>regoperator</>), for example:
 <programlisting>
-SELECT * FROM pg_stat_file('filename');
-SELECT (pg_stat_file('filename')).modification;
+SELECT pg_type_is_visible('myschema.widget'::regtype);
 </programlisting>
+    Note that it would not make much sense to test an unqualified name in
+    this way &mdash; if the name can be recognized at all, it must be visible.
    </para>
 
-   <para>
-    The functions shown in <xref linkend="functions-advisory-locks"> manage
-    advisory locks.  For details about proper usage of these functions, see
-    <xref linkend="advisory-locks">.
-   </para>
+   <indexterm zone="functions-info">
+    <primary>format_type</primary>
+   </indexterm>
 
-   <table id="functions-advisory-locks">
-    <title>Advisory Lock Functions</title>
+   <indexterm zone="functions-info">
+    <primary>pg_get_viewdef</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_ruledef</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_indexdef</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_triggerdef</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_constraintdef</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_expr</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_userbyid</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_get_serial_sequence</primary>
+   </indexterm>
+
+   <indexterm zone="functions-info">
+    <primary>pg_tablespace_databases</primary>
+   </indexterm>
+
+  <para>
+   <xref linkend="functions-info-catalog-table"> lists functions that
+   extract information from the system catalogs.
+  </para>
+
+   <table id="functions-info-catalog-table">
+    <title>System Catalog Information Functions</title>
     <tgroup cols="3">
      <thead>
-      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
-      </row>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
      </thead>
 
      <tbody>
       <row>
-       <entry>
-        <literal><function>pg_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal>
-       </entry>
-       <entry><type>void</type></entry>
-       <entry>Obtain exclusive advisory lock</entry>
+       <entry><literal><function>format_type</function>(<parameter>type_oid</parameter>, <parameter>typemod</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get SQL name of a data type</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get definition of a constraint</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get definition of a constraint</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>decompile internal form of an expression, assuming that any Vars
+       in it refer to the relation indicated by the second parameter</entry>
+      </row>
+      <row>
+       <entry><literal><function>pg_get_expr</function>(<parameter>expr_text</parameter>, <parameter>relation_oid</>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>decompile internal form of an expression, assuming that any Vars
+       in it refer to the relation indicated by the second parameter</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
-       </entry>
-       <entry><type>void</type></entry>
-       <entry>Obtain exclusive advisory lock</entry>
+       <entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get <command>CREATE INDEX</> command for index</entry>
       </row>
-
       <row>
-       <entry>
-        <literal><function>pg_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
-       </entry>
-       <entry><type>void</type></entry>
-       <entry>Obtain shared advisory lock</entry>
+       <entry><literal><function>pg_get_indexdef</function>(<parameter>index_oid</parameter>, <parameter>column_no</>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get <command>CREATE INDEX</> command for index,
+       or definition of just one index column when
+       <parameter>column_no</> is not zero</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
-       </entry>
-       <entry><type>void</type></entry>
-       <entry>Obtain shared advisory lock</entry>
+       <entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get <command>CREATE RULE</> command for rule</entry>
       </row>
-
       <row>
-       <entry>
-        <literal><function>pg_try_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Obtain exclusive advisory lock if available</entry>
+       <entry><literal><function>pg_get_ruledef</function>(<parameter>rule_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get <command>CREATE RULE</> command for rule</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_try_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Obtain exclusive advisory lock if available</entry>
+       <entry><literal><function>pg_get_serial_sequence</function>(<parameter>table_name</parameter>, <parameter>column_name</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get name of the sequence that a <type>serial</type> or <type>bigserial</type> column
+       uses</entry>
       </row>
-
       <row>
-       <entry>
-        <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Obtain shared advisory lock if available</entry>
+       <entry><function>pg_get_triggerdef</function>(<parameter>trigger_oid</parameter>)</entry>
+       <entry><type>text</type></entry>
+       <entry>get <command>CREATE [ CONSTRAINT ] TRIGGER</> command for trigger</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Obtain shared advisory lock if available</entry>
+       <entry><literal><function>pg_get_userbyid</function>(<parameter>roleid</parameter>)</literal></entry>
+       <entry><type>name</type></entry>
+       <entry>get role name with given ID</entry>
       </row>
-
       <row>
-       <entry>
-        <literal><function>pg_advisory_unlock</function>(<parameter>key</> <type>bigint</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Release an exclusive advisory lock</entry>
+       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_advisory_unlock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Release an exclusive advisory lock</entry>
+       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_name</parameter>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get underlying <command>SELECT</command> command for view (<emphasis>deprecated</emphasis>)</entry>
       </row>
-
       <row>
-       <entry>
-        <literal><function>pg_advisory_unlock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Release a shared advisory lock</entry>
+       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get underlying <command>SELECT</command> command for view</entry>
       </row>
       <row>
-       <entry>
-        <literal><function>pg_advisory_unlock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
-       </entry>
-       <entry><type>boolean</type></entry>
-       <entry>Release a shared advisory lock</entry>
+       <entry><literal><function>pg_get_viewdef</function>(<parameter>view_oid</parameter>, <parameter>pretty_bool</>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get underlying <command>SELECT</command> command for view</entry>
       </row>
-
       <row>
-       <entry>
-        <literal><function>pg_advisory_unlock_all</function>()</literal>
-       </entry>
-       <entry><type>void</type></entry>
-       <entry>Release all advisory locks held by the current session</entry>
+       <entry><literal><function>pg_tablespace_databases</function>(<parameter>tablespace_oid</parameter>)</literal></entry>
+       <entry><type>setof oid</type></entry>
+       <entry>get the set of database OIDs that have objects in the tablespace</entry>
       </row>
-
      </tbody>
     </tgroup>
    </table>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_advisory_lock</primary>
-   </indexterm>
-   <para>
-    <function>pg_advisory_lock</> locks an application-defined resource,
-    which can be identified either by a single 64-bit key value or two
-    32-bit key values (note that these two key spaces do not overlap).  If
-    another session already holds a lock on the same resource, the
-    function will wait until the resource becomes available.  The lock
-    is exclusive.  Multiple lock requests stack, so that if the same resource
-    is locked three times it must be also unlocked three times to be
-    released for other sessions' use.
-   </para>
+  <para>
+   <function>format_type</function> returns the SQL name of a data type that
+   is identified by its type OID and possibly a type modifier.  Pass NULL
+   for the type modifier if no specific modifier is known.
+  </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_advisory_lock_shared</primary>
+  <para>
+   <function>pg_get_constraintdef</function>,
+   <function>pg_get_indexdef</function>, <function>pg_get_ruledef</function>,
+   and <function>pg_get_triggerdef</function>, respectively reconstruct the
+   creating command for a constraint, index, rule, or trigger. (Note that this
+   is a decompiled reconstruction, not the original text of the command.)
+   <function>pg_get_expr</function> decompiles the internal form of an
+   individual expression, such as the default value for a column.  It can be
+   useful when examining the contents of system catalogs.
+   <function>pg_get_viewdef</function> reconstructs the <command>SELECT</>
+   query that defines a view. Most of these functions come in two variants,
+   one of which can optionally <quote>pretty-print</> the result.  The
+   pretty-printed format is more readable, but the default format is more
+   likely to be interpreted the same way by future versions of
+   <productname>PostgreSQL</>; avoid using pretty-printed output for dump
+   purposes.  Passing <literal>false</> for the pretty-print parameter yields
+   the same result as the variant that does not have the parameter at all.
+  </para>
+
+  <para>
+   <function>pg_get_serial_sequence</function> returns the name of the
+   sequence associated with a column, or NULL if no sequence is associated
+   with the column.  The first input parameter is a table name with
+   optional schema, and the second parameter is a column name.  Because
+   the first parameter is potentially a schema and table, it is not treated
+   as a double-quoted identifier, meaning it is lowercased by default,
+   while the second parameter, being just a column name, is treated as
+   double-quoted and has its case preserved.  The function returns a value
+   suitably formatted for passing to the sequence functions (see <xref
+   linkend="functions-sequence">).  This association can be modified or
+   removed with <command>ALTER SEQUENCE OWNED BY</>.  (The function
+   probably should have been called
+   <function>pg_get_owned_sequence</function>; its name reflects the fact
+   that it's typically used with <type>serial</> or <type>bigserial</>
+   columns.)
+  </para>
+
+  <para>
+   <function>pg_get_userbyid</function> extracts a role's name given
+   its OID.
+  </para>
+
+  <para>
+   <function>pg_tablespace_databases</function> allows a tablespace to be
+   examined. It returns the set of OIDs of databases that have objects stored
+   in the tablespace. If this function returns any rows, the tablespace is not
+   empty and cannot be dropped. To display the specific objects populating the
+   tablespace, you will need to connect to the databases identified by
+   <function>pg_tablespace_databases</function> and query their
+   <structname>pg_class</> catalogs.
+  </para>
+
+   <indexterm zone="functions-info">
+    <primary>col_description</primary>
    </indexterm>
-   <para>
-    <function>pg_advisory_lock_shared</> works the same as
-    <function>pg_advisory_lock</>,
-    except the lock can be shared with other sessions requesting shared locks.
-    Only would-be exclusive lockers are locked out.
-   </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_try_advisory_lock</primary>
+   <indexterm zone="functions-info">
+    <primary>obj_description</primary>
    </indexterm>
-   <para>
-    <function>pg_try_advisory_lock</> is similar to
-    <function>pg_advisory_lock</>, except the function will not wait for the
-    lock to become available.  It will either obtain the lock immediately and
-    return <literal>true</>, or return <literal>false</> if the lock cannot be
-    acquired now.
-   </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_try_advisory_lock_shared</primary>
+   <indexterm zone="functions-info">
+    <primary>shobj_description</primary>
    </indexterm>
-   <para>
-    <function>pg_try_advisory_lock_shared</> works the same as
-    <function>pg_try_advisory_lock</>, except it attempts to acquire
-    shared rather than exclusive lock.
-   </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_advisory_unlock</primary>
+   <indexterm zone="functions-info">
+    <primary>comment</primary>
+    <secondary sortas="database objects">about database objects</secondary>
    </indexterm>
+
    <para>
-    <function>pg_advisory_unlock</> will release a previously-acquired
-    exclusive advisory lock.  It
-    will return <literal>true</> if the lock is successfully released.
-    If the lock was in fact not held, it will return <literal>false</>,
-    and in addition, an SQL warning will be raised by the server.
+    The functions shown in <xref linkend="functions-info-comment-table">
+    extract comments previously stored with the <xref linkend="sql-comment"
+    endterm="sql-comment-title"> command.  A null value is returned if no
+    comment could be found matching the specified parameters.
    </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_advisory_unlock_shared</primary>
-   </indexterm>
+   <table id="functions-info-comment-table">
+    <title>Comment Information Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
+     </thead>
+
+     <tbody>
+      <row>
+       <entry><literal><function>col_description</function>(<parameter>table_oid</parameter>, <parameter>column_number</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get comment for a table column</entry>
+      </row>
+      <row>
+       <entry><literal><function>obj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get comment for a database object</entry>
+      </row>
+      <row>
+       <entry><literal><function>obj_description</function>(<parameter>object_oid</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get comment for a database object (<emphasis>deprecated</emphasis>)</entry>
+      </row>
+      <row>
+       <entry><literal><function>shobj_description</function>(<parameter>object_oid</parameter>, <parameter>catalog_name</parameter>)</literal></entry>
+       <entry><type>text</type></entry>
+       <entry>get comment for a shared database object</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+
    <para>
-    <function>pg_advisory_unlock_shared</> works the same as
-    <function>pg_advisory_unlock</>, 
-    except to release a shared advisory lock.
+    <function>col_description</function> returns the comment for a table column,
+    which is specified by the OID of its table and its column number.
+    <function>obj_description</function> cannot be used for table columns since
+    columns do not have OIDs of their own.
    </para>
 
-   <indexterm zone="functions-admin">
-    <primary>pg_advisory_unlock_all</primary>
-   </indexterm>
    <para>
-    <function>pg_advisory_unlock_all</> will release all advisory locks
-    held by the current session.  (This function is implicitly invoked
-    at session end, even if the client disconnects ungracefully.)
+    The two-parameter form of <function>obj_description</function> returns the
+    comment for a database object specified by its OID and the name of the
+    containing system catalog.  For example,
+    <literal>obj_description(123456,'pg_class')</literal>
+    would retrieve the comment for a table with OID 123456.
+    The one-parameter form of <function>obj_description</function> requires only
+    the object OID.  It is now deprecated since there is no guarantee that
+    OIDs are unique across different system catalogs; therefore, the wrong
+    comment could be returned.
    </para>
 
+   <para>
+    <function>shobj_description</function> is used just like
+    <function>obj_description</function> only that it is used for retrieving
+    comments on shared objects.  Some system catalogs are global to all
+    databases within each cluster and their descriptions are stored globally
+    as well.
+   </para>
   </sect1>
 
- <sect1 id="functions-xml">
-  <title>XML Functions</title>
+ <sect1 id="functions-admin">
+  <title>System Administration Functions</title>
 
   <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>
-   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.
+   <xref linkend="functions-admin-set-table"> shows the functions
+   available to query and alter run-time configuration parameters.
   </para>
 
-  <sect2>
-   <title>Producing XML Content</title>
-
-   <para>
-    A set of functions and function-like expressions are available for
-    producing XML content from SQL data.  As such, they are
-    particularly suitable for formatting query results into XML
-    documents for processing in client applications.
-   </para>
-
-   <sect3>
-    <title><literal>xmlcomment</literal></title>
-
-    <indexterm>
-     <primary>xmlcomment</primary>
-    </indexterm>
-
-<synopsis>
-<function>xmlcomment</function>(<replaceable>text</replaceable>)
-</synopsis>
-
-    <para>
-     The function <function>xmlcomment</function> creates an XML value
-     containing an XML comment with the specified text as content.
-     The text cannot contain <literal>--</literal> or end with a
-     <literal>-</literal> so that the resulting construct is a valid
-     XML comment.  If the argument is null, the result is null.
-    </para>
-
-    <para>
-     Example:
-<screen><![CDATA[
-SELECT xmlcomment('hello');
-
-  xmlcomment
---------------
- <!--hello-->
-]]></screen>
-    </para>
-   </sect3>
-
-   <sect3>
-    <title><literal>xmlconcat</literal></title>
-
-    <indexterm>
-     <primary>xmlconcat</primary>
-    </indexterm>
-
- <synopsis>
- <function>xmlconcat</function>(<replaceable>xml</replaceable><optional>, ...</optional>)
- </synopsis>
-    <para>
-     The function <function>xmlconcat</function> concatenates a list
-     of individual XML values to create a single value containing an
-     XML content fragment.  Null values are omitted; the result is
-     only null if there are no nonnull arguments.
-    </para>
-
-    <para>
-     Example:
-<screen><![CDATA[
-SELECT xmlconcat('<abc/>', '<bar>foo</bar>');
-
-      xmlconcat
-----------------------
- <abc/><bar>foo</bar>
-]]></screen>
-    </para>
-
-    <para>
-     XML declarations, if present are combined as follows.  If all
-     argument values have the same XML version declaration, that
-     version is used in the result, else no version is used.  If all
-     argument values have the standalone declaration value
-     <quote>yes</quote>, then that value is used in the result.  If
-     all argument values have a standalone declaration value and at
-     least one is <quote>no</quote>, then that is used in the result.
-     Else the result will have no standalone declaration.  If the
-     result is determined to require a standalone declaration but no
-     version declaration, a version declaration with version 1.0 will
-     be used because XML requires an XML declaration to contain a
-     version declaration.  Encoding declarations are ignored and
-     removed in all cases.
-    </para>
+   <table id="functions-admin-set-table">
+    <title>Configuration Settings Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
+     </thead>
 
-    <para>
-     Example:
-<screen><![CDATA[
-SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone="no"?><bar/>');
+     <tbody>
+      <row>
+       <entry>
+        <literal><function>current_setting</function>(<parameter>setting_name</parameter>)</literal>
+       </entry>
+       <entry><type>text</type></entry>
+       <entry>current value of setting</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>set_config(<parameter>setting_name</parameter>,
+                             <parameter>new_value</parameter>,
+                             <parameter>is_local</parameter>)</function></literal>
+       </entry>
+       <entry><type>text</type></entry>
+       <entry>set parameter and return new value</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
 
-             xmlconcat
------------------------------------
- <?xml version="1.1"?><foo/><bar/>
-]]></screen>
-    </para>
-   </sect3>
-   <sect3>
-    <title><literal>xmlelement</literal></title>
-   <indexterm>
-    <primary>xmlelement</primary>
+   <indexterm zone="functions-admin">
+    <primary>SET</primary>
    </indexterm>
-<synopsis>
- <function>xmlelement</function>(name <replaceable>name</replaceable> <optional>, xmlattributes(<replaceable>value</replaceable> <optional>AS <replaceable>attname</replaceable></optional> <optional>, ... </optional>)</optional> <optional><replaceable>, content, ...</replaceable></optional>)
- </synopsis>
-    <para>
-     The <function>xmlelement</function> expression produces an XML
-     element with the given name, attributes, and content.
-    </para>
-
-    <para>
-     Examples:
-<screen><![CDATA[
-SELECT xmlelement(name foo);
-
- xmlelement
-------------
- <foo/>
 
-SELECT xmlelement(name foo, xmlattributes('xyz' as bar));
-
-    xmlelement
-------------------
- <foo bar="xyz"/>
-
-SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'cont', 'ent');
+   <indexterm zone="functions-admin">
+    <primary>SHOW</primary>
+   </indexterm>
 
-             xmlelement
--------------------------------------
<foo bar="2007-01-26">content</foo>
-]]></screen>
-    </para>
+   <indexterm zone="functions-admin">
+    <primary>configuration</primary>
   <secondary sortas="server">of the server</secondary>
+    <tertiary>functions</tertiary>
+   </indexterm>
 
-    <para>
-     Element and attribute names that are not valid XML names are
-     escaped by replacing the offending characters by the sequence
-     <literal>_x<replaceable>HHHH</replaceable>_</literal>, where
-     <replaceable>HHHH</replaceable> is the character's Unicode
-     codepoint in hexadecimal notation.  For example:
-<screen><![CDATA[
-SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));
+   <para>
+    The function <function>current_setting</function> yields the
+    current value of the setting <parameter>setting_name</parameter>.
+    It corresponds to the <acronym>SQL</acronym> command
+    <command>SHOW</command>.  An example:
+<programlisting>
+SELECT current_setting('datestyle');
 
-            xmlelement
-----------------------------------
- <foo_x0024_bar a_x0026_b="xyz"/>
-]]></screen>
-    </para>
+ current_setting
+-----------------
+ ISO, MDY
+(1 row)
+</programlisting>
+   </para>
 
-    <para>
-     An explicit attribute name need not be specified if the attribute
-     value is a column reference, in which case the column's name will
-     be used as attribute name by default.  In any other case, the
-     attribute must be given an explicit name.  So this example is
-     valid:
-<screen>
-CREATE TABLE test (a xml, b xml);
-SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;
-</screen>
-     But these are not:
-<screen>
-SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test;
-SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test;
-</screen>
-    </para>
+   <para>
+    <function>set_config</function> sets the parameter
+    <parameter>setting_name</parameter> to
+    <parameter>new_value</parameter>.  If
+    <parameter>is_local</parameter> is <literal>true</literal>, the
+    new value will only apply to the current transaction. If you want
+    the new value to apply for the current session, use
+    <literal>false</literal> instead. The function corresponds to the
+    SQL command <command>SET</command>. An example:
+<programlisting>
+SELECT set_config('log_statement_stats', 'off', false);
 
-    <para>
-     Element content, if specified, will be formatted according to
-     data type.  If the content is itself of type <type>xml</type>,
-     complex XML documents can be constructed.  For example:
-<screen><![CDATA[
-SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
-                            xmlelement(name abc),
-                            xmlcomment('test'),
-                            xmlelement(name xyz));
+ set_config
+------------
+ off
+(1 row)
+</programlisting>
+   </para>
 
-                  xmlelement
-----------------------------------------------
- <foo bar="xyz"><abc/><!--test--><xyz/></foo>
-]]></screen>
+   <indexterm zone="functions-admin">
+    <primary>pg_cancel_backend</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_reload_conf</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_rotate_logfile</primary>
+   </indexterm>
 
-     Content of other types will be formatted into valid XML character
-     data.  This means in particular that the characters &lt;, &gt;,
-     and &amp; will be converted to entities.  Binary data (data type
-     <type>bytea</type>) will be represented in base64 or hex
-     encoding, depending on the setting of the configuration parameter
-     <xref linkend="guc-xmlbinary">.  The particular behavior for
-     individual data types is expected 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.
-    </para>
-   </sect3>
-   <sect3>
-    <title><literal>xmlforest</literal></title>
-   <indexterm>
-    <primary>xmlforest</primary>
+   <indexterm zone="functions-admin">
+    <primary>signal</primary>
+    <secondary sortas="backend">backend processes</secondary>
    </indexterm>
- <synopsis>
- <function>xmlforest</function>(<replaceable>content</replaceable> <optional>AS <replaceable>name</replaceable></optional> <optional>, ...</optional>)
- </synopsis>
-    <para>
-     The <function>xmlforest</function> expression produces an XML
-     forest (sequence) of elements using the given names and content.
-    </para>
 
-    <para>
-     Examples:
-<screen><![CDATA[
-SELECT xmlforest('abc' AS foo, 123 AS bar);
+   <para>
+    The functions shown in <xref
+    linkend="functions-admin-signal-table"> send control signals to
+    other server processes.  Use of these functions is restricted
+    to superusers.
+   </para>
 
-          xmlforest
-------------------------------
- <foo>abc</foo><bar>123</bar>
+   <table id="functions-admin-signal-table">
+    <title>Server Signalling Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      </row>
+     </thead>
 
+     <tbody>
+      <row>
+       <entry>
+        <literal><function>pg_cancel_backend</function>(<parameter>pid</parameter> <type>int</>)</literal>
+        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Cancel a backend's current query</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_reload_conf</function>()</literal>
+        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Cause server processes to reload their configuration files</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_rotate_logfile</function>()</literal>
+        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Rotate server's log file</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
 
-SELECT xmlforest(table_name, column_name) FROM information_schema.columns WHERE table_schema = 'pg_catalog';
+   <para>
+    Each of these functions returns <literal>true</literal> if
+    successful and <literal>false</literal> otherwise.
+   </para>
 
-                                         xmlforest
--------------------------------------------------------------------------------------------
- <table_name>pg_authid</table_name><column_name>rolname</column_name>
- <table_name>pg_authid</table_name><column_name>rolsuper</column_name>
- ...
-]]></screen>
+   <para>
+    <function>pg_cancel_backend</> sends a query cancel
+    (<systemitem>SIGINT</>) signal to a backend process identified by
+    process ID.  The process ID of an active backend can be found from
+    the <structfield>procpid</structfield> column in the
+    <structname>pg_stat_activity</structname> view, or by listing the
+    <command>postgres</command> processes on the server with
+    <application>ps</>.
+   </para>
 
-     As seen in the second example, the element name can be omitted if
-     the content value is a column reference, in which case the column
-     name is used by default.  Otherwise, a name must be specified.
-    </para>
+   <para>
+    <function>pg_reload_conf</> sends a <systemitem>SIGHUP</> signal
+    to the server, causing the configuration files
+    to be reloaded by all server processes.
+   </para>
 
-    <para>
-     Element names that are not valid XML names are escaped as shown
-     for <function>xmlelement</function> above.  Similarly, content
-     data is escaped to make valid XML content, unless it is already
-     of type <type>xml</type>.
-    </para>
+   <para>
+    <function>pg_rotate_logfile</> signals the log-file manager to switch
+    to a new output file immediately.  This works only when
+    <varname>redirect_stderr</> is used for logging, since otherwise there
+    is no log-file manager subprocess.
+   </para>
 
-    <para>
-     Note that XML forests are not valid XML documents if they consist
-     of more than one element.  So it might be useful to wrap
-     <function>xmlforest</function> expressions in
-     <function>xmlelement</function>.
-    </para>
-   </sect3>
-   <sect3>
-    <title><literal>xmlpi</literal></title>
-   <indexterm>
-    <primary>xmlpi</primary>
+   <indexterm zone="functions-admin">
+    <primary>pg_start_backup</primary>
    </indexterm>
- <synopsis>
- <function>xmlpi</function>(name <replaceable>target</replaceable> <optional>, <replaceable>content</replaceable></optional>)
- </synopsis>
-    <para>
-     The <function>xmlpi</function> expression creates an XML
-     processing instruction.  The content, if present, must not
-     contain the character sequence <literal>?&gt;</literal>.
-    </para>
+   <indexterm zone="functions-admin">
+    <primary>pg_stop_backup</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_switch_xlog</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_current_xlog_location</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_current_xlog_insert_location</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_xlogfile_name_offset</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_xlogfile_name</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>backup</primary>
+   </indexterm>
+
+   <para>
+    The functions shown in <xref
+    linkend="functions-admin-backup-table"> assist in making on-line backups.
+    Use of the first three functions is restricted to superusers.
+   </para>
+
+   <table id="functions-admin-backup-table">
+    <title>Backup Control Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      </row>
+     </thead>
+
+     <tbody>
+      <row>
+       <entry>
+        <literal><function>pg_start_backup</function>(<parameter>label</> <type>text</>)</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Set up for performing on-line backup</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_stop_backup</function>()</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Finish performing on-line backup</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_switch_xlog</function>()</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Force switch to a new transaction log file</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_current_xlog_location</function>()</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Get current transaction log write location</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_current_xlog_insert_location</function>()</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Get current transaction log insert location</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_xlogfile_name_offset</function>(<parameter>location</> <type>text</>)</literal>
+        </entry>
+       <entry><type>text</>, <type>integer</></entry>
+       <entry>Convert transaction log location string to file name and decimal byte offset within file</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_xlogfile_name</function>(<parameter>location</> <type>text</>)</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Convert transaction log location string to file name</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
 
-    <para>
-     Example:
-<screen><![CDATA[
-SELECT xmlpi(name php, 'echo "hello world";');
+   <para>
+    <function>pg_start_backup</> accepts a single parameter which is an
+    arbitrary user-defined label for the backup.  (Typically this would be
+    the name under which the backup dump file will be stored.)  The function
+    writes a backup label file into the database cluster's data directory,
+    and then returns the backup's starting transaction log location as text.  The user
+    need not pay any attention to this result value, but it is provided in
+    case it is of use. 
+<programlisting>
+postgres=# select pg_start_backup('label_goes_here');
+ pg_start_backup
+-----------------
+ 0/D4445B8
+(1 row)
+</programlisting>
+   </para>
 
-            xmlpi
------------------------------
- <?php echo "hello world";?>
-]]></screen>
-    </para>
-   </sect3>
-   <sect3>
-    <title><literal>xmlroot</literal></title>
-   <indexterm>
-    <primary>xmlroot</primary>
-   </indexterm>
- <synopsis>
- <function>xmlroot</function>(<replaceable>xml</replaceable>, version <replaceable>text</replaceable>|no value <optional>, standalone yes|no|no value</optional>)
- </synopsis>
-    <para>
-     The <function>xmlroot</function> expression alters the properties
-     of the root node of an XML value.  If a version is specified,
-     this replaces the value in the version declaration, if a
-     standalone value is specified, this replaces the value in the
-     standalone declaration.
-    </para>
+   <para>
+    <function>pg_stop_backup</> removes the label file created by
+    <function>pg_start_backup</>, and instead creates a backup history file in
+    the transaction log archive area.  The history file includes the label given to
+    <function>pg_start_backup</>, the starting and ending transaction log locations for
+    the backup, and the starting and ending times of the backup.  The return
+    value is the backup's ending transaction log location (which again might be of little
+    interest).  After noting the ending location, the current transaction log insertion
+    point is automatically advanced to the next transaction log file, so that the
+    ending transaction log file can be archived immediately to complete the backup.
+   </para>
 
-    <para>
-<screen><![CDATA[
-SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'), version '1.0', standalone yes);
+   <para>
+    <function>pg_switch_xlog</> moves to the next transaction log file, allowing the 
+    current file to be archived (assuming you are using continuous archiving).
+    The result is the ending transaction log location within the just-completed transaction log file.
+    If there has been no transaction log activity since the last transaction log switch,
+    <function>pg_switch_xlog</> does nothing and returns the end location
+    of the previous transaction log file.
+   </para>
 
-                xmlroot
-----------------------------------------
- <?xml version="1.0" standalone="yes"?>
- <content>abc</content>
-]]></screen>
-    </para>
-   </sect3>
+   <para>
+    <function>pg_current_xlog_location</> displays the current transaction log write
+    location in the same format used by the above functions.  Similarly
+    <function>pg_current_xlog_insert_location</> displays the current transaction log
+    insertion point.  The insertion point is the <quote>logical</> end of transaction log
+    at any instant, while the write location is the end of what has actually
+    been written out from the server's internal buffers.  The write location
+    is the end of what can be examined from outside the server, and is usually
+    what you want if you are interested in archiving partially-complete transaction log
+    files.  The insertion point is made available primarily for server
+    debugging purposes.  These are both read-only operations and do not
+    require superuser permissions.
+   </para>
 
-   <sect3>
-    <title>XML Predicates</title>
+   <para>
+    You can use <function>pg_xlogfile_name_offset</> to extract the
+    corresponding transaction log file name and byte offset from the results of any of the
+    above functions.  For example:
+<programlisting>
+postgres=# select * from pg_xlogfile_name_offset(pg_stop_backup());
+        file_name         | file_offset 
+--------------------------+-------------
+ 00000001000000000000000D |     4039624
+(1 row)
+</programlisting>
+    Similarly, <function>pg_xlogfile_name</> extracts just the transaction log file name.
+    When the given transction log location is exactly at an transaction log file boundary, both
+    these functions return the name of the preceding transaction log file.
+    This is usually the desired behavior for managing transaction log archiving
+    behavior, since the preceding file is the last one that currently
+    needs to be archived.
+   </para>
 
-    <indexterm>
-     <primary>IS DOCUMENT</primary>
-    </indexterm>
+   <para>
+    For details about proper usage of these functions, see
+    <xref linkend="continuous-archiving">.
+   </para>
 
-<synopsis>
-<replaceable>xml</replaceable> IS DOCUMENT
-</synopsis>
+   <para>
+    The functions shown in <xref linkend="functions-admin-dbsize"> calculate
+    the actual disk space usage of database objects.
+   </para>
 
-    <para>
-     The expression <literal>IS DOCUMENT</literal> returns true if the
-     argument XML value is a proper XML document, false if it is not
-     (that is, it is a content fragment), or null if the argument is
-     null.  See <xref linkend="datatype-xml"> about the difference
-     between documents and content fragments.
-    </para>
-   </sect3>
-  </sect2>
+   <indexterm zone="functions-admin">
+    <primary>pg_column_size</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_database_size</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_relation_size</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_size_pretty</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_tablespace_size</primary>
+   </indexterm>
+   <indexterm zone="functions-admin">
+    <primary>pg_total_relation_size</primary>
+   </indexterm>
 
-  <sect2>
-   <title>Mapping Tables to XML</title>
+   <table id="functions-admin-dbsize">
+    <title>Database Object Size Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      </row>
+     </thead>
 
-   <para>
-    The following functions map the contents of relational tables to
-    XML values.  They can be thought of as XML export functionality.
-<synopsis>
-table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text)
-query_to_xml(query text, nulls boolean, tableforest boolean, targetns text)
-cursor_to_xml(cursor refcursor, count int, nulls boolean, tableforest boolean, targetns text)
-</synopsis>
-    The return type of each function is <type>xml</type>.
+     <tbody>
+      <row>
+       <entry><function>pg_column_size</function>(<type>any</type>)</entry>
+       <entry><type>int</type></entry>
+       <entry>Number of bytes used to store a particular value (possibly compressed)</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_database_size</function>(<type>oid</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>Disk space used by the database with the specified OID</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_database_size</function>(<type>name</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>Disk space used by the database with the specified name</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_relation_size</function>(<type>oid</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>Disk space used by the table or index with the specified OID</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_relation_size</function>(<type>text</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>
+        Disk space used by the table or index with the specified name.
+        The table name can be qualified with a schema name
+       </entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_size_pretty</function>(<type>bigint</type>)</literal>
+        </entry>
+       <entry><type>text</type></entry>
+       <entry>Converts a size in bytes into a human-readable format with size units</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_tablespace_size</function>(<type>oid</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>Disk space used by the tablespace with the specified OID</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_tablespace_size</function>(<type>name</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>Disk space used by the tablespace with the specified name</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_total_relation_size</function>(<type>oid</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>
+        Total disk space used by the table with the specified OID,
+        including indexes and toasted data
+       </entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_total_relation_size</function>(<type>text</type>)</literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>
+        Total disk space used by the table with the specified name,
+        including indexes and toasted data.  The table name can be
+        qualified with a schema name
+       </entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+
+   <para>
+    <function>pg_column_size</> shows the space used to store any individual
+    data value.
    </para>
 
    <para>
-    <function>table_to_xml</function> maps the content of the named
-    table, passed as parameter <parameter>tbl</parameter>.  The
-    <type>regclass</type> accepts strings identifying tables using the
-    usual notation, including optional schema qualifications and
-    double quotes.  <function>query_to_xml</function> executes the
-    query whose text is passed as parameter
-    <parameter>query</parameter> and maps the result set.
-    <function>cursor_to_xml</function> fetches the indicated number of
-    rows from the cursor specified by the parameter
-    <parameter>cursor</parameter>.  This variant is recommendable if
-    large tables have to be mapped, because the result value is built
-    up in memory by each function.
+    <function>pg_database_size</function> and <function>pg_tablespace_size</>
+    accept the OID or name of a database or tablespace, and return the total
+    disk space used therein.
    </para>
 
    <para>
-    If <parameter>tableforest</parameter> is false, then the resulting
-    XML document looks like this:
-<screen><![CDATA[
-<tablename>
-  <row>
-    <columnname1>data</columnname1>
-    <columnname2>data</columnname2>
-  </row>
+    <function>pg_relation_size</> accepts the OID or name of a table, index or
+    toast table, and returns the size in bytes.
+   </para>
 
-  <row>
-    ...
-  </row>
+   <para>
+    <function>pg_size_pretty</> can be used to format the result of one of
+    the other functions in a human-readable way, using kB, MB, GB or TB as
+    appropriate.
+   </para>
 
-  ...
-</tablename>
-]]></screen>
+   <para>
+    <function>pg_total_relation_size</> accepts the OID or name of a
+    table or toast table, and returns the size in bytes of the data
+    and all associated indexes and toast tables.
+   </para>
 
-    If <parameter>tableforest</parameter> is true, the result is an
-    XML content fragment that looks like this:
-<screen><![CDATA[
-<tablename>
-  <columnname1>data</columnname1>
-  <columnname2>data</columnname2>
-</tablename>
+   <para>
+    The functions shown in <xref
+    linkend="functions-admin-genfile"> provide native file access to
+    files on the machine hosting the server. Only files within the
+    database cluster directory and the <varname>log_directory</> can be
+    accessed.  Use a relative path for files within the cluster directory,
+    and a path matching the <varname>log_directory</> configuration setting
+    for log files.  Use of these functions is restricted to superusers.
+   </para>
 
-<tablename>
-  ...
-</tablename>
+   <table id="functions-admin-genfile">
+    <title>Generic File Access Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      </row>
+     </thead>
 
-...
-]]></screen>
+     <tbody>
+      <row>
+       <entry>
+        <literal><function>pg_ls_dir</function>(<parameter>dirname</> <type>text</>)</literal>
+       </entry>
+       <entry><type>setof text</type></entry>
+       <entry>List the contents of a directory</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_read_file</function>(<parameter>filename</> <type>text</>, <parameter>offset</> <type>bigint</>, <parameter>length</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>text</type></entry>
+       <entry>Return the contents of a text file</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_stat_file</function>(<parameter>filename</> <type>text</>)</literal>
+       </entry>
+       <entry><type>record</type></entry>
+       <entry>Return information about a file</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
 
-    If no table name is avaible, that is, when mapping a query or a
-    cursor, the string <literal>table</literal> is used in the first
-    format, <literal>row</literal> in the second format.
+   <indexterm zone="functions-admin">
+    <primary>pg_ls_dir</primary>
+   </indexterm>
+   <para>
+    <function>pg_ls_dir</> returns all the names in the specified
+    directory, except the special entries <quote><literal>.</></> and
+    <quote><literal>..</></>.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_read_file</primary>
+   </indexterm>
    <para>
-    The choice between these formats is up to the user.  The first
-    format is a proper XML document, which will be important in many
-    applications.  The second format tends to be more useful in the
-    <function>cursor_to_xml</function> function if the result values are to be
-    reassembled into one document later on.  The functions for
-    producing XML content discussed above, in particular
-    <function>xmlelement</function>, can be used to alter the results
-    to taste.
+    <function>pg_read_file</> returns part of a text file, starting
+    at the given <parameter>offset</>, returning at most <parameter>length</>
+    bytes (less if the end of file is reached first).  If <parameter>offset</>
+    is negative, it is relative to the end of the file.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_stat_file</primary>
+   </indexterm>
    <para>
-    The data values are mapping in the same way as described for the
-    function <function>xmlelement</function> above.
+    <function>pg_stat_file</> returns a record containing the file
+    size, last accessed time stamp, last modified time stamp,
+    last file status change time stamp (Unix platforms only),
+    file creation time stamp (Windows only), and a <type>boolean</type>
+    indicating if it is a directory.  Typical usages include:
+<programlisting>
+SELECT * FROM pg_stat_file('filename');
+SELECT (pg_stat_file('filename')).modification;
+</programlisting>
    </para>
 
    <para>
-    The parameter <parameter>nulls</parameter> determines whether null
-    values should be included in the output.  If true, null values in
-    columns are represented as
-<screen><![CDATA[
-<columnname xsi:nil="true"/>
-]]></screen>
-    where <literal>xsi</literal> is the XML namespace prefix for XML
-    Schema Instance.  An appropriate namespace declaration will be
-    added to the result value.  If false, columns containing null
-    values are simply omitted from the output.
+    The functions shown in <xref linkend="functions-advisory-locks"> manage
+    advisory locks.  For details about proper usage of these functions, see
+    <xref linkend="advisory-locks">.
    </para>
 
-   <para>
-    The parameter <parameter>targetns</parameter> specifies the
-    desired XML namespace of the result.  If no particular namespace
-    is wanted, an empty string should be passed.
-   </para>
+   <table id="functions-advisory-locks">
+    <title>Advisory Lock Functions</title>
+    <tgroup cols="3">
+     <thead>
+      <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry>
+      </row>
+     </thead>
+
+     <tbody>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain exclusive advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain exclusive advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain shared advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Obtain shared advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain exclusive advisory lock if available</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain exclusive advisory lock if available</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain shared advisory lock if available</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_try_advisory_lock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Obtain shared advisory lock if available</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release an exclusive advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release an exclusive advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock_shared</function>(<parameter>key</> <type>bigint</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release a shared advisory lock</entry>
+      </row>
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock_shared</function>(<parameter>key1</> <type>int</>, <parameter>key2</> <type>int</>)</literal>
+       </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Release a shared advisory lock</entry>
+      </row>
+
+      <row>
+       <entry>
+        <literal><function>pg_advisory_unlock_all</function>()</literal>
+       </entry>
+       <entry><type>void</type></entry>
+       <entry>Release all advisory locks held by the current session</entry>
+      </row>
+
+     </tbody>
+    </tgroup>
+   </table>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_lock</primary>
+   </indexterm>
    <para>
-    The following functions return XML Schema documents describing the
-    mappings made by the data mappings produced by the corresponding
-    functions above.
-<synopsis>
-table_to_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
-query_to_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
-cursor_to_xmlschema(cursor refcursor, nulls boolean, tableforest boolean, targetns text)
-</synopsis>
-    It is essential that the same parameters are passed in order to
-    obtain matching XML data mappings and XML Schema documents.
+    <function>pg_advisory_lock</> locks an application-defined resource,
+    which can be identified either by a single 64-bit key value or two
+    32-bit key values (note that these two key spaces do not overlap).  If
+    another session already holds a lock on the same resource, the
+    function will wait until the resource becomes available.  The lock
+    is exclusive.  Multiple lock requests stack, so that if the same resource
+    is locked three times it must be also unlocked three times to be
+    released for other sessions' use.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_lock_shared</primary>
+   </indexterm>
    <para>
-    The following functions produce XML data mappings and the
-    corresponding XML Schema in one document (or forest), linked
-    together.  They can be useful where self-contained and
-    self-describing results are wanted.
-<synopsis>
-table_to_xml_and_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
-query_to_xml_and_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
-</synopsis>
+    <function>pg_advisory_lock_shared</> works the same as
+    <function>pg_advisory_lock</>,
+    except the lock can be shared with other sessions requesting shared locks.
+    Only would-be exclusive lockers are locked out.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_try_advisory_lock</primary>
+   </indexterm>
    <para>
-    In addition, the following functions are available to produce
-    analogous mappings of entire schemas or the entire current
-    database.
-<synopsis>
-schema_to_xml(schema name, nulls boolean, tableforest boolean, targetns text)
-schema_to_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
-schema_to_xml_and_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
-
-database_to_xml(nulls boolean, tableforest boolean, targetns text)
-database_to_xmlschema(nulls boolean, tableforest boolean, targetns text)
-database_to_xml_and_xmlschema(nulls boolean, tableforest boolean, targetns text)
-</synopsis>
-
-    Note that these potentially produce a lot of data, which needs to
-    be built up in memory.  When requesting content mappings of large
-    schemas or databases, it may be worthwhile to consider mapping the
-    tables separately instead, possibly even through a cursor.
+    <function>pg_try_advisory_lock</> is similar to
+    <function>pg_advisory_lock</>, except the function will not wait for the
+    lock to become available.  It will either obtain the lock immediately and
+    return <literal>true</>, or return <literal>false</> if the lock cannot be
+    acquired now.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_try_advisory_lock_shared</primary>
+   </indexterm>
    <para>
-    The result of a schema content mapping looks like this:
-
-<screen><![CDATA[
-<schemaname>
-
-table1-mapping
-
-table2-mapping
-
-...
-
-</schemaname>]]></screen>
-
-    where the format of a table mapping depends on the
-    <parameter>tableforest</parameter> parameter as explained above.
+    <function>pg_try_advisory_lock_shared</> works the same as
+    <function>pg_try_advisory_lock</>, except it attempts to acquire
+    shared rather than exclusive lock.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_unlock</primary>
+   </indexterm>
    <para>
-    The result of a database content mapping looks like this:
-
-<screen><![CDATA[
-<dbname>
-
-<schema1name>
-  ...
-</schema1name>
-
-<schema2name>
-  ...
-</schema2name>
-
-...
-
-</dbname>]]></screen>
-
-    where the schema mapping is as above.
+    <function>pg_advisory_unlock</> will release a previously-acquired
+    exclusive advisory lock.  It
+    will return <literal>true</> if the lock is successfully released.
+    If the lock was in fact not held, it will return <literal>false</>,
+    and in addition, an SQL warning will be raised by the server.
    </para>
 
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_unlock_shared</primary>
+   </indexterm>
    <para>
-    As an example for using the output produced by these functions,
-    <xref linkend="xslt-xml-html"> shows an XSLT stylesheet that
-    converts the output of
-    <function>table_to_xml_and_xmlschema</function> to an HTML
-    document containing a tabular rendition of the table data.  In a
-    similar manner, the result data of these functions can be
-    converted into other XML-based formats.
+    <function>pg_advisory_unlock_shared</> works the same as
+    <function>pg_advisory_unlock</>, 
+    except to release a shared advisory lock.
    </para>
 
-   <figure id="xslt-xml-html">
-    <title>XSLT stylesheet for converting SQL/XML output to HTML</title>
-<programlisting><![CDATA[
-<?xml version="1.0"?>
-<xsl:stylesheet version="1.0"
-    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-    xmlns="http://www.w3.org/1999/xhtml"
->
-
-  <xsl:output method="xml"
-      doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
-      doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
-      indent="yes"/>
-
-  <xsl:template match="/*">
-    <xsl:variable name="schema" select="//xsd:schema"/>
-    <xsl:variable name="tabletypename"
-                  select="$schema/xsd:element[@name=name(current())]/@type"/>
-    <xsl:variable name="rowtypename"
-                  select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
-
-    <html>
-      <head>
-        <title><xsl:value-of select="name(current())"/></title>
-      </head>
-      <body>
-        <table>
-          <tr>
-            <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
-              <th><xsl:value-of select="."/></th>
-            </xsl:for-each>
-          </tr>
-
-          <xsl:for-each select="row">
-            <tr>
-              <xsl:for-each select="*">
-                <td><xsl:value-of select="."/></td>
-              </xsl:for-each>
-            </tr>
-          </xsl:for-each>
-        </table>
-      </body>
-    </html>
-  </xsl:template>
-
-</xsl:stylesheet>
-]]></programlisting>
-   </figure>
-  </sect2>
-
-  <sect2>
-   <title>Processing XML</title>
-
+   <indexterm zone="functions-admin">
+    <primary>pg_advisory_unlock_all</primary>
+   </indexterm>
    <para>
-    <acronym>XML</> support is not just the existence of an
-    <type>xml</type> data type, but a variety of features supported by
-    a database system.  These capabilities include import/export,
-    indexing, searching, transforming, and <acronym>XML</> to
-    <acronym>SQL</> mapping.  <productname>PostgreSQL</> supports some
-    but not all of these <acronym>XML</> capabilities.  For an
-    overview of <acronym>XML</> use in databases, see <ulink
-    url="http://www.rpbourret.com/xml/XMLAndDatabases.htm"></>.
+    <function>pg_advisory_unlock_all</> will release all advisory locks
+    held by the current session.  (This function is implicitly invoked
+    at session end, even if the client disconnects ungracefully.)
    </para>
 
-   <variablelist>
-   <varlistentry>
-    <term>Indexing</term>
-    <listitem>
-
-     <para>
-      <filename>contrib/xml2/</> functions can be used in expression
-      indexes to index specific <acronym>XML</> fields.  To index the
-      full contents of <acronym>XML</> documents, the full-text
-      indexing tool <filename>contrib/tsearch2/</> can be used.  Of
-      course, Tsearch2 indexes have no <acronym>XML</> awareness so
-      additional <filename>contrib/xml2/</> checks should be added to
-      queries.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>Searching</term>
-    <listitem>
-
-     <para>
-      XPath searches are implemented using <filename>contrib/xml2/</>.
-      It processes <acronym>XML</> text documents and returns results
-      based on the requested query.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>Transforming</term>
-    <listitem>
-
-     <para>
-      <filename>contrib/xml2/</> supports <acronym>XSLT</> (Extensible
-      Stylesheet Language Transformation).
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>XML to SQL Mapping</term>
-    <listitem>
+  </sect1>
 
-     <para>
-      This involves converting <acronym>XML</> data to and from
-      relational structures. <productname>PostgreSQL</> has no
-      internal support for such mapping, and relies on external tools
-      to do such conversions.
-     </para>
-    </listitem>
-   </varlistentry>
-   </variablelist>
-  </sect2>
- </sect1>
 </chapter>