Commit 8c1de5fb authored by Peter Eisentraut's avatar Peter Eisentraut

Initial SQL/XML support: xml data type and initial set of functions.

parent ed1e9cd5
...@@ -894,6 +894,7 @@ Optional Packages: ...@@ -894,6 +894,7 @@ Optional Packages:
--with-openssl build with OpenSSL support --with-openssl build with OpenSSL support
--without-readline do not use GNU Readline nor BSD Libedit for editing --without-readline do not use GNU Readline nor BSD Libedit for editing
--with-libedit-preferred prefer BSD Libedit over GNU Readline --with-libedit-preferred prefer BSD Libedit over GNU Readline
--with-libxml build with XML support
--without-zlib do not use Zlib --without-zlib do not use Zlib
--with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-gnu-ld assume the C compiler uses GNU ld [default=no]
...@@ -4160,6 +4161,42 @@ fi; ...@@ -4160,6 +4161,42 @@ fi;
#
# XML
#
pgac_args="$pgac_args with_libxml"
# Check whether --with-libxml or --without-libxml was given.
if test "${with_libxml+set}" = set; then
withval="$with_libxml"
case $withval in
yes)
cat >>confdefs.h <<\_ACEOF
#define USE_LIBXML 1
_ACEOF
;;
no)
:
;;
*)
{ { echo "$as_me:$LINENO: error: no argument expected for --with-libxml option" >&5
echo "$as_me: error: no argument expected for --with-libxml option" >&2;}
{ (exit 1); exit 1; }; }
;;
esac
else
with_libxml=no
fi;
# #
# Zlib # Zlib
# #
...@@ -7268,6 +7305,87 @@ fi ...@@ -7268,6 +7305,87 @@ fi
fi fi
if test "$with_libxml" = yes ; then
echo "$as_me:$LINENO: checking for xmlInitParser in -lxml2" >&5
echo $ECHO_N "checking for xmlInitParser in -lxml2... $ECHO_C" >&6
if test "${ac_cv_lib_xml2_xmlInitParser+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lxml2 $LIBS"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char xmlInitParser ();
int
main ()
{
xmlInitParser ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_xml2_xmlInitParser=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_xml2_xmlInitParser=no
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
echo "$as_me:$LINENO: result: $ac_cv_lib_xml2_xmlInitParser" >&5
echo "${ECHO_T}$ac_cv_lib_xml2_xmlInitParser" >&6
if test $ac_cv_lib_xml2_xmlInitParser = yes; then
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBXML2 1
_ACEOF
LIBS="-lxml2 $LIBS"
else
{ { echo "$as_me:$LINENO: error: library 'xml2' is required for XML support" >&5
echo "$as_me: error: library 'xml2' is required for XML support" >&2;}
{ (exit 1); exit 1; }; }
fi
fi
## ##
## Header files ## Header files
...@@ -10359,6 +10477,155 @@ fi ...@@ -10359,6 +10477,155 @@ fi
done done
fi
if test "$with_libxml" = yes ; then
if test "${ac_cv_header_libxml_parser_h+set}" = set; then
echo "$as_me:$LINENO: checking for libxml/parser.h" >&5
echo $ECHO_N "checking for libxml/parser.h... $ECHO_C" >&6
if test "${ac_cv_header_libxml_parser_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
echo "$as_me:$LINENO: result: $ac_cv_header_libxml_parser_h" >&5
echo "${ECHO_T}$ac_cv_header_libxml_parser_h" >&6
else
# Is the header compilable?
echo "$as_me:$LINENO: checking libxml/parser.h usability" >&5
echo $ECHO_N "checking libxml/parser.h usability... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <libxml/parser.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6
# Is the header present?
echo "$as_me:$LINENO: checking libxml/parser.h presence" >&5
echo $ECHO_N "checking libxml/parser.h presence... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <libxml/parser.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
else
ac_cpp_err=
fi
else
ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: libxml/parser.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: libxml/parser.h: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: libxml/parser.h: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: libxml/parser.h: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: libxml/parser.h: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: libxml/parser.h: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: libxml/parser.h: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: libxml/parser.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: libxml/parser.h: in the future, the compiler will take precedence" >&2;}
(
cat <<\_ASBOX
## ---------------------------------------- ##
## Report this to pgsql-bugs@postgresql.org ##
## ---------------------------------------- ##
_ASBOX
) |
sed "s/^/$as_me: WARNING: /" >&2
;;
esac
echo "$as_me:$LINENO: checking for libxml/parser.h" >&5
echo $ECHO_N "checking for libxml/parser.h... $ECHO_C" >&6
if test "${ac_cv_header_libxml_parser_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_cv_header_libxml_parser_h=$ac_header_preproc
fi
echo "$as_me:$LINENO: result: $ac_cv_header_libxml_parser_h" >&5
echo "${ECHO_T}$ac_cv_header_libxml_parser_h" >&6
fi
if test $ac_cv_header_libxml_parser_h = yes; then
:
else
{ { echo "$as_me:$LINENO: error: header file <libxml/parser.h> is required for XML support" >&5
echo "$as_me: error: header file <libxml/parser.h> is required for XML support" >&2;}
{ (exit 1); exit 1; }; }
fi
fi fi
if test "$with_ldap" = yes ; then if test "$with_ldap" = yes ; then
......
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
dnl $PostgreSQL: pgsql/configure.in,v 1.492 2006/12/14 21:49:54 tgl Exp $ dnl $PostgreSQL: pgsql/configure.in,v 1.493 2006/12/21 16:05:12 petere Exp $
dnl dnl
dnl Developers, please strive to achieve this order: dnl Developers, please strive to achieve this order:
dnl dnl
...@@ -531,6 +531,13 @@ PGAC_ARG_BOOL(with, libedit-preferred, no, ...@@ -531,6 +531,13 @@ PGAC_ARG_BOOL(with, libedit-preferred, no,
[ --with-libedit-preferred prefer BSD Libedit over GNU Readline]) [ --with-libedit-preferred prefer BSD Libedit over GNU Readline])
#
# XML
#
PGAC_ARG_BOOL(with, libxml, no, [ --with-libxml build with XML support],
[AC_DEFINE([USE_LIBXML], 1, [Define to 1 to build with XML support. (--with-libxml)])])
# #
# Zlib # Zlib
# #
...@@ -716,6 +723,10 @@ if test "$with_pam" = yes ; then ...@@ -716,6 +723,10 @@ if test "$with_pam" = yes ; then
AC_CHECK_LIB(pam, pam_start, [], [AC_MSG_ERROR([library 'pam' is required for PAM])]) AC_CHECK_LIB(pam, pam_start, [], [AC_MSG_ERROR([library 'pam' is required for PAM])])
fi fi
if test "$with_libxml" = yes ; then
AC_CHECK_LIB(xml2, xmlInitParser, [], [AC_MSG_ERROR([library 'xml2' is required for XML support])])
fi
## ##
## Header files ## Header files
...@@ -791,6 +802,10 @@ if test "$with_pam" = yes ; then ...@@ -791,6 +802,10 @@ if test "$with_pam" = yes ; then
[AC_MSG_ERROR([header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.])])]) [AC_MSG_ERROR([header file <security/pam_appl.h> or <pam/pam_appl.h> is required for PAM.])])])
fi fi
if test "$with_libxml" = yes ; then
AC_CHECK_HEADER(libxml/parser.h, [], [AC_MSG_ERROR([header file <libxml/parser.h> is required for XML support])])
fi
if test "$with_ldap" = yes ; then if test "$with_ldap" = yes ; then
if test "$PORTNAME" != "win32"; then if test "$PORTNAME" != "win32"; then
AC_CHECK_HEADERS(ldap.h, [], AC_CHECK_HEADERS(ldap.h, [],
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.181 2006/11/23 04:27:33 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.182 2006/12/21 16:05:12 petere Exp $ -->
<chapter id="datatype"> <chapter id="datatype">
<title id="datatype-title">Data Types</title> <title id="datatype-title">Data Types</title>
...@@ -233,6 +233,12 @@ ...@@ -233,6 +233,12 @@
<entry><type>timestamptz</type></entry> <entry><type>timestamptz</type></entry>
<entry>date and time, including time zone</entry> <entry>date and time, including time zone</entry>
</row> </row>
<row>
<entry><type>xml</type></entry>
<entry></entry>
<entry>XML data</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
...@@ -248,7 +254,8 @@ ...@@ -248,7 +254,8 @@
precision</type>, <type>integer</type>, <type>interval</type>, precision</type>, <type>integer</type>, <type>interval</type>,
<type>numeric</type>, <type>decimal</type>, <type>real</type>, <type>numeric</type>, <type>decimal</type>, <type>real</type>,
<type>smallint</type>, <type>time</type> (with or without time zone), <type>smallint</type>, <type>time</type> (with or without time zone),
<type>timestamp</type> (with or without time zone). <type>timestamp</type> (with or without time zone),
<type>xml</type>.
</para> </para>
</note> </note>
...@@ -3358,12 +3365,21 @@ SELECT * FROM pg_attribute ...@@ -3358,12 +3365,21 @@ SELECT * FROM pg_attribute
</sect1> </sect1>
<sect1 id="datatype-xml"> <sect1 id="datatype-xml">
<title><acronym>XML</> Document Support</title> <title><acronym>XML</> Type</title>
<indexterm zone="datatype"> <indexterm zone="datatype-xml">
<primary>xml</primary> <primary>XML</primary>
</indexterm> </indexterm>
<para>
The data type <type>xml</type> can be used to store XML data. Its
advantage over storing XML data in, say, a text 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">. Currently, there is no support for
validation against a specific <acronym>XML</> schema.
</para>
<para> <para>
<acronym>XML</> (Extensible Markup Language) support is not one <acronym>XML</> (Extensible Markup Language) support is not one
capability, but a variety of features supported by a database capability, but a variety of features supported by a database
...@@ -3378,22 +3394,6 @@ SELECT * FROM pg_attribute ...@@ -3378,22 +3394,6 @@ SELECT * FROM pg_attribute
</para> </para>
<variablelist> <variablelist>
<varlistentry>
<term>Storage</term>
<listitem>
<para>
PostgreSQL does not have a specialized <acronym>XML</> data type.
Users should store <acronym>XML</> documents in ordinary
<type>TEXT</> fields. If you need the document split apart into
its component parts so each element is stored separately, you must
use a middle-ware solution to do that, but once done, the data
becomes relational and has to be processed accordingly.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>Import/Export</term> <term>Import/Export</term>
<listitem> <listitem>
...@@ -3408,21 +3408,6 @@ SELECT * FROM pg_attribute ...@@ -3408,21 +3408,6 @@ SELECT * FROM pg_attribute
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>Validation</term>
<listitem>
<para>
<filename>/contrib/xml2</> has a function called
<function>xml_is_well_formed()</> that can be used in a <literal>CHECK</>
constraint to enforce that a field contains well-formed <acronym>XML</>.
It does not support validation against a specific <acronym>XML</>
schema. A server-side language with <acronym>XML</> capabilities
could be used to do schema-specific <acronym>XML</> checks.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>Indexing</term> <term>Indexing</term>
<listitem> <listitem>
...@@ -3438,20 +3423,6 @@ SELECT * FROM pg_attribute ...@@ -3438,20 +3423,6 @@ SELECT * FROM pg_attribute
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>Modification</term>
<listitem>
<para>
If an <command>UPDATE</> does not modify an <acronym>XML</> field,
the <acronym>XML</> data is shared between the old and new rows.
However, if the <command>UPDATE</> modifies an <acronym>XML</>
field, a full modified copy of the <acronym>XML</> field must be
created internally.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>Searching</term> <term>Searching</term>
<listitem> <listitem>
...@@ -3487,19 +3458,6 @@ SELECT * FROM pg_attribute ...@@ -3487,19 +3458,6 @@ SELECT * FROM pg_attribute
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>Missing Features</term>
<listitem>
<para>
Missing features include XQuery, SQL/XML syntax (ISO/IEC
9075-14), and an <acronym>XML</> data type optimized for
<acronym>XML</> storage.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</sect1> </sect1>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.347 2006/11/25 00:38:53 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.348 2006/12/21 16:05:12 petere Exp $ -->
<chapter id="functions"> <chapter id="functions">
<title>Functions and Operators</title> <title>Functions and Operators</title>
...@@ -10741,4 +10741,113 @@ SELECT (pg_stat_file('filename')).modification; ...@@ -10741,4 +10741,113 @@ SELECT (pg_stat_file('filename')).modification;
</para> </para>
</sect1> </sect1>
<sect1 id="functions-xml">
<title>XML Functions</title>
<para>
The functions and function-like expressions described in this
section operate on values of type <type>xml</type>.
</para>
<sect2>
<title><literal>xmlcomment</literal></title>
<indexterm>
<primary>xmlcomment</primary>
</indexterm>
<synopsis>
<function>xmlcomment</function>(<replaceable>text</replaceable>)
</synopsis>
<para>
Creates an XML comment.
</para>
</sect2>
<sect2>
<title><literal>xmlconcat</literal></title>
<indexterm>
<primary>xmlconcat</primary>
</indexterm>
<synopsis>
<function>xmlconcat</function>(<replaceable>xml</replaceable><optional>, xml, ...</optional>)
</synopsis>
<para>
Combines a list of individual XML values to create a
single value containing an XML forest.
</para>
</sect2>
<sect2>
<title><literal>xmlelement</literal></title>
<indexterm>
<primary>xmlelement</primary>
</indexterm>
<synopsis>
<function>xmlelement</function>(name <replaceable>name</replaceable><optional>, xmlattribytes(<replaceable>value</replaceable> <optional>AS <replaceable>label</replaceable></optional><optional>, ... </optional>)</optional>
<optional><replaceable>, content, ...</replaceable></optional>)
</synopsis>
<para>
Creates an XML element, allowing the name to be specified.
</para>
</sect2>
<sect2>
<title><literal>xmlforest</literal></title>
<indexterm>
<primary>xmlforest</primary>
</indexterm>
<synopsis>
<function>xmlforest</function>(<replaceable>value</replaceable> <optional>AS <replaceable>label</replaceable></optional><optional>, ...</optional>)
</synopsis>
<para>
Creates XML elements from columns, using the name of each
column as the name of the corresponding element.
</para>
</sect2>
<sect2>
<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>
Creates an XML processing instruction.
</para>
</sect2>
<sect2>
<title><literal>xmlroot</literal></title>
<indexterm>
<primary>xmlroot</primary>
</indexterm>
<synopsis>
<function>xmlroot</function>(<replaceable>xml</replaceable>, version <replaceable>text</replaceable> <optional>, standalone yes|no|no value</optional>)
</synopsis>
<para>
Creates the root node of an XML document.
</para>
</sect2>
</sect1>
</chapter> </chapter>
<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.268 2006/12/02 09:29:51 petere Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.269 2006/12/21 16:05:13 petere Exp $ -->
<chapter id="installation"> <chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]> <title><![%standalone-include[<productname>PostgreSQL</>]]>
...@@ -905,6 +905,15 @@ su - postgres ...@@ -905,6 +905,15 @@ su - postgres
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--with-libxml</option></term>
<listitem>
<para>
Build with libxml, required for SQL/XML support.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--enable-integer-datetimes</option></term> <term><option>--enable-integer-datetimes</option></term>
<listitem> <listitem>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.199 2006/11/17 16:46:27 petere Exp $ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.200 2006/12/21 16:05:13 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/typcache.h" #include "utils/typcache.h"
#include "utils/xml.h"
/* static function decls */ /* static function decls */
...@@ -119,6 +120,8 @@ static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr, ...@@ -119,6 +120,8 @@ static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr, static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(NullTestState *nstate, static Datum ExecEvalNullTest(NullTestState *nstate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
...@@ -2878,6 +2881,120 @@ ExecEvalBooleanTest(GenericExprState *bstate, ...@@ -2878,6 +2881,120 @@ ExecEvalBooleanTest(GenericExprState *bstate,
} }
} }
/* ----------------------------------------------------------------
* ExecEvalXml
* ----------------------------------------------------------------
*/
static Datum
ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
StringInfoData buf;
bool isnull;
ListCell *arg;
text *result = NULL;
int len;
initStringInfo(&buf);
*isNull = false;
if (isDone)
*isDone = ExprSingleResult;
switch (xmlExpr->op)
{
case IS_XMLCONCAT:
*isNull = true;
foreach(arg, xmlExpr->args)
{
ExprState *e = (ExprState *) lfirst(arg);
Datum value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (!isnull)
{
appendStringInfoString(&buf, DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeout, value)));
*isNull = false;
}
}
break;
case IS_XMLELEMENT:
{
int state = 0, i = 0;
appendStringInfo(&buf, "<%s", xmlExpr->name);
foreach(arg, xmlExpr->named_args)
{
GenericExprState *gstate = (GenericExprState *) lfirst(arg);
Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
if (!isnull)
{
char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->named_args_tcache[i], value));
appendStringInfo(&buf, " %s=\"%s\"", xmlExpr->named_args_ncache[i], outstr);
pfree(outstr);
}
i++;
}
if (xmlExpr->args)
{
ExprState *expr = linitial(xmlExpr->args);
Datum value = ExecEvalExpr(expr, econtext, &isnull, NULL);
if (!isnull)
{
char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeout, value));
if (state == 0)
{
appendStringInfoChar(&buf, '>');
state = 1;
}
appendStringInfo(&buf, "%s", outstr);
pfree(outstr);
}
}
if (state == 0)
appendStringInfo(&buf, "/>");
else if (state == 1)
appendStringInfo(&buf, "</%s>", xmlExpr->name);
}
break;
case IS_XMLFOREST:
{
/* only if all argumets are null returns null */
int i = 0;
*isNull = true;
foreach(arg, xmlExpr->named_args)
{
GenericExprState *gstate = (GenericExprState *) lfirst(arg);
Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
if (!isnull)
{
char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->named_args_tcache[i], value));
appendStringInfo(&buf, "<%s>%s</%s>", xmlExpr->named_args_ncache[i], outstr, xmlExpr->named_args_ncache[i]);
pfree(outstr);
*isNull = false;
}
i += 1;
}
}
break;
default:
break;
}
len = buf.len + VARHDRSZ;
result = palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), buf.data, buf.len);
pfree(buf.data);
PG_RETURN_TEXT_P(result);
}
/* /*
* ExecEvalCoerceToDomain * ExecEvalCoerceToDomain
* *
...@@ -3668,6 +3785,64 @@ ExecInitExpr(Expr *node, PlanState *parent) ...@@ -3668,6 +3785,64 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) mstate; state = (ExprState *) mstate;
} }
break; break;
case T_XmlExpr:
{
List *outlist;
ListCell *arg;
XmlExpr *xexpr = (XmlExpr *) node;
XmlExprState *xstate = makeNode(XmlExprState);
int i = 0;
Oid typeout;
xstate->name = xexpr->name;
xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
xstate->op = xexpr->op;
outlist = NIL;
if (xexpr->named_args)
{
xstate->named_args_tcache = (Oid *) palloc(list_length(xexpr->named_args) * sizeof(int));
xstate->named_args_ncache = (char **) palloc(list_length(xexpr->named_args) * sizeof(char *));
i = 0;
foreach(arg, xexpr->named_args)
{
bool tpisvarlena;
Expr *e = (Expr *) lfirst(arg);
ExprState *estate = ExecInitExpr(e, parent);
TargetEntry *tle;
outlist = lappend(outlist, estate);
tle = (TargetEntry *) ((GenericExprState *) estate)->xprstate.expr;
getTypeOutputInfo(exprType((Node *)tle->expr), &typeout, &tpisvarlena);
xstate->named_args_ncache[i] = tle->resname;
xstate->named_args_tcache[i] = typeout;
i++;
}
}
else
{
xstate->named_args_tcache = NULL;
xstate->named_args_ncache = NULL;
}
xstate->named_args = outlist;
outlist = NIL;
foreach(arg, xexpr->args)
{
bool tpisvarlena;
ExprState *estate;
Expr *e = (Expr *) lfirst(arg);
getTypeOutputInfo(exprType((Node *)e), &typeout, &tpisvarlena);
estate = ExecInitExpr(e, parent);
outlist = lappend(outlist, estate);
}
xstate->arg_typeout = typeout;
xstate->args = outlist;
state = (ExprState *) xstate;
}
break;
case T_NullIfExpr: case T_NullIfExpr:
{ {
NullIfExpr *nullifexpr = (NullIfExpr *) node; NullIfExpr *nullifexpr = (NullIfExpr *) node;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.354 2006/12/10 22:13:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.355 2006/12/21 16:05:13 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1136,6 +1136,22 @@ _copyBooleanTest(BooleanTest *from) ...@@ -1136,6 +1136,22 @@ _copyBooleanTest(BooleanTest *from)
return newnode; return newnode;
} }
/*
* _copyXmlExpr
*/
static XmlExpr *
_copyXmlExpr(XmlExpr *from)
{
XmlExpr *newnode = makeNode(XmlExpr);
COPY_SCALAR_FIELD(op);
COPY_STRING_FIELD(name);
COPY_NODE_FIELD(named_args);
COPY_NODE_FIELD(args);
return newnode;
}
/* /*
* _copyCoerceToDomain * _copyCoerceToDomain
*/ */
...@@ -2966,6 +2982,9 @@ copyObject(void *from) ...@@ -2966,6 +2982,9 @@ copyObject(void *from)
case T_BooleanTest: case T_BooleanTest:
retval = _copyBooleanTest(from); retval = _copyBooleanTest(from);
break; break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;
case T_CoerceToDomain: case T_CoerceToDomain:
retval = _copyCoerceToDomain(from); retval = _copyCoerceToDomain(from);
break; break;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.288 2006/12/10 22:13:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.289 2006/12/21 16:05:13 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -495,6 +495,17 @@ _equalBooleanTest(BooleanTest *a, BooleanTest *b) ...@@ -495,6 +495,17 @@ _equalBooleanTest(BooleanTest *a, BooleanTest *b)
return true; return true;
} }
static bool
_equalXmlExpr(XmlExpr *a, XmlExpr *b)
{
COMPARE_SCALAR_FIELD(op);
COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(named_args);
COMPARE_NODE_FIELD(args);
return true;
}
static bool static bool
_equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b) _equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b)
{ {
...@@ -1968,6 +1979,9 @@ equal(void *a, void *b) ...@@ -1968,6 +1979,9 @@ equal(void *a, void *b)
case T_BooleanTest: case T_BooleanTest:
retval = _equalBooleanTest(a, b); retval = _equalBooleanTest(a, b);
break; break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;
case T_CoerceToDomain: case T_CoerceToDomain:
retval = _equalCoerceToDomain(a, b); retval = _equalCoerceToDomain(a, b);
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.286 2006/12/10 22:13:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.287 2006/12/21 16:05:13 petere Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -920,6 +920,17 @@ _outBooleanTest(StringInfo str, BooleanTest *node) ...@@ -920,6 +920,17 @@ _outBooleanTest(StringInfo str, BooleanTest *node)
WRITE_ENUM_FIELD(booltesttype, BoolTestType); WRITE_ENUM_FIELD(booltesttype, BoolTestType);
} }
static void
_outXmlExpr(StringInfo str, XmlExpr *node)
{
WRITE_NODE_TYPE("XMLEXPR");
WRITE_ENUM_FIELD(op, XmlExprOp);
WRITE_STRING_FIELD(name);
WRITE_NODE_FIELD(named_args);
WRITE_NODE_FIELD(args);
}
static void static void
_outCoerceToDomain(StringInfo str, CoerceToDomain *node) _outCoerceToDomain(StringInfo str, CoerceToDomain *node)
{ {
...@@ -2019,6 +2030,9 @@ _outNode(StringInfo str, void *obj) ...@@ -2019,6 +2030,9 @@ _outNode(StringInfo str, void *obj)
case T_BooleanTest: case T_BooleanTest:
_outBooleanTest(str, obj); _outBooleanTest(str, obj);
break; break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;
case T_CoerceToDomain: case T_CoerceToDomain:
_outCoerceToDomain(str, obj); _outCoerceToDomain(str, obj);
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.196 2006/12/10 22:13:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.197 2006/12/21 16:05:13 petere Exp $
* *
* NOTES * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
...@@ -764,6 +764,22 @@ _readBooleanTest(void) ...@@ -764,6 +764,22 @@ _readBooleanTest(void)
READ_DONE(); READ_DONE();
} }
/*
* _readXmlExpr
*/
static XmlExpr *
_readXmlExpr(void)
{
READ_LOCALS(XmlExpr);
READ_ENUM_FIELD(op, XmlExprOp);
READ_STRING_FIELD(name);
READ_NODE_FIELD(named_args);
READ_NODE_FIELD(args);
READ_DONE();
}
/* /*
* _readCoerceToDomain * _readCoerceToDomain
*/ */
...@@ -1014,6 +1030,8 @@ parseNodeString(void) ...@@ -1014,6 +1030,8 @@ parseNodeString(void)
return_value = _readNullTest(); return_value = _readNullTest();
else if (MATCH("BOOLEANTEST", 11)) else if (MATCH("BOOLEANTEST", 11))
return_value = _readBooleanTest(); return_value = _readBooleanTest();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("COERCETODOMAIN", 14)) else if (MATCH("COERCETODOMAIN", 14))
return_value = _readCoerceToDomain(); return_value = _readCoerceToDomain();
else if (MATCH("COERCETODOMAINVALUE", 19)) else if (MATCH("COERCETODOMAINVALUE", 19))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.223 2006/10/25 22:11:32 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.224 2006/12/21 16:05:13 petere Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -559,6 +559,8 @@ expression_returns_set_walker(Node *node, void *context) ...@@ -559,6 +559,8 @@ expression_returns_set_walker(Node *node, void *context)
return false; return false;
if (IsA(node, NullIfExpr)) if (IsA(node, NullIfExpr))
return false; return false;
if (IsA(node, XmlExpr))
return false;
return expression_tree_walker(node, expression_returns_set_walker, return expression_tree_walker(node, expression_returns_set_walker,
context); context);
...@@ -876,6 +878,8 @@ contain_nonstrict_functions_walker(Node *node, void *context) ...@@ -876,6 +878,8 @@ contain_nonstrict_functions_walker(Node *node, void *context)
return true; return true;
if (IsA(node, BooleanTest)) if (IsA(node, BooleanTest))
return true; return true;
if (IsA(node, XmlExpr))
return true;
return expression_tree_walker(node, contain_nonstrict_functions_walker, return expression_tree_walker(node, contain_nonstrict_functions_walker,
context); context);
} }
...@@ -3334,6 +3338,16 @@ expression_tree_walker(Node *node, ...@@ -3334,6 +3338,16 @@ expression_tree_walker(Node *node,
return walker(((NullTest *) node)->arg, context); return walker(((NullTest *) node)->arg, context);
case T_BooleanTest: case T_BooleanTest:
return walker(((BooleanTest *) node)->arg, context); return walker(((BooleanTest *) node)->arg, context);
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
if (walker(xexpr->named_args, context))
return true;
if (walker(xexpr->args, context))
return true;
}
break;
case T_CoerceToDomain: case T_CoerceToDomain:
return walker(((CoerceToDomain *) node)->arg, context); return walker(((CoerceToDomain *) node)->arg, context);
case T_TargetEntry: case T_TargetEntry:
...@@ -3857,6 +3871,17 @@ expression_tree_mutator(Node *node, ...@@ -3857,6 +3871,17 @@ expression_tree_mutator(Node *node,
return (Node *) newnode; return (Node *) newnode;
} }
break; break;
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
XmlExpr *newnode;
FLATCOPY(newnode, xexpr, XmlExpr);
MUTATE(newnode->named_args, xexpr->named_args, List *);
MUTATE(newnode->args, xexpr->args, List *);
return (Node *) newnode;
}
break;
case T_NullIfExpr: case T_NullIfExpr:
{ {
NullIfExpr *expr = (NullIfExpr *) node; NullIfExpr *expr = (NullIfExpr *) node;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.568 2006/11/05 22:42:09 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.569 2006/12/21 16:05:14 petere Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -106,6 +106,7 @@ static void insertSelectOptions(SelectStmt *stmt, ...@@ -106,6 +106,7 @@ static void insertSelectOptions(SelectStmt *stmt,
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg); static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
static Node *doNegate(Node *n, int location); static Node *doNegate(Node *n, int location);
static void doNegateFloat(Value *v); static void doNegateFloat(Value *v);
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args);
%} %}
...@@ -345,6 +346,11 @@ static void doNegateFloat(Value *v); ...@@ -345,6 +346,11 @@ static void doNegateFloat(Value *v);
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner %type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
%type <list> opt_check_option %type <list> opt_check_option
%type <target> xml_attribute_el
%type <list> xml_attribute_list xml_attributes
%type <node> xml_root_version
%type <ival> opt_xml_root_standalone document_or_content xml_whitespace_option
/* /*
* If you make any token changes, update the keyword table in * If you make any token changes, update the keyword table in
...@@ -365,13 +371,13 @@ static void doNegateFloat(Value *v); ...@@ -365,13 +371,13 @@ static void doNegateFloat(Value *v);
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS
CONVERSION_P CONVERT COPY CREATE CREATEDB CONTENT CONVERSION_P CONVERT COPY CREATE CREATEDB
CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS
DESC DISABLE_P DISTINCT DO DOMAIN_P DOUBLE_P DROP DESC DISABLE_P DISTINCT DO DOCUMENT DOMAIN_P DOUBLE_P DROP
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING
EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
...@@ -398,7 +404,7 @@ static void doNegateFloat(Value *v); ...@@ -398,7 +404,7 @@ static void doNegateFloat(Value *v);
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB NAME NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
...@@ -417,8 +423,8 @@ static void doNegateFloat(Value *v); ...@@ -417,8 +423,8 @@ static void doNegateFloat(Value *v);
SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE START STATEMENT
STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP SUBSTRING SUPERUSER_P SYMMETRIC
SYSID SYSTEM_P SYSID SYSTEM_P
TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
...@@ -428,12 +434,15 @@ static void doNegateFloat(Value *v); ...@@ -428,12 +434,15 @@ static void doNegateFloat(Value *v);
UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
UPDATE USER USING UPDATE USER USING
VACUUM VALID VALIDATOR VALUES VARCHAR VARYING VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING
VERBOSE VIEW VOLATILE VERBOSE VERSION VIEW VOLATILE
WHEN WHERE WHITESPACE WITH WITHOUT WORK WRITE
WHEN WHERE WITH WITHOUT WORK WRITE XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE
YEAR_P YEAR_P YES
ZONE ZONE
...@@ -484,6 +493,7 @@ static void doNegateFloat(Value *v); ...@@ -484,6 +493,7 @@ static void doNegateFloat(Value *v);
* left-associativity among the JOIN rules themselves. * left-associativity among the JOIN rules themselves.
*/ */
%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL %left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
%right PRESERVE STRIP
%% %%
/* /*
...@@ -7868,6 +7878,146 @@ func_expr: func_name '(' ')' ...@@ -7868,6 +7878,146 @@ func_expr: func_name '(' ')'
v->op = IS_LEAST; v->op = IS_LEAST;
$$ = (Node *)v; $$ = (Node *)v;
} }
| XMLCONCAT '(' expr_list ')'
{
$$ = makeXmlExpr(IS_XMLCONCAT, NULL, NULL, $3);
}
| XMLELEMENT '(' NAME ColLabel ')'
{
$$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, NULL);
}
| XMLELEMENT '(' NAME ColLabel ',' xml_attributes ')'
{
$$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NULL);
}
| XMLELEMENT '(' NAME ColLabel ',' expr_list ')'
{
$$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, $6);
}
| XMLELEMENT '(' NAME ColLabel ',' xml_attributes ',' expr_list ')'
{
$$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8);
}
| XMLFOREST '(' xml_attribute_list ')'
{
$$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NULL);
}
| XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("xmlparse");
n->args = list_make3(makeBoolAConst($3 == DOCUMENT), $4, makeBoolAConst($5 == PRESERVE));
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n;
}
| XMLPI '(' NAME ColLabel ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("xmlpi");
n->args = list_make1(makeStringConst($4, NULL));
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n;
}
| XMLPI '(' NAME ColLabel ',' a_expr ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = SystemFuncName("xmlpi");
n->args = list_make2(makeStringConst($4, NULL), $6);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n;
}
| XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'
{
FuncCall *n = makeNode(FuncCall);
Node *ver;
A_Const *sa;
if ($5)
ver = $5;
else
{
A_Const *val;
val = makeNode(A_Const);
val->val.type = T_Null;
ver = (Node *) val;
}
if ($6)
sa = makeBoolAConst($6 == 1);
else
{
sa = makeNode(A_Const);
sa->val.type = T_Null;
}
n->funcname = SystemFuncName("xmlroot");
n->args = list_make3($3, ver, sa);
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n;
}
| XMLSERIALIZE '(' document_or_content a_expr AS Typename ')'
{
/*
* FIXME: This should be made distinguishable from
* CAST (for reverse compilation at least).
*/
$$ = makeTypeCast($4, $6);
}
;
/*
* SQL/XML support
*/
xml_root_version: VERSION a_expr { $$ = $2; }
| VERSION NO VALUE { $$ = NULL; }
;
opt_xml_root_standalone: ',' STANDALONE YES { $$ = 1; }
| ',' STANDALONE NO { $$ = -1; }
| ',' STANDALONE NO VALUE { $$ = 0; }
| /*EMPTY*/ { $$ = 0; }
;
xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; }
;
xml_attribute_list: xml_attribute_el { $$ = list_make1($1); }
| xml_attribute_list ',' xml_attribute_el { $$ = lappend($1, $3); }
;
xml_attribute_el: a_expr AS ColLabel
{
$$ = makeNode(ResTarget);
$$->name = $3;
$$->indirection = NULL;
$$->val = (Node *) $1;
}
| a_expr
{
$$ = makeNode(ResTarget);
$$->name = NULL;
$$->indirection = NULL;
$$->val = (Node *) $1;
}
;
document_or_content: DOCUMENT { $$ = DOCUMENT; }
| CONTENT { $$ = CONTENT; }
;
xml_whitespace_option: PRESERVE WHITESPACE { $$ = PRESERVE; }
| STRIP WHITESPACE { $$ = STRIP; }
| /*EMPTY*/ { $$ = STRIP; }
; ;
/* /*
...@@ -8562,6 +8712,7 @@ unreserved_keyword: ...@@ -8562,6 +8712,7 @@ unreserved_keyword:
| CONCURRENTLY | CONCURRENTLY
| CONNECTION | CONNECTION
| CONSTRAINTS | CONSTRAINTS
| CONTENT
| CONVERSION_P | CONVERSION_P
| COPY | COPY
| CREATEDB | CREATEDB
...@@ -8581,6 +8732,7 @@ unreserved_keyword: ...@@ -8581,6 +8732,7 @@ unreserved_keyword:
| DELIMITER | DELIMITER
| DELIMITERS | DELIMITERS
| DISABLE_P | DISABLE_P
| DOCUMENT
| DOMAIN_P | DOMAIN_P
| DOUBLE_P | DOUBLE_P
| DROP | DROP
...@@ -8640,6 +8792,7 @@ unreserved_keyword: ...@@ -8640,6 +8792,7 @@ unreserved_keyword:
| MODE | MODE
| MONTH_P | MONTH_P
| MOVE | MOVE
| NAME
| NAMES | NAMES
| NEXT | NEXT
| NO | NO
...@@ -8700,12 +8853,14 @@ unreserved_keyword: ...@@ -8700,12 +8853,14 @@ unreserved_keyword:
| SHOW | SHOW
| SIMPLE | SIMPLE
| STABLE | STABLE
| STANDALONE
| START | START
| STATEMENT | STATEMENT
| STATISTICS | STATISTICS
| STDIN | STDIN
| STDOUT | STDOUT
| STORAGE | STORAGE
| STRIP
| SUPERUSER_P | SUPERUSER_P
| SYSID | SYSID
| SYSTEM_P | SYSTEM_P
...@@ -8729,13 +8884,17 @@ unreserved_keyword: ...@@ -8729,13 +8884,17 @@ unreserved_keyword:
| VALID | VALID
| VALIDATOR | VALIDATOR
| VARYING | VARYING
| VERSION
| VIEW | VIEW
| VALUE
| VOLATILE | VOLATILE
| WHITESPACE
| WITH | WITH
| WITHOUT | WITHOUT
| WORK | WORK
| WRITE | WRITE
| YEAR_P | YEAR_P
| YES
| ZONE | ZONE
; ;
...@@ -8788,6 +8947,14 @@ col_name_keyword: ...@@ -8788,6 +8947,14 @@ col_name_keyword:
| TRIM | TRIM
| VALUES | VALUES
| VARCHAR | VARCHAR
| XMLATTRIBUTES
| XMLELEMENT
| XMLCONCAT
| XMLFOREST
| XMLPARSE
| XMLPI
| XMLROOT
| XMLSERIALIZE
; ;
/* Function identifier --- keywords that can be function names. /* Function identifier --- keywords that can be function names.
...@@ -9322,6 +9489,17 @@ doNegateFloat(Value *v) ...@@ -9322,6 +9489,17 @@ doNegateFloat(Value *v)
} }
} }
static Node *
makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
{
XmlExpr *x = makeNode(XmlExpr);
x->op = op;
x->name = name;
x->named_args = named_args;
x->args = args;
return (Node *) x;
}
/* /*
* Must undefine base_yylex before including scan.c, since we want it * Must undefine base_yylex before including scan.c, since we want it
* to create the function base_yylex not filtered_base_yylex. * to create the function base_yylex not filtered_base_yylex.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.177 2006/10/07 21:51:02 petere Exp $ * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.178 2006/12/21 16:05:14 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -89,6 +89,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -89,6 +89,7 @@ static const ScanKeyword ScanKeywords[] = {
{"connection", CONNECTION}, {"connection", CONNECTION},
{"constraint", CONSTRAINT}, {"constraint", CONSTRAINT},
{"constraints", CONSTRAINTS}, {"constraints", CONSTRAINTS},
{"content", CONTENT},
{"conversion", CONVERSION_P}, {"conversion", CONVERSION_P},
{"convert", CONVERT}, {"convert", CONVERT},
{"copy", COPY}, {"copy", COPY},
...@@ -123,6 +124,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -123,6 +124,7 @@ static const ScanKeyword ScanKeywords[] = {
{"disable", DISABLE_P}, {"disable", DISABLE_P},
{"distinct", DISTINCT}, {"distinct", DISTINCT},
{"do", DO}, {"do", DO},
{"document", DOCUMENT},
{"domain", DOMAIN_P}, {"domain", DOMAIN_P},
{"double", DOUBLE_P}, {"double", DOUBLE_P},
{"drop", DROP}, {"drop", DROP},
...@@ -218,6 +220,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -218,6 +220,7 @@ static const ScanKeyword ScanKeywords[] = {
{"mode", MODE}, {"mode", MODE},
{"month", MONTH_P}, {"month", MONTH_P},
{"move", MOVE}, {"move", MOVE},
{"name", NAME},
{"names", NAMES}, {"names", NAMES},
{"national", NATIONAL}, {"national", NATIONAL},
{"natural", NATURAL}, {"natural", NATURAL},
...@@ -314,6 +317,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -314,6 +317,7 @@ static const ScanKeyword ScanKeywords[] = {
{"smallint", SMALLINT}, {"smallint", SMALLINT},
{"some", SOME}, {"some", SOME},
{"stable", STABLE}, {"stable", STABLE},
{"standalone", STANDALONE},
{"start", START}, {"start", START},
{"statement", STATEMENT}, {"statement", STATEMENT},
{"statistics", STATISTICS}, {"statistics", STATISTICS},
...@@ -321,6 +325,7 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -321,6 +325,7 @@ static const ScanKeyword ScanKeywords[] = {
{"stdout", STDOUT}, {"stdout", STDOUT},
{"storage", STORAGE}, {"storage", STORAGE},
{"strict", STRICT_P}, {"strict", STRICT_P},
{"strip", STRIP},
{"substring", SUBSTRING}, {"substring", SUBSTRING},
{"superuser", SUPERUSER_P}, {"superuser", SUPERUSER_P},
{"symmetric", SYMMETRIC}, {"symmetric", SYMMETRIC},
...@@ -357,19 +362,31 @@ static const ScanKeyword ScanKeywords[] = { ...@@ -357,19 +362,31 @@ static const ScanKeyword ScanKeywords[] = {
{"vacuum", VACUUM}, {"vacuum", VACUUM},
{"valid", VALID}, {"valid", VALID},
{"validator", VALIDATOR}, {"validator", VALIDATOR},
{"value", VALUE},
{"values", VALUES}, {"values", VALUES},
{"varchar", VARCHAR}, {"varchar", VARCHAR},
{"varying", VARYING}, {"varying", VARYING},
{"verbose", VERBOSE}, {"verbose", VERBOSE},
{"version", VERSION},
{"view", VIEW}, {"view", VIEW},
{"volatile", VOLATILE}, {"volatile", VOLATILE},
{"when", WHEN}, {"when", WHEN},
{"where", WHERE}, {"where", WHERE},
{"whitespace", WHITESPACE},
{"with", WITH}, {"with", WITH},
{"without", WITHOUT}, {"without", WITHOUT},
{"work", WORK}, {"work", WORK},
{"write", WRITE}, {"write", WRITE},
{"xmlattributes", XMLATTRIBUTES},
{"xmlconcat", XMLCONCAT},
{"xmlelement", XMLELEMENT},
{"xmlforest", XMLFOREST},
{"xmlparse", XMLPARSE},
{"xmlpi", XMLPI},
{"xmlroot", XMLROOT},
{"xmlserialize", XMLSERIALIZE},
{"year", YEAR_P}, {"year", YEAR_P},
{"yes", YES},
{"zone", ZONE}, {"zone", ZONE},
}; };
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.147 2006/12/10 22:13:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.148 2006/12/21 16:05:14 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -919,6 +919,46 @@ coerce_to_bigint(ParseState *pstate, Node *node, ...@@ -919,6 +919,46 @@ coerce_to_bigint(ParseState *pstate, Node *node,
return node; return node;
} }
/*
* coerce_to_xml()
* Coerce an argument of a construct that requires xml input.
* Also check that input is not a set.
*
* Returns the possibly-transformed node tree.
*
* As with coerce_type, pstate may be NULL if no special unknown-Param
* processing is wanted.
*/
Node *
coerce_to_xml(ParseState *pstate, Node *node,
const char *constructName)
{
Oid inputTypeId = exprType(node);
if (inputTypeId != XMLOID)
{
node = coerce_to_target_type(pstate, node, inputTypeId,
XMLOID, -1,
COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST);
if (node == NULL)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
/* translator: first %s is name of a SQL construct, eg LIMIT */
errmsg("argument of %s must be type xml, not type %s",
constructName, format_type_be(inputTypeId))));
}
if (expression_returns_set(node))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
/* translator: %s is name of a SQL construct, eg LIMIT */
errmsg("argument of %s must not return a set",
constructName)));
return node;
}
/* select_common_type() /* select_common_type()
* Determine the common supertype of a list of input expression types. * Determine the common supertype of a list of input expression types.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.199 2006/12/10 22:13:26 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.200 2006/12/21 16:05:14 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/xml.h"
bool Transform_null_equals = false; bool Transform_null_equals = false;
...@@ -55,6 +56,7 @@ static Node *transformArrayExpr(ParseState *pstate, ArrayExpr *a); ...@@ -55,6 +56,7 @@ static Node *transformArrayExpr(ParseState *pstate, ArrayExpr *a);
static Node *transformRowExpr(ParseState *pstate, RowExpr *r); static Node *transformRowExpr(ParseState *pstate, RowExpr *r);
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c); static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m); static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname, static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
...@@ -232,6 +234,10 @@ transformExpr(ParseState *pstate, Node *expr) ...@@ -232,6 +234,10 @@ transformExpr(ParseState *pstate, Node *expr)
result = transformBooleanTest(pstate, (BooleanTest *) expr); result = transformBooleanTest(pstate, (BooleanTest *) expr);
break; break;
case T_XmlExpr:
result = transformXmlExpr(pstate, (XmlExpr *) expr);
break;
/********************************************* /*********************************************
* Quietly accept node types that may be presented when we are * Quietly accept node types that may be presented when we are
* called on an already-transformed tree. * called on an already-transformed tree.
...@@ -1409,6 +1415,56 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b) ...@@ -1409,6 +1415,56 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
return (Node *) b; return (Node *) b;
} }
static Node *
transformXmlExpr(ParseState *pstate, XmlExpr *x)
{
ListCell *lc;
XmlExpr *newx = makeNode(XmlExpr);
newx->op = x->op;
if (x->name)
newx->name = map_sql_identifier_to_xml_name(x->name, false);
else
newx->name = NULL;
foreach(lc, x->named_args)
{
ResTarget *r = (ResTarget *) lfirst(lc);
Node *expr = transformExpr(pstate, r->val);
char *argname = NULL;
if (r->name)
argname = map_sql_identifier_to_xml_name(r->name, false);
else if (IsA(r->val, ColumnRef))
argname = map_sql_identifier_to_xml_name(FigureColname(r->val), true);
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
x->op == IS_XMLELEMENT
? errmsg("unnamed attribute value must be a column reference")
: errmsg("unnamed element value must be a column reference")));
newx->named_args = lappend(newx->named_args,
makeTargetEntry((Expr *) expr, 0, argname, false));
}
foreach(lc, x->args)
{
Node *e = (Node *) lfirst(lc);
Node *newe;
newe = coerce_to_xml(pstate, transformExpr(pstate, e),
(x->op == IS_XMLCONCAT
? "XMLCONCAT"
: (x->op == IS_XMLELEMENT
? "XMLELEMENT"
: "XMLFOREST")));
newx->args = lappend(newx->args, newe);
}
return (Node *) newx;
}
/* /*
* Construct a whole-row reference to represent the notation "relation.*". * Construct a whole-row reference to represent the notation "relation.*".
* *
...@@ -1668,6 +1724,9 @@ exprType(Node *expr) ...@@ -1668,6 +1724,9 @@ exprType(Node *expr)
case T_BooleanTest: case T_BooleanTest:
type = BOOLOID; type = BOOLOID;
break; break;
case T_XmlExpr:
type = XMLOID;
break;
case T_CoerceToDomain: case T_CoerceToDomain:
type = ((CoerceToDomain *) expr)->resulttype; type = ((CoerceToDomain *) expr)->resulttype;
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.149 2006/10/04 00:29:56 momjian Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.150 2006/12/21 16:05:14 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1315,6 +1315,21 @@ FigureColnameInternal(Node *node, char **name) ...@@ -1315,6 +1315,21 @@ FigureColnameInternal(Node *node, char **name)
return 2; return 2;
} }
break; break;
case T_XmlExpr:
/* make SQL/XML functions act like a regular function */
switch (((XmlExpr*) node)->op)
{
case IS_XMLCONCAT:
*name = "xmlconcat";
return 2;
case IS_XMLELEMENT:
*name = "xmlelement";
return 2;
case IS_XMLFOREST:
*name = "xmlforest";
return 2;
}
break;
default: default:
break; break;
} }
......
# #
# Makefile for utils/adt # Makefile for utils/adt
# #
# $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.60 2006/04/05 22:11:55 tgl Exp $ # $PostgreSQL: pgsql/src/backend/utils/adt/Makefile,v 1.61 2006/12/21 16:05:15 petere Exp $
# #
subdir = src/backend/utils/adt subdir = src/backend/utils/adt
...@@ -25,7 +25,7 @@ OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \ ...@@ -25,7 +25,7 @@ OBJS = acl.o arrayfuncs.o array_userfuncs.o arrayutils.o bool.o \
tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \ tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
network.o mac.o inet_net_ntop.o inet_net_pton.o \ network.o mac.o inet_net_ntop.o inet_net_pton.o \
ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \ ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o xml.o
like.o: like.c like_match.c like.o: like.c like_match.c
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees * ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text * back to source text
* *
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.235 2006/11/10 22:59:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.236 2006/12/21 16:05:15 petere Exp $
**********************************************************************/ **********************************************************************/
#include "postgres.h" #include "postgres.h"
...@@ -2988,6 +2988,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) ...@@ -2988,6 +2988,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_CoalesceExpr: case T_CoalesceExpr:
case T_MinMaxExpr: case T_MinMaxExpr:
case T_NullIfExpr: case T_NullIfExpr:
case T_XmlExpr:
case T_Aggref: case T_Aggref:
case T_FuncExpr: case T_FuncExpr:
/* function-like: name(..) or name[..] */ /* function-like: name(..) or name[..] */
...@@ -3096,6 +3097,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) ...@@ -3096,6 +3097,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_CoalesceExpr: /* own parentheses */ case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */ case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */ case T_NullIfExpr: /* other separators */
case T_XmlExpr: /* own parentheses */
case T_Aggref: /* own parentheses */ case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */ case T_CaseExpr: /* other separators */
return true; return true;
...@@ -3144,6 +3146,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) ...@@ -3144,6 +3146,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_CoalesceExpr: /* own parentheses */ case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */ case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */ case T_NullIfExpr: /* other separators */
case T_XmlExpr: /* own parentheses */
case T_Aggref: /* own parentheses */ case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */ case T_CaseExpr: /* other separators */
return true; return true;
...@@ -3845,6 +3848,28 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -3845,6 +3848,28 @@ get_rule_expr(Node *node, deparse_context *context,
} }
break; break;
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
switch (xexpr->op)
{
case IS_XMLCONCAT:
appendStringInfo(buf, "XMLCONCAT(");
break;
case IS_XMLELEMENT:
appendStringInfo(buf, "XMLELEMENT(");
break;
case IS_XMLFOREST:
appendStringInfo(buf, "XMLFOREST(");
break;
}
get_rule_expr((Node *) xexpr->named_args, context, true);
get_rule_expr((Node *) xexpr->args, context, true);
appendStringInfoChar(buf, ')');
}
break;
case T_CoerceToDomain: case T_CoerceToDomain:
{ {
CoerceToDomain *ctest = (CoerceToDomain *) node; CoerceToDomain *ctest = (CoerceToDomain *) node;
......
This diff is collapsed.
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* (currently mule internal code (mic) is used) * (currently mule internal code (mic) is used)
* Tatsuo Ishii * Tatsuo Ishii
* *
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.59 2006/10/04 00:30:02 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.60 2006/12/21 16:05:15 petere Exp $
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -599,7 +599,7 @@ void ...@@ -599,7 +599,7 @@ void
SetDatabaseEncoding(int encoding) SetDatabaseEncoding(int encoding)
{ {
if (!PG_VALID_BE_ENCODING(encoding)) if (!PG_VALID_BE_ENCODING(encoding))
elog(ERROR, "invalid database encoding"); elog(ERROR, "invalid database encoding: %d", encoding);
DatabaseEncoding = &pg_enc2name_tbl[encoding]; DatabaseEncoding = &pg_enc2name_tbl[encoding];
Assert(DatabaseEncoding->encoding == encoding); Assert(DatabaseEncoding->encoding == encoding);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* Copyright (c) 2002-2006, PostgreSQL Global Development Group * Copyright (c) 2002-2006, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.26 2006/03/05 15:58:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.27 2006/12/21 16:05:15 petere Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -300,6 +300,8 @@ DATA(insert ( 1266 25 939 i )); ...@@ -300,6 +300,8 @@ DATA(insert ( 1266 25 939 i ));
DATA(insert ( 25 1266 938 e )); DATA(insert ( 25 1266 938 e ));
DATA(insert ( 1700 25 1688 i )); DATA(insert ( 1700 25 1688 i ));
DATA(insert ( 25 1700 1686 e )); DATA(insert ( 25 1700 1686 e ));
DATA(insert ( 142 25 0 e ));
DATA(insert ( 25 142 2896 e ));
/* /*
* Cross-category casts to and from VARCHAR * Cross-category casts to and from VARCHAR
...@@ -338,6 +340,8 @@ DATA(insert ( 1266 1043 939 a )); ...@@ -338,6 +340,8 @@ DATA(insert ( 1266 1043 939 a ));
DATA(insert ( 1043 1266 938 e )); DATA(insert ( 1043 1266 938 e ));
DATA(insert ( 1700 1043 1688 a )); DATA(insert ( 1700 1043 1688 a ));
DATA(insert ( 1043 1700 1686 e )); DATA(insert ( 1043 1700 1686 e ));
DATA(insert ( 142 1043 0 e ));
DATA(insert ( 1043 142 2896 e ));
/* /*
* Cross-category casts to and from BPCHAR * Cross-category casts to and from BPCHAR
...@@ -377,6 +381,7 @@ DATA(insert ( 1266 1042 939 a )); ...@@ -377,6 +381,7 @@ DATA(insert ( 1266 1042 939 a ));
DATA(insert ( 1042 1266 938 e )); DATA(insert ( 1042 1266 938 e ));
DATA(insert ( 1700 1042 1688 a )); DATA(insert ( 1700 1042 1688 a ));
DATA(insert ( 1042 1700 1686 e )); DATA(insert ( 1042 1700 1686 e ));
DATA(insert ( 142 1042 0 e ));
/* /*
* Length-coercion functions * Length-coercion functions
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.430 2006/12/06 18:06:47 neilc Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.431 2006/12/21 16:05:15 petere Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -3976,6 +3976,26 @@ DESCR("release shared advisory lock"); ...@@ -3976,6 +3976,26 @@ DESCR("release shared advisory lock");
DATA(insert OID = 2892 ( pg_advisory_unlock_all PGNSP PGUID 12 f f t f v 0 2278 "" _null_ _null_ _null_ pg_advisory_unlock_all - _null_ )); DATA(insert OID = 2892 ( pg_advisory_unlock_all PGNSP PGUID 12 f f t f v 0 2278 "" _null_ _null_ _null_ pg_advisory_unlock_all - _null_ ));
DESCR("release all advisory locks"); DESCR("release all advisory locks");
/* XML support */
DATA(insert OID = 2893 ( xml_in PGNSP PGUID 12 f f t f i 1 142 "2275" _null_ _null_ _null_ xml_in - _null_ ));
DESCR("I/O");
DATA(insert OID = 2894 ( xml_out PGNSP PGUID 12 f f t f i 1 2275 "142" _null_ _null_ _null_ xml_out - _null_ ));
DESCR("I/O");
DATA(insert OID = 2895 ( xmlcomment PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlcomment - _null_ ));
DESCR("generate an XML comment");
DATA(insert OID = 2896 ( xmlparse PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlparse - _null_ ));
DESCR("perform a non-validating parse of a character string to produce an XML value");
DATA(insert OID = 2897 ( xmlparse PGNSP PGUID 12 f f t f i 3 142 "25 16 16" _null_ _null_ _null_ xmlparse - _null_ ));
DESCR("perform a non-validating parse of a character string to produce an XML value");
DATA(insert OID = 2898 ( xmlpi PGNSP PGUID 12 f f t f i 1 142 "19" _null_ _null_ _null_ xmlpi - _null_ ));
DESCR("generate an XML processing instruction");
DATA(insert OID = 2899 ( xmlpi PGNSP PGUID 12 f f t f i 2 142 "19 25" _null_ _null_ _null_ xmlpi - _null_ ));
DESCR("generate an XML processing instruction");
DATA(insert OID = 2900 ( xmlroot PGNSP PGUID 12 f f f f i 3 142 "142 25 16" _null_ _null_ _null_ xmlroot - _null_ ));
DESCR("create an XML value by modifying the properties of the XML root information item of another XML value");
DATA(insert OID = 2901 ( xmlvalidate PGNSP PGUID 12 f f t f i 2 16 "142 25" _null_ _null_ _null_ xmlvalidate - _null_ ));
DESCR("validate an XML value");
/* /*
* Symbolic values for provolatile column: these indicate whether the result * Symbolic values for provolatile column: these indicate whether the result
* of a function is dependent *only* on the values of its explicit arguments, * of a function is dependent *only* on the values of its explicit arguments,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.172 2006/10/04 00:30:08 momjian Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.173 2006/12/21 16:05:15 petere Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -316,6 +316,10 @@ DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c t \054 1259 0 record_in reco ...@@ -316,6 +316,10 @@ DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c t \054 1259 0 record_in reco
#define PG_CLASS_RELTYPE_OID 83 #define PG_CLASS_RELTYPE_OID 83
/* OIDS 100 - 199 */ /* OIDS 100 - 199 */
DATA(insert OID = 142 ( xml PGNSP PGUID -1 f b t \054 0 0 xml_in xml_out - - - i x f 0 -1 0 _null_ _null_ ));
DESCR("XML content");
#define XMLOID 142
DATA(insert OID = 143 ( _xml PGNSP PGUID -1 f b t \054 0 142 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
/* OIDS 200 - 299 */ /* OIDS 200 - 299 */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.162 2006/12/04 02:06:55 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.163 2006/12/21 16:05:16 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -723,6 +723,22 @@ typedef struct NullTestState ...@@ -723,6 +723,22 @@ typedef struct NullTestState
TupleDesc argdesc; /* tupdesc for most recent input */ TupleDesc argdesc; /* tupdesc for most recent input */
} NullTestState; } NullTestState;
/* ----------------
* XmlExprState node
* ----------------
*/
typedef struct XmlExprState
{
ExprState xprstate;
XmlExprOp op;
char *name;
List *named_args;
List *args;
Oid *named_args_tcache;
char **named_args_ncache;
Oid arg_typeout;
} XmlExprState;
/* ---------------- /* ----------------
* CoerceToDomainState node * CoerceToDomainState node
* ---------------- * ----------------
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.188 2006/09/28 20:51:42 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.189 2006/12/21 16:05:16 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -140,6 +140,7 @@ typedef enum NodeTag ...@@ -140,6 +140,7 @@ typedef enum NodeTag
T_RangeTblRef, T_RangeTblRef,
T_JoinExpr, T_JoinExpr,
T_FromExpr, T_FromExpr,
T_XmlExpr,
/* /*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h) * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
...@@ -168,6 +169,7 @@ typedef enum NodeTag ...@@ -168,6 +169,7 @@ typedef enum NodeTag
T_NullTestState, T_NullTestState,
T_CoerceToDomainState, T_CoerceToDomainState,
T_DomainConstraintState, T_DomainConstraintState,
T_XmlExprState,
/* /*
* TAGS FOR PLANNER NODES (relation.h) * TAGS FOR PLANNER NODES (relation.h)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.118 2006/12/10 22:13:27 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.119 2006/12/21 16:05:16 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -765,6 +765,26 @@ typedef struct BooleanTest ...@@ -765,6 +765,26 @@ typedef struct BooleanTest
BoolTestType booltesttype; /* test type */ BoolTestType booltesttype; /* test type */
} BooleanTest; } BooleanTest;
/*
* XmlExpr - holder for SQL/XML functions XMLCONCAT,
* XMLELEMENT, XMLFOREST
*/
typedef enum XmlExprOp
{
IS_XMLCONCAT,
IS_XMLELEMENT,
IS_XMLFOREST,
} XmlExprOp;
typedef struct XmlExpr
{
Expr xpr;
XmlExprOp op; /* xml expression type */
char *name; /* element name */
List *named_args;
List *args;
} XmlExpr;
/* /*
* CoerceToDomain * CoerceToDomain
* *
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.66 2006/10/04 00:30:09 momjian Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.67 2006/12/21 16:05:16 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -59,6 +59,8 @@ extern Node *coerce_to_integer(ParseState *pstate, Node *node, ...@@ -59,6 +59,8 @@ extern Node *coerce_to_integer(ParseState *pstate, Node *node,
const char *constructName); const char *constructName);
extern Node *coerce_to_bigint(ParseState *pstate, Node *node, extern Node *coerce_to_bigint(ParseState *pstate, Node *node,
const char *constructName); const char *constructName);
extern Node *coerce_to_xml(ParseState *pstate, Node *node,
const char *constructName);
extern Oid select_common_type(List *typeids, const char *context); extern Oid select_common_type(List *typeids, const char *context);
extern Node *coerce_to_common_type(ParseState *pstate, Node *node, extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
......
...@@ -251,6 +251,9 @@ ...@@ -251,6 +251,9 @@
/* Define to 1 if you have the `wldap32' library (-lwldap32). */ /* Define to 1 if you have the `wldap32' library (-lwldap32). */
#undef HAVE_LIBWLDAP32 #undef HAVE_LIBWLDAP32
/* Define to 1 if you have the `xml2' library (-lxml2). */
#undef HAVE_LIBXML2
/* Define to 1 if you have the `z' library (-lz). */ /* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ #undef HAVE_LIBZ
...@@ -627,6 +630,9 @@ ...@@ -627,6 +630,9 @@
/* Define to 1 to build with LDAP support. (--with-ldap) */ /* Define to 1 to build with LDAP support. (--with-ldap) */
#undef USE_LDAP #undef USE_LDAP
/* Define to 1 to build with XML support. (--with-libxml) */
#undef USE_LIBXML
/* Define to select named POSIX semaphores. */ /* Define to select named POSIX semaphores. */
#undef USE_NAMED_POSIX_SEMAPHORES #undef USE_NAMED_POSIX_SEMAPHORES
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* Copyright (c) 2003-2006, PostgreSQL Global Development Group * Copyright (c) 2003-2006, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.20 2006/06/16 23:29:26 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.21 2006/12/21 16:05:16 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -148,6 +148,10 @@ ...@@ -148,6 +148,10 @@
#define ERRCODE_INVALID_BINARY_REPRESENTATION MAKE_SQLSTATE('2','2', 'P','0','3') #define ERRCODE_INVALID_BINARY_REPRESENTATION MAKE_SQLSTATE('2','2', 'P','0','3')
#define ERRCODE_BAD_COPY_FILE_FORMAT MAKE_SQLSTATE('2','2', 'P','0','4') #define ERRCODE_BAD_COPY_FILE_FORMAT MAKE_SQLSTATE('2','2', 'P','0','4')
#define ERRCODE_UNTRANSLATABLE_CHARACTER MAKE_SQLSTATE('2','2', 'P','0','5') #define ERRCODE_UNTRANSLATABLE_CHARACTER MAKE_SQLSTATE('2','2', 'P','0','5')
#define ERRCODE_INVALID_XML_DOCUMENT MAKE_SQLSTATE('2', '2', '0', '0', 'M')
#define ERRCODE_INVALID_XML_CONTENT MAKE_SQLSTATE('2', '2', '0', '0', 'N')
#define ERRCODE_INVALID_XML_COMMENT MAKE_SQLSTATE('2', '2', '0', '0', 'S')
#define ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION MAKE_SQLSTATE('2', '2', '0', '0', 'T')
/* Class 23 - Integrity Constraint Violation */ /* Class 23 - Integrity Constraint Violation */
#define ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION MAKE_SQLSTATE('2','3', '0','0','0') #define ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION MAKE_SQLSTATE('2','3', '0','0','0')
......
/*-------------------------------------------------------------------------
*
* xml.h
* Declarations for XML data type support.
*
*
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.1 2006/12/21 16:05:16 petere Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef XML_H
#define XML_H
#include "fmgr.h"
typedef struct varlena xmltype;
#define DatumGetXmlP(X) ((xmltype *) PG_DETOAST_DATUM(X))
#define PG_GETARG_XML_P(n) DatumGetXmlP(PG_GETARG_DATUM(n))
#define PG_RETURN_XML_P(x) PG_RETURN_POINTER(x)
extern Datum xml_in(PG_FUNCTION_ARGS);
extern Datum xml_out(PG_FUNCTION_ARGS);
extern Datum xmlcomment(PG_FUNCTION_ARGS);
extern Datum xmlparse(PG_FUNCTION_ARGS);
extern Datum xmlpi(PG_FUNCTION_ARGS);
extern Datum xmlroot(PG_FUNCTION_ARGS);
extern Datum xmlvalidate(PG_FUNCTION_ARGS);
extern char *map_sql_identifier_to_xml_name(unsigned char *ident, bool fully_escaped);
#endif /* XML_H */
...@@ -73,7 +73,7 @@ WHERE p1.oid != p2.oid AND ...@@ -73,7 +73,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname, p2.oid, p2.proname SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2 FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND WHERE p1.oid < p2.oid AND
p1.prosrc = p2.prosrc AND p1.prosrc = p2.prosrc AND p1.prosrc NOT IN ('xmlparse', 'xmlpi') AND
p1.prolang = 12 AND p2.prolang = 12 AND p1.prolang = 12 AND p2.prolang = 12 AND
(p1.proisagg = false OR p2.proisagg = false) AND (p1.proisagg = false OR p2.proisagg = false) AND
(p1.prolang != p2.prolang OR (p1.prolang != p2.prolang OR
...@@ -285,6 +285,8 @@ WHERE c.castfunc = p.oid AND ...@@ -285,6 +285,8 @@ WHERE c.castfunc = p.oid AND
-- those are binary-compatible while the reverse way goes through rtrim(). -- those are binary-compatible while the reverse way goes through rtrim().
-- As of 8.2, this finds the cast from cidr to inet, because that is a -- As of 8.2, this finds the cast from cidr to inet, because that is a
-- trivial binary coercion while the other way goes through inet_to_cidr(). -- trivial binary coercion while the other way goes through inet_to_cidr().
-- As of 8.3, this finds casts from xml to text, varchar, and bpchar,
-- because the other direction has to go through xmlparse().
SELECT * SELECT *
FROM pg_cast c FROM pg_cast c
WHERE c.castfunc = 0 AND WHERE c.castfunc = 0 AND
...@@ -297,7 +299,10 @@ WHERE c.castfunc = 0 AND ...@@ -297,7 +299,10 @@ WHERE c.castfunc = 0 AND
25 | 1042 | 0 | i 25 | 1042 | 0 | i
1043 | 1042 | 0 | i 1043 | 1042 | 0 | i
650 | 869 | 0 | i 650 | 869 | 0 | i
(3 rows) 142 | 25 | 0 | e
142 | 1043 | 0 | e
142 | 1042 | 0 | e
(6 rows)
-- **************** pg_operator **************** -- **************** pg_operator ****************
-- Look for illegal values in pg_operator fields. -- Look for illegal values in pg_operator fields.
......
...@@ -160,7 +160,7 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements ...@@ -160,7 +160,7 @@ SELECT name, statement, parameter_types FROM pg_prepared_statements
: \x09ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int); : \x09ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int);
q5 | PREPARE q5(int, text) AS | {integer,text} q5 | PREPARE q5(int, text) AS | {integer,text}
: \x09SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2; : \x09SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2;
q6 | PREPARE q6 AS | {integer,name} q6 | PREPARE q6 AS | {integer,"\"name\""}
: SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; : SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;
q7 | PREPARE q7(unknown) AS | {path} q7 | PREPARE q7(unknown) AS | {path}
: SELECT * FROM road WHERE thepath = $1; : SELECT * FROM road WHERE thepath = $1;
......
This diff is collapsed.
CREATE TABLE xmltest (
id int,
data xml
);
INSERT INTO xmltest VALUES (1, '<value>one</value>');
INSERT INTO xmltest VALUES (2, '<value>two</value>');
INSERT INTO xmltest VALUES (3, '<wrong');
ERROR: could not parse XML data
DETAIL: Expected '>'
SELECT * FROM xmltest;
id | data
----+--------------------
1 | <value>one</value>
2 | <value>two</value>
(2 rows)
SELECT xmlcomment('test');
xmlcomment
-------------
<!--test-->
(1 row)
SELECT xmlcomment('-test');
xmlcomment
--------------
<!---test-->
(1 row)
SELECT xmlcomment('test-');
ERROR: invalid XML comment
SELECT xmlcomment('--test');
ERROR: invalid XML comment
SELECT xmlcomment('te st');
xmlcomment
--------------
<!--te st-->
(1 row)
SELECT xmlconcat(xmlcomment('hello'),
xmlelement(NAME qux, 'foo'),
xmlcomment('world'));
xmlconcat
----------------------------------------
<!--hello--><qux>foo</qux><!--world-->
(1 row)
SELECT xmlconcat('hello', 'you');
xmlconcat
-----------
helloyou
(1 row)
SELECT xmlconcat(1, 2);
ERROR: argument of XMLCONCAT must be type xml, not type integer
SELECT xmlconcat('bad', '<syntax');
ERROR: could not parse XML data
DETAIL: Expected '>'
SELECT xmlelement(name element,
xmlattributes (1 as one, 'deuce' as two),
'content');
xmlelement
------------------------------------------------
<element one="1" two="deuce">content</element>
(1 row)
SELECT xmlelement(name element,
xmlattributes ('unnamed and wrong'));
ERROR: unnamed attribute value must be a column reference
SELECT xmlelement(name element, xmlelement(name nested, 'stuff'));
xmlelement
-------------------------------------------
<element><nested>stuff</nested></element>
(1 row)
SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
xmlelement
----------------------------------------------------------------------
<employee><name>sharon</name><age>25</age><pay>1000</pay></employee>
<employee><name>sam</name><age>30</age><pay>2000</pay></employee>
<employee><name>bill</name><age>20</age><pay>1000</pay></employee>
<employee><name>jeff</name><age>23</age><pay>600</pay></employee>
<employee><name>cim</name><age>30</age><pay>400</pay></employee>
<employee><name>linda</name><age>19</age><pay>100</pay></employee>
(6 rows)
SELECT xmlelement(name wrong, 37);
ERROR: argument of XMLELEMENT must be type xml, not type integer
SELECT xmlpi(name foo);
xmlpi
---------
<?foo?>
(1 row)
SELECT xmlpi(name xmlstuff);
ERROR: invalid XML processing instruction
DETAIL: XML processing instruction target name cannot start with "xml".
SELECT xmlpi(name foo, 'bar');
xmlpi
-------------
<?foo bar?>
(1 row)
SELECT xmlpi(name foo, 'in?>valid');
ERROR: invalid XML processing instruction
DETAIL: XML processing instruction cannot contain "?>".
SELECT xmlroot (
xmlelement (
name gazonk,
xmlattributes (
'val' AS name,
1 + 1 AS num
),
xmlelement (
NAME qux,
'foo'
)
),
version '1.0',
standalone yes
);
xmlroot
------------------------------------------------------------------------------------------
<?xml version="1.0" standalone="yes"?><gazonk name="val" num="2"><qux>foo</qux></gazonk>
(1 row)
SELECT xmlserialize(content data as character varying) FROM xmltest;
data
--------------------
<value>one</value>
<value>two</value>
(2 rows)
-- Check mapping SQL identifier to XML name
SELECT xmlpi(name ":::_xml_abc135.%-&_");
xmlpi
-------------------------------------------------
<?_x003A_::_x005F_xml_abc135._x0025_-_x0026__?>
(1 row)
SELECT xmlpi(name "123");
xmlpi
---------------
<?_x0031_23?>
(1 row)
CREATE TABLE xmltest (
id int,
data xml
);
INSERT INTO xmltest VALUES (1, '<value>one</value>');
ERROR: no XML support in this installation
INSERT INTO xmltest VALUES (2, '<value>two</value>');
ERROR: no XML support in this installation
INSERT INTO xmltest VALUES (3, '<wrong');
ERROR: no XML support in this installation
SELECT * FROM xmltest;
id | data
----+------
(0 rows)
SELECT xmlcomment('test');
ERROR: no XML support in this installation
SELECT xmlcomment('-test');
ERROR: no XML support in this installation
SELECT xmlcomment('test-');
ERROR: no XML support in this installation
SELECT xmlcomment('--test');
ERROR: no XML support in this installation
SELECT xmlcomment('te st');
ERROR: no XML support in this installation
SELECT xmlconcat(xmlcomment('hello'),
xmlelement(NAME qux, 'foo'),
xmlcomment('world'));
ERROR: no XML support in this installation
SELECT xmlconcat('hello', 'you');
ERROR: no XML support in this installation
SELECT xmlconcat(1, 2);
ERROR: argument of XMLCONCAT must be type xml, not type integer
SELECT xmlconcat('bad', '<syntax');
ERROR: no XML support in this installation
SELECT xmlelement(name element,
xmlattributes (1 as one, 'deuce' as two),
'content');
ERROR: no XML support in this installation
SELECT xmlelement(name element,
xmlattributes ('unnamed and wrong'));
ERROR: no XML support in this installation
SELECT xmlelement(name element, xmlelement(name nested, 'stuff'));
ERROR: no XML support in this installation
SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
ERROR: no XML support in this installation
SELECT xmlelement(name wrong, 37);
ERROR: no XML support in this installation
SELECT xmlpi(name foo);
ERROR: no XML support in this installation
SELECT xmlpi(name xmlstuff);
ERROR: no XML support in this installation
SELECT xmlpi(name foo, 'bar');
ERROR: no XML support in this installation
SELECT xmlpi(name foo, 'in?>valid');
ERROR: no XML support in this installation
SELECT xmlroot (
xmlelement (
name gazonk,
xmlattributes (
'val' AS name,
1 + 1 AS num
),
xmlelement (
NAME qux,
'foo'
)
),
version '1.0',
standalone yes
);
ERROR: no XML support in this installation
-- Check mapping SQL identifier to XML name
SELECT xmlpi(name ":::_xml_abc135.%-&_");
ERROR: no XML support in this installation
SELECT xmlpi(name "123");
ERROR: no XML support in this installation
# ---------- # ----------
# The first group of parallel test # The first group of parallel test
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.35 2006/08/30 23:34:22 tgl Exp $ # $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.36 2006/12/21 16:05:16 petere Exp $
# ---------- # ----------
test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric
...@@ -75,7 +75,7 @@ test: select_views portals_p2 rules foreign_key cluster dependency guc ...@@ -75,7 +75,7 @@ test: select_views portals_p2 rules foreign_key cluster dependency guc
# The sixth group of parallel test # The sixth group of parallel test
# ---------- # ----------
# "plpgsql" cannot run concurrently with "rules" # "plpgsql" cannot run concurrently with "rules"
test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism rowtypes returning test: limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism rowtypes returning xml
# run stats by itself because its delay may be insufficient under heavy load # run stats by itself because its delay may be insufficient under heavy load
test: stats test: stats
......
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.33 2006/08/30 23:34:22 tgl Exp $ # $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.34 2006/12/21 16:05:16 petere Exp $
# This should probably be in an order similar to parallel_schedule. # This should probably be in an order similar to parallel_schedule.
test: boolean test: boolean
test: char test: char
...@@ -102,5 +102,6 @@ test: sequence ...@@ -102,5 +102,6 @@ test: sequence
test: polymorphism test: polymorphism
test: rowtypes test: rowtypes
test: returning test: returning
test: xml
test: stats test: stats
test: tablespace test: tablespace
...@@ -76,7 +76,7 @@ WHERE p1.oid != p2.oid AND ...@@ -76,7 +76,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname, p2.oid, p2.proname SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2 FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND WHERE p1.oid < p2.oid AND
p1.prosrc = p2.prosrc AND p1.prosrc = p2.prosrc AND p1.prosrc NOT IN ('xmlparse', 'xmlpi') AND
p1.prolang = 12 AND p2.prolang = 12 AND p1.prolang = 12 AND p2.prolang = 12 AND
(p1.proisagg = false OR p2.proisagg = false) AND (p1.proisagg = false OR p2.proisagg = false) AND
(p1.prolang != p2.prolang OR (p1.prolang != p2.prolang OR
...@@ -235,6 +235,9 @@ WHERE c.castfunc = p.oid AND ...@@ -235,6 +235,9 @@ WHERE c.castfunc = p.oid AND
-- As of 8.2, this finds the cast from cidr to inet, because that is a -- As of 8.2, this finds the cast from cidr to inet, because that is a
-- trivial binary coercion while the other way goes through inet_to_cidr(). -- trivial binary coercion while the other way goes through inet_to_cidr().
-- As of 8.3, this finds casts from xml to text, varchar, and bpchar,
-- because the other direction has to go through xmlparse().
SELECT * SELECT *
FROM pg_cast c FROM pg_cast c
WHERE c.castfunc = 0 AND WHERE c.castfunc = 0 AND
......
CREATE TABLE xmltest (
id int,
data xml
);
INSERT INTO xmltest VALUES (1, '<value>one</value>');
INSERT INTO xmltest VALUES (2, '<value>two</value>');
INSERT INTO xmltest VALUES (3, '<wrong');
SELECT * FROM xmltest;
SELECT xmlcomment('test');
SELECT xmlcomment('-test');
SELECT xmlcomment('test-');
SELECT xmlcomment('--test');
SELECT xmlcomment('te st');
SELECT xmlconcat(xmlcomment('hello'),
xmlelement(NAME qux, 'foo'),
xmlcomment('world'));
SELECT xmlconcat('hello', 'you');
SELECT xmlconcat(1, 2);
SELECT xmlconcat('bad', '<syntax');
SELECT xmlelement(name element,
xmlattributes (1 as one, 'deuce' as two),
'content');
SELECT xmlelement(name element,
xmlattributes ('unnamed and wrong'));
SELECT xmlelement(name element, xmlelement(name nested, 'stuff'));
SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
SELECT xmlelement(name wrong, 37);
SELECT xmlpi(name foo);
SELECT xmlpi(name xmlstuff);
SELECT xmlpi(name foo, 'bar');
SELECT xmlpi(name foo, 'in?>valid');
SELECT xmlroot (
xmlelement (
name gazonk,
xmlattributes (
'val' AS name,
1 + 1 AS num
),
xmlelement (
NAME qux,
'foo'
)
),
version '1.0',
standalone yes
);
SELECT xmlserialize(content data as character varying) FROM xmltest;
-- Check mapping SQL identifier to XML name
SELECT xmlpi(name ":::_xml_abc135.%-&_");
SELECT xmlpi(name "123");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment