Re: SQL/XML publishing function experimental patch II - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: SQL/XML publishing function experimental patch II
Date
Msg-id 200606141945.k5EJjpk26566@candle.pha.pa.us
Whole thread Raw
In response to Re: SQL/XML publishing function experimental patch II  (David Fetter <david@fetter.org>)
Responses Re: SQL/XML publishing function experimental patch II
List pgsql-patches
Do we want this XML patch in the backend?  It needs syntax support so I
don't see how it could be done in /contrib.  Attached.

---------------------------------------------------------------------------

David Fetter wrote:
> On Wed, Sep 28, 2005 at 04:30:54PM +0200, Pavel Stehule wrote:
> > Hello
> >
> > base type changed to text, better registration xmlagg function
> >
> > Regards Pavel Stehule
>
> Now with some slightly improved documentation, works vs. CVS tip as of
> this writing.
>
> Cheers,
> D
> --
> David Fetter david@fetter.org http://fetter.org/
> phone: +1 510 893 6100   mobile: +1 415 235 3778
>
> Remember to vote!

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: explain analyze is your friend

--
  Bruce Momjian   http://candle.pha.pa.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.286
diff -c -r1.286 func.sgml
*** doc/src/sgml/func.sgml    16 Sep 2005 05:35:39 -0000    1.286
--- doc/src/sgml/func.sgml    2 Oct 2005 23:50:12 -0000
***************
*** 9707,9712 ****
--- 9707,9836 ----
     </para>

    </sect1>
+
+  <sect1 id="functions-sqlxml">
+   <title>SQL/XML public functions</title>
+
+   <sect2>
+    <title><literal>XMLAGG</literal></title>
+
+   <indexterm>
+    <primary>XMLAGG</primary>
+   </indexterm>
+
+ <synopsis>
+ <function>XMLAGG</function>(<replaceable>xml expr</replaceable>)
+ </synopsis>
+
+    <para>
+     This combines a collection of rows, each containing a single XML
+     value, to create a single value containing an XML forest.
+    </para>
+    </sect2>
+
+   <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 expr</replaceable><optional>, xml expr</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>,
XMLATTRIBUTES(<replaceable>value</replaceable><optional>AS <replaceable>label</replaceable></optional><optional>, ...
</optional>)</optional>
+ <optional>, xml expr list</optional>
+ <optional><replaceable>, value</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>(<replaceable>text</replaceable>)
+ </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 expr</replaceable>
+ <optional>, VERSION|ENCODING|STANDALONE = <replaceable>text<replaceable>, ... </optional>)
+ </synopsis>
+
+    <para>
+     Creates the root node of an XML document.
+    </para>
+    </sect2>
+
+   </sect1>
  </chapter>

  <!-- Keep this comment at the end of the file
Index: src/backend/executor/execQual.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/execQual.c,v
retrieving revision 1.180
diff -c -r1.180 execQual.c
*** src/backend/executor/execQual.c    26 Jun 2005 22:05:36 -0000    1.180
--- src/backend/executor/execQual.c    2 Oct 2005 23:50:15 -0000
***************
*** 53,59 ****
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/typcache.h"
!

  /* static function decls */
  static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
--- 53,60 ----
  #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/typcache.h"
! #include "lib/stringinfo.h"
! #include <string.h>

  /* static function decls */
  static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
***************
*** 111,116 ****
--- 112,119 ----
  static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
                 ExprContext *econtext,
                 bool *isNull, ExprDoneCond *isDone);
+ static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
+                 bool *isNull, ExprDoneCond *isDone);
  static Datum ExecEvalNullTest(GenericExprState *nstate,
                   ExprContext *econtext,
                   bool *isNull, ExprDoneCond *isDone);
***************
*** 218,223 ****
--- 221,228 ----
   * have to know the difference (that's what they need refattrlength for).
   *----------
   */
+
+
  static Datum
  ExecEvalArrayRef(ArrayRefExprState *astate,
                   ExprContext *econtext,
***************
*** 2304,2312 ****
          }
      }

!     return result;
  }

  /* ----------------------------------------------------------------
   *        ExecEvalNullIf
   *
--- 2309,2507 ----
          }
      }

!      return result;
! }
!
! /* ----------------------------------------------------------------
!  *        ExecEvalXml
!  * ----------------------------------------------------------------
!  */
!
! static char *
! getXmlParam(XmlParams *params, XmlParamOp op)
! {
!     if (params == NULL)
!         return NULL;
!     switch (op)
!     {
!         case IS_XMLNAME:
!             return params->name;
!         case IS_XMLVERSION:
!             return params->version;
!         case IS_XMLENCODING:
!             return params->encoding;
!         case IS_XMLSTANDALONE:
!             return params->standalone;
!     }
!     return NULL;
! }
!
! static void
! appendStringInfoText(StringInfo str, const text *t)
! {
!     appendBinaryStringInfo(str, VARDATA(t), VARSIZE(t) - VARHDRSZ);
! }
!
! 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->xml_args)
!                     {
!                         ExprState  *e = (ExprState *) lfirst(arg);
!                         Datum value = ExecEvalExpr(e, econtext, &isnull, NULL);
!                         if (!isnull)
!                         {
!                         appendStringInfoText(&buf, (text *)value);
!                         *isNull = false;
!                         }
!                     }
!                 }
!                 break;
!             case IS_XMLELEMENT:
!                 {
!                     appendStringInfo(&buf, "<%s",  getXmlParam(xmlExpr->params, IS_XMLNAME));
!                     int state = 0;
!                     int i = 0;
!                     foreach(arg, xmlExpr->nargs)
!                     {
!                         GenericExprState *gstate = (GenericExprState *) lfirst(arg);
!                         Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
!                         if (!isnull)
!                         {
!                                 char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->nargs_tcache[i], value));
!                                 appendStringInfo(&buf, " %s=\"%s\"", xmlExpr->nargs_ncache[i], outstr);
!                                 pfree(outstr);
!                         }
!                         i += 1;
!                     }
!                     foreach(arg, xmlExpr->xml_args)
!                     {
!                         ExprState  *e = (ExprState *) lfirst(arg);
!                         Datum value = ExecEvalExpr(e, econtext, &isnull, NULL);
!                         if (!isnull)
!                         {
!                             if (state == 0)
!                             {
!                                 appendStringInfoChar(&buf, '>');
!                                 state = 1;
!                             }
!                             appendStringInfoText(&buf,  (text *)value);
!                         }
!                     }
!                     if (xmlExpr->args)
!                     {
!                         ExprState *expr = linitial(xmlExpr->args);
!                         Datum value = ExecEvalExpr(expr, econtext, &isnull, NULL);
!
!                         if (!isnull)
!                         {
!                             char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeId, 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>",  getXmlParam(xmlExpr->params, IS_XMLNAME));
!
!                 }
!                 break;
!             case IS_XMLFOREST:
!                 {
!                     /* only if all argumets are null returns null */
!                     int i = 0; *isNull = true;
!                     foreach(arg, xmlExpr->nargs)
!                     {
!                         GenericExprState *gstate = (GenericExprState *) lfirst(arg);
!                         Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
!                         if (!isnull)
!                         {
!                                 char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->nargs_tcache[i], value));
!                                 appendStringInfo(&buf, "<%s>%s</%s>",  xmlExpr->nargs_ncache[i], outstr,
xmlExpr->nargs_ncache[i]);                                
!                                 pfree(outstr);
!                                 *isNull = false;
!                         }
!                         i += 1;
!                     }
!                 }
!                 break;
!             case IS_XMLCOMMENT:
!             case IS_XMLPI:
!                 {
!                     bool isnull;
!                     ExprState *arg = linitial(xmlExpr->args);
!                     Datum value = ExecEvalExpr(arg, econtext, &isnull, NULL);
!                     char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeId, value));
!                     if (xmlExpr->op == IS_XMLCOMMENT)
!                             appendStringInfo(&buf, "<-- %s -->",  outstr);
!                     if (xmlExpr->op == IS_XMLPI)
!                         appendStringInfo(&buf, "<? %s ?>",  outstr);
!                     pfree(outstr);
!                 }
!                 break;
!             case IS_XMLROOT:
!                 {
!                     ExprState *xarg = linitial(xmlExpr->xml_args);
!                     Datum value = ExecEvalExpr(xarg, econtext, &isnull, NULL);
!
!                     appendStringInfo(&buf,"<?xml");
!                     if (getXmlParam(xmlExpr->params, IS_XMLVERSION))
!                         appendStringInfo(&buf, " version=\"%s\"", getXmlParam(xmlExpr->params, IS_XMLVERSION));
!                     if (getXmlParam(xmlExpr->params, IS_XMLENCODING))
!                         appendStringInfo(&buf, " encoding=\"%s\"", getXmlParam(xmlExpr->params,IS_XMLENCODING));
!                     if (getXmlParam(xmlExpr->params, IS_XMLSTANDALONE))
!                         appendStringInfo(&buf, " standalone=\"%s\"", getXmlParam(xmlExpr->params,IS_XMLSTANDALONE));
!                     appendStringInfo(&buf, "?>");
!                     appendStringInfoText(&buf, (text *) value);
!                 }
!                 break;
!             case IS_XMLSERIALIZE:
!                 {
!                     ExprState  *arg = linitial(xmlExpr->xml_args);
!                     Datum value = ExecEvalExpr(arg, econtext, isNull, NULL);
!                     PG_RETURN_TEXT_P(value);
!                 }
!                 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);
!
  }

+
  /* ----------------------------------------------------------------
   *        ExecEvalNullIf
   *
***************
*** 3296,3301 ****
--- 3491,3565 ----
                  state = (ExprState *) mstate;
              }
              break;
+         case T_XmlExpr:
+             {
+                 List *outlist; ListCell *arg;
+                 XmlExpr *xexpr = (XmlExpr *) node;
+                 XmlExprState *xstate = makeNode(XmlExprState);
+                 int i = 0; Oid typid;
+
+                 xstate->level = xexpr->level;
+                 xstate->params = xexpr->params;
+
+                 xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
+                 xstate->op = xexpr->op;
+
+                 outlist = NIL;
+                 if (xexpr->nargs)
+                 {
+                     xstate->nargs_tcache = (int*)palloc(list_length(xexpr->nargs)*sizeof(int));
+                     xstate->nargs_ncache = (char**)palloc(list_length(xexpr->nargs)*sizeof(char*));
+
+                     i = 0;
+                     foreach(arg, xexpr->nargs)
+                     {
+                         bool tpisvarlena;
+                         Expr *e = (Expr *) lfirst(arg);
+                         ExprState *estate = ExecInitExpr(e, parent);
+
+                         outlist = lappend(outlist, estate);
+                         TargetEntry *tle = (TargetEntry *) ((GenericExprState *) estate)->xprstate.expr;
+                         getTypeOutputInfo(exprType((Node *)tle->expr), &typid, &tpisvarlena);
+                         xstate->nargs_ncache[i] = tle->resname;
+                         xstate->nargs_tcache[i++] = typid;
+                     }
+                 }
+                 else
+                 {
+                     xstate->nargs_tcache = NULL;
+                     xstate->nargs_ncache = NULL;
+                 }
+                 xstate->nargs = outlist;
+
+                 outlist = NIL;
+                 if (xexpr->xml_args)
+                 {
+                     foreach(arg, xexpr->xml_args)
+                     {
+                         Expr *e = (Expr *) lfirst(arg);
+                         ExprState *estate = ExecInitExpr(e, parent);
+
+                         outlist = lappend(outlist, estate);
+                     }
+                 }
+                 xstate->xml_args = outlist;
+
+                 outlist = NIL;
+                 foreach(arg, xexpr->args)
+                 {
+                     bool tpisvarlena;
+                     Expr *e = (Expr *) lfirst(arg);
+                     getTypeOutputInfo(exprType((Node *)e), &typid, &tpisvarlena);
+                     ExprState *estate = ExecInitExpr(e, parent);
+                     outlist = lappend(outlist, estate);
+                 }
+                 xstate->arg_typeId = typid;
+                 xstate->args = outlist;
+
+                 state = (ExprState *) xstate;
+             }
+             break;
+
          case T_NullIfExpr:
              {
                  NullIfExpr *nullifexpr = (NullIfExpr *) node;
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.315
diff -c -r1.315 copyfuncs.c
*** src/backend/nodes/copyfuncs.c    1 Aug 2005 20:31:08 -0000    1.315
--- src/backend/nodes/copyfuncs.c    2 Oct 2005 23:50:17 -0000
***************
*** 1063,1068 ****
--- 1063,1098 ----
  }

  /*
+  * _copyXmlExpr
+  */
+
+ static XmlParams *
+ _copyXmlParams(XmlParams *from)
+ {
+     XmlParams *newnode = makeNode(XmlParams);
+     COPY_STRING_FIELD(name);
+     COPY_STRING_FIELD(version);
+     COPY_STRING_FIELD(encoding);
+     COPY_STRING_FIELD(standalone);
+
+     return newnode;
+ }
+
+ static XmlExpr *
+ _copyXmlExpr(XmlExpr *from)
+ {
+     XmlExpr *newnode = makeNode(XmlExpr);
+     COPY_SCALAR_FIELD(op);
+     COPY_NODE_FIELD(xml_args);
+     COPY_NODE_FIELD(nargs);
+     COPY_NODE_FIELD(args);
+     COPY_NODE_FIELD(params);
+     COPY_SCALAR_FIELD(level);
+
+     return newnode;
+ }
+
+ /*
   * _copyNullIfExpr (same as OpExpr)
   */
  static NullIfExpr *
***************
*** 2843,2848 ****
--- 2873,2884 ----
          case T_MinMaxExpr:
              retval = _copyMinMaxExpr(from);
              break;
+         case T_XmlParams:
+             retval = _copyXmlParams(from);
+             break;
+         case T_XmlExpr:
+             retval = _copyXmlExpr(from);
+             break;
          case T_NullIfExpr:
              retval = _copyNullIfExpr(from);
              break;
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.252
diff -c -r1.252 equalfuncs.c
*** src/backend/nodes/equalfuncs.c    1 Aug 2005 20:31:08 -0000    1.252
--- src/backend/nodes/equalfuncs.c    2 Oct 2005 23:50:18 -0000
***************
*** 460,465 ****
--- 460,488 ----
      return true;
  }

+
+ static bool
+ _equalXmlParams(XmlParams *a, XmlParams *b)
+ {
+     COMPARE_STRING_FIELD(name);
+     COMPARE_STRING_FIELD(version);
+     COMPARE_STRING_FIELD(encoding);
+     COMPARE_STRING_FIELD(standalone);
+ }
+
+ static bool
+ _equalXmlExpr(XmlExpr *a, XmlExpr *b)
+ {
+     COMPARE_SCALAR_FIELD(op);
+     COMPARE_NODE_FIELD(xml_args);
+     COMPARE_NODE_FIELD(args);
+     COMPARE_NODE_FIELD(nargs);
+     COMPARE_NODE_FIELD(params);
+     COMPARE_SCALAR_FIELD(level);
+
+     return true;
+ }
+
  static bool
  _equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
  {
***************
*** 1899,1904 ****
--- 1922,1933 ----
          case T_MinMaxExpr:
              retval = _equalMinMaxExpr(a, b);
              break;
+         case T_XmlParams:
+             retval = _equalXmlParams(a, b);
+             break;
+         case T_XmlExpr:
+             retval = _equalXmlExpr(a, b);
+             break;
          case T_NullIfExpr:
              retval = _equalNullIfExpr(a, b);
              break;
Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.260
diff -c -r1.260 outfuncs.c
*** src/backend/nodes/outfuncs.c    27 Aug 2005 22:13:43 -0000    1.260
--- src/backend/nodes/outfuncs.c    2 Oct 2005 23:50:19 -0000
***************
*** 875,880 ****
--- 875,904 ----
  }

  static void
+ _outXmlParams(StringInfo str, XmlParams *node)
+ {
+     WRITE_NODE_TYPE("XMLPARAMS");
+
+     WRITE_STRING_FIELD(name);
+     WRITE_STRING_FIELD(encoding);
+     WRITE_STRING_FIELD(version);
+     WRITE_STRING_FIELD(standalone);
+ }
+
+ static void
+ _outXmlExpr(StringInfo str, XmlExpr *node)
+ {
+     WRITE_NODE_TYPE("XMLEXPR");
+
+     WRITE_ENUM_FIELD(op, XmlExprOp);
+     WRITE_NODE_FIELD(xml_args);
+     WRITE_NODE_FIELD(nargs);
+     WRITE_NODE_FIELD(args);
+     WRITE_NODE_FIELD(params);
+     WRITE_INT_FIELD(level);
+ }
+
+ static void
  _outNullIfExpr(StringInfo str, NullIfExpr *node)
  {
      WRITE_NODE_TYPE("NULLIFEXPR");
***************
*** 1925,1930 ****
--- 1949,1957 ----
              case T_MinMaxExpr:
                  _outMinMaxExpr(str, obj);
                  break;
+             case T_XmlExpr:
+                 _outXmlExpr(str, obj);
+                 break;
              case T_NullIfExpr:
                  _outNullIfExpr(str, obj);
                  break;
Index: src/backend/nodes/readfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/readfuncs.c,v
retrieving revision 1.181
diff -c -r1.181 readfuncs.c
*** src/backend/nodes/readfuncs.c    1 Aug 2005 20:31:08 -0000    1.181
--- src/backend/nodes/readfuncs.c    2 Oct 2005 23:50:20 -0000
***************
*** 81,87 ****

  /* Read a float field */
  #define READ_FLOAT_FIELD(fldname) \
!     token = pg_strtok(&length);        /* skip :fldname */ \
      token = pg_strtok(&length);        /* get field value */ \
      local_node->fldname = atof(token)

--- 81,87 ----

  /* Read a float field */
  #define READ_FLOAT_FIELD(fldname) \
!         /* skip :fldname */ \
      token = pg_strtok(&length);        /* get field value */ \
      local_node->fldname = atof(token)

***************
*** 674,679 ****
--- 674,707 ----
      READ_DONE();
  }

+ static XmlParams *
+ _readXmlParams(void)
+ {
+     READ_LOCALS(XmlParams);
+
+     READ_STRING_FIELD(name);
+     READ_STRING_FIELD(encoding);
+     READ_STRING_FIELD(version);
+     READ_STRING_FIELD(standalone);
+
+     READ_DONE();
+ }
+
+ static XmlExpr *
+ _readXmlExpr(void)
+ {
+     READ_LOCALS(XmlExpr);
+
+     READ_ENUM_FIELD(op, XmlExprOp);
+     READ_NODE_FIELD(xml_args);
+     READ_NODE_FIELD(nargs);
+     READ_NODE_FIELD(args);
+     READ_NODE_FIELD(params);
+     READ_INT_FIELD(level);
+
+     READ_DONE();
+ }
+
  /*
   * _readNullIfExpr
   */
***************
*** 1000,1005 ****
--- 1028,1037 ----
          return_value = _readCoalesceExpr();
      else if (MATCH("MINMAX", 6))
          return_value = _readMinMaxExpr();
+     else if (MATCH("XMLPARAMS", 9))
+         return_value = _readXmlParams();
+     else if (MATCH("XMLEXPR", 7))
+         return_value = _readXmlExpr();
      else if (MATCH("NULLIFEXPR", 10))
          return_value = _readNullIfExpr();
      else if (MATCH("NULLTEST", 8))
Index: src/backend/optimizer/util/clauses.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v
retrieving revision 1.200
diff -c -r1.200 clauses.c
*** src/backend/optimizer/util/clauses.c    3 Jul 2005 21:14:17 -0000    1.200
--- src/backend/optimizer/util/clauses.c    2 Oct 2005 23:50:22 -0000
***************
*** 546,551 ****
--- 546,553 ----
          return false;
      if (IsA(node, NullIfExpr))
          return false;
+     if (IsA(node, XmlExpr))
+         return false;

      return expression_tree_walker(node, expression_returns_set_walker,
                                    context);
***************
*** 853,858 ****
--- 855,862 ----
          return true;
      if (IsA(node, NullIfExpr))
          return true;
+     if (IsA(node, XmlExpr))
+         return true;
      if (IsA(node, NullTest))
          return true;
      if (IsA(node, BooleanTest))
***************
*** 2944,2949 ****
--- 2948,2964 ----
              return walker(((MinMaxExpr *) node)->args, context);
          case T_NullIfExpr:
              return walker(((NullIfExpr *) node)->args, context);
+         case T_XmlExpr:
+             {
+                 XmlExpr *xexpr = (XmlExpr *) node;
+                 if (walker(xexpr->nargs, context))
+                     return true;
+                 if (walker(xexpr->xml_args, context))
+                     return true;
+                 if (walker(xexpr->args, context))
+                     return true;
+             }
+             break;
          case T_NullTest:
              return walker(((NullTest *) node)->arg, context);
          case T_BooleanTest:
***************
*** 3422,3427 ****
--- 3437,3454 ----
                  return (Node *) newnode;
              }
              break;
+         case T_XmlExpr:
+             {
+                 XmlExpr *xexpr = (XmlExpr *) node;
+                 XmlExpr *newnode;
+
+                 FLATCOPY(newnode, xexpr, XmlExpr);
+                 MUTATE(newnode->nargs, xexpr->nargs, List *);
+                 MUTATE(newnode->xml_args, xexpr->xml_args, List *);
+                 MUTATE(newnode->args, xexpr->args, List *);
+                 return (Node *) newnode;
+             }
+             break;
          case T_NullTest:
              {
                  NullTest   *ntest = (NullTest *) node;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.511
diff -c -r2.511 gram.y
*** src/backend/parser/gram.y    23 Sep 2005 22:25:25 -0000    2.511
--- src/backend/parser/gram.y    2 Oct 2005 23:50:28 -0000
***************
*** 91,96 ****
--- 91,101 ----
                                  Node *limitOffset, Node *limitCount);
  static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
  static Node *doNegate(Node *n);
+ static XmlExpr *makeXmlExpr(XmlExprOp op, char *name,
+                             List *xml_attr, List *xml_args,
+                             List *args, XmlParams *params);
+ static XmlParams *setXmlParam(XmlParams *params, XmlParamOp op, char *value);
+
  static void doNegateFloat(Value *v);

  %}
***************
*** 128,133 ****
--- 133,141 ----

      InsertStmt            *istmt;
      VariableSetStmt        *vsetstmt;
+     XmlExpr            *xmlexpr;
+     XmlParams        *xmlparams;
+     XmlParam        xmlparam;
  }

  %type <node>    stmt schema_stmt
***************
*** 325,330 ****
--- 333,345 ----
  %type <boolean> constraints_set_mode
  %type <str>        OptTableSpace OptConsTableSpace OptTableSpaceOwner

+ %type <target>    n_expr_el
+ %type <xmlexpr> xmlexpr xml_args
+ %type <list>    xmlexpr_list n_expr_list
+ %type <xmlparams> xmlroot_par_list
+ %type <xmlparam> xmlroot_param
+
+

  /*
   * If you make any token changes, update the keyword table in
***************
*** 377,383 ****

      MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE

!     NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
      NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
      NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC

--- 392,398 ----

      MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE

!     NAME NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
      NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
      NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC

***************
*** 398,404 ****
      SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
      SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
      STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
!     SYSID SYSTEM_P

      TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
      TO TOAST TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
--- 413,419 ----
      SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
      SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
      STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
!     SYSID SYSTEM_P STANDALONE

      TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
      TO TOAST TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
***************
*** 408,416 ****
      UPDATE USER USING

      VACUUM VALID VALIDATOR VALUES VARCHAR VARYING
!     VERBOSE VIEW VOLATILE

      WHEN WHERE WITH WITHOUT WORK WRITE

      YEAR_P

--- 423,434 ----
      UPDATE USER USING

      VACUUM VALID VALIDATOR VALUES VARCHAR VARYING
!     VERBOSE VERSION VIEW VOLATILE

      WHEN WHERE WITH WITHOUT WORK WRITE
+
+     XMLAGG XMLATTRIBUTES XMLCOMMENT XMLCONCAT XMLELEMENT XMLFOREST
+     XMLPI XMLROOT XMLSERIALIZE

      YEAR_P

***************
*** 7408,7413 ****
--- 7426,7560 ----
                      v->op = IS_LEAST;
                      $$ = (Node *)v;
                  }
+             | XMLSERIALIZE '(' xmlexpr ')'
+                 {
+                     $$ = (Node *)
+                         makeXmlExpr(IS_XMLSERIALIZE, NULL, NULL, list_make1($3), NULL, NULL);
+                 }
+         ;
+
+ /*
+  *  Supporting SQL/XML functions, use only for publishing. For storing results
+  *  to tables and using them in pub. functions is neccessery support xml datatype,
+  *  one part of xmlexpr will be col with xml value.
+  */
+
+ xmlexpr:        XMLAGG '(' a_expr ')' /* for nested xmlagg */
+                 {
+                     $$ = makeXmlExpr(IS_XMLAGG, NULL, NULL, NULL, list_make1($3), NULL);
+                 }
+             | XMLAGG '(' xmlexpr ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLAGG, NULL, NULL, list_make1($3), NULL, NULL);
+                 }
+             | XMLCOMMENT '(' a_expr ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLCOMMENT, NULL, NULL, NULL, list_make1($3), NULL);
+                 }
+             | XMLCONCAT '(' xmlexpr_list ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NULL, $3, NULL, NULL);
+                 }
+             | XMLELEMENT '(' NAME ColLabel ',' xml_args ')'
+                 {
+                     $6->params = setXmlParam($6->params, IS_XMLNAME, $4);
+                     $6->op = IS_XMLELEMENT;
+                     $$ = $6;
+                 }
+             | XMLELEMENT '(' NAME ColLabel ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, NULL, NULL, NULL);
+                 }
+
+             | XMLELEMENT '(' NAME ColLabel ',' XMLATTRIBUTES '(' n_expr_list ')' ',' xml_args ')'
+                 {
+                     $11->params = setXmlParam($11->params, IS_XMLNAME, $4);
+                     $11->nargs = $8;
+                     $11->op = IS_XMLELEMENT;
+                     $$ = $11;
+                 }
+             | XMLELEMENT '(' NAME ColLabel ',' XMLATTRIBUTES '(' n_expr_list ')' ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLELEMENT, $4, $8, NULL, NULL, NULL);
+                 }
+             | XMLFOREST '(' n_expr_list ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NULL, NULL, NULL);
+                 }
+             | XMLPI '(' a_expr ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLPI, NULL, NULL, NULL, list_make1($3), NULL);
+                 }
+             | XMLROOT '(' xmlexpr ',' xmlroot_par_list ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLROOT, NULL, NULL, list_make1($3), NULL, $5);
+                 }
+             | XMLROOT '(' xmlexpr ')'
+                 {
+                     $$ = makeXmlExpr(IS_XMLROOT, NULL, NULL, list_make1($3), NULL, NULL);
+                 }
+         ;
+
+
+ xmlroot_par_list:    xmlroot_param                    { $$ = setXmlParam(NULL, $1.op, $1.value); }
+             | xmlroot_par_list ',' xmlroot_param         { $$ = setXmlParam($1, $3.op, $3.value); }
+         ;
+
+
+ xmlroot_param:        VERSION Sconst
+                 {
+                     $$.op = IS_XMLVERSION;
+                     $$.value = $2;
+                 }
+             | ENCODING Sconst
+                 {
+                     $$.op = IS_XMLENCODING;
+                     $$.value = $2;
+                 }
+             | STANDALONE Sconst
+                 {
+                     $$.op = IS_XMLSTANDALONE;
+                     $$.value = $2;
+                 }
+         ;
+
+ xml_args:        xmlexpr_list ',' a_expr
+                 {
+                     $$ = makeXmlExpr(IS_XMLUNKNOWN, NULL, NULL, $1, list_make1($3), NULL);
+                 }
+             | a_expr
+                 {
+                     $$ = makeXmlExpr(IS_XMLUNKNOWN, NULL, NULL, NULL, list_make1($1), NULL);
+                 }
+             | xmlexpr_list
+                 {
+                     $$ = makeXmlExpr(IS_XMLUNKNOWN, NULL, NULL, $1, NULL, NULL);
+                 }
+         ;
+
+ xmlexpr_list:        xmlexpr                    { $$ = list_make1($1); }
+             | xmlexpr_list ',' xmlexpr        { $$ = lappend($1, $3); }
+         ;
+
+ n_expr_list:        n_expr_el                { $$ = list_make1($1); }
+             | n_expr_list ',' n_expr_el        { $$ = lappend($1, $3); }
+         ;
+
+ n_expr_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;
+                 }
          ;

  /*
***************
*** 7770,7775 ****
--- 7917,7936 ----
                      $$->indirection = NIL;
                      $$->val = (Node *)n;
                  }
+             | xmlexpr AS ColLabel
+                 {
+                     $$ = makeNode(ResTarget);
+                     $$->name = $3;
+                     $$->indirection = NIL;
+                     $$->val = (Node *)$1;
+                 }
+             | xmlexpr
+                 {
+                     $$ = makeNode(ResTarget);
+                     $$->name = NULL;
+                     $$->indirection = NIL;
+                     $$->val = (Node *)$1;
+                 }
          ;

  update_target_list:
***************
*** 8240,8245 ****
--- 8401,8407 ----
              | SHOW
              | SIMPLE
              | STABLE
+             | STANDALONE
              | START
              | STATEMENT
              | STATISTICS
***************
*** 8279,8284 ****
--- 8441,8448 ----
              | WRITE
              | YEAR_P
              | ZONE
+             | NAME
+             | VERSION
          ;

  /* Column identifier --- keywords that can be column, table, etc names.
***************
*** 8329,8334 ****
--- 8493,8507 ----
              | TREAT
              | TRIM
              | VARCHAR
+             | XMLAGG
+             | XMLATTRIBUTES
+             | XMLELEMENT
+             | XMLCOMMENT
+             | XMLCONCAT
+             | XMLFOREST
+             | XMLROOT
+             | XMLSERIALIZE
+             | XMLPI
          ;

  /* Function identifier --- keywords that can be function names.
***************
*** 8914,8917 ****
--- 9087,9138 ----
      }
  }

+ static XmlParams *
+ setXmlParam(XmlParams *params, XmlParamOp op, char *value)
+ {
+     if (value == NULL)
+         return params;
+
+     if (params == NULL)
+     {
+         params = makeNode(XmlParams);
+         params->encoding = NULL;
+         params->name = NULL;
+         params->version = NULL;
+         params->standalone = NULL;
+     }
+     switch (op)
+     {
+         case IS_XMLENCODING:
+             params->encoding = value;
+             break;
+         case IS_XMLVERSION:
+             params->version = value;
+             break;
+         case IS_XMLNAME:
+             params->name = value;
+             break;
+         case IS_XMLSTANDALONE:
+             params->standalone = value;
+             break;
+     }
+     return params;
+ }
+
+ static XmlExpr *
+ makeXmlExpr(XmlExprOp op, char *name, List *nargs, List *xml_args,
+     List *args, XmlParams *params)
+ {
+
+     XmlExpr *x = makeNode(XmlExpr);
+     x->op = op;
+     x->nargs = nargs;
+     x->xml_args = xml_args;
+     x->args = args;
+     x->level = 0;
+     x->params = setXmlParam(params, IS_XMLNAME, name);
+     return x;
+ }
+
+
  #include "scan.c"
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.165
diff -c -r1.165 keywords.c
*** src/backend/parser/keywords.c    23 Aug 2005 22:40:27 -0000    1.165
--- src/backend/parser/keywords.c    2 Oct 2005 23:50:28 -0000
***************
*** 213,218 ****
--- 213,219 ----
      {"mode", MODE},
      {"month", MONTH_P},
      {"move", MOVE},
+     {"name", NAME},
      {"names", NAMES},
      {"national", NATIONAL},
      {"natural", NATURAL},
***************
*** 306,311 ****
--- 307,313 ----
      {"smallint", SMALLINT},
      {"some", SOME},
      {"stable", STABLE},
+     {"standalone", STANDALONE},
      {"start", START},
      {"statement", STATEMENT},
      {"statistics", STATISTICS},
***************
*** 354,359 ****
--- 356,362 ----
      {"varchar", VARCHAR},
      {"varying", VARYING},
      {"verbose", VERBOSE},
+     {"version", VERSION},
      {"view", VIEW},
      {"volatile", VOLATILE},
      {"when", WHEN},
***************
*** 362,367 ****
--- 365,379 ----
      {"without", WITHOUT},
      {"work", WORK},
      {"write", WRITE},
+     {"xmlagg", XMLAGG},
+     {"xmlattributes", XMLATTRIBUTES},
+     {"xmlcomment", XMLCOMMENT},
+     {"xmlconcat", XMLCONCAT},
+     {"xmlelement", XMLELEMENT},
+     {"xmlforest", XMLFOREST},
+     {"xmlpi", XMLPI},
+     {"xmlroot", XMLROOT},
+     {"xmlserialize", XMLSERIALIZE},
      {"year", YEAR_P},
      {"zone", ZONE},
  };
Index: src/backend/parser/parse_expr.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.184
diff -c -r1.184 parse_expr.c
*** src/backend/parser/parse_expr.c    26 Jun 2005 22:05:39 -0000    1.184
--- src/backend/parser/parse_expr.c    2 Oct 2005 23:50:30 -0000
***************
*** 54,59 ****
--- 54,60 ----
  static Node *transformRowExpr(ParseState *pstate, RowExpr *r);
  static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
  static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
+ static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x);
  static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
  static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
  static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
***************
*** 70,75 ****
--- 71,77 ----
  static Expr *make_distinct_op(ParseState *pstate, List *opname,
                   Node *ltree, Node *rtree);

+ extern char *FigureColname(Node *e);

  /*
   * transformExpr -
***************
*** 213,219 ****
          case T_MinMaxExpr:
              result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
              break;
!
          case T_NullTest:
              {
                  NullTest   *n = (NullTest *) expr;
--- 215,225 ----
          case T_MinMaxExpr:
              result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
              break;
!
!         case T_XmlExpr:
!             result = transformXmlExpr(pstate, (XmlExpr *) expr);
!             break;
!
          case T_NullTest:
              {
                  NullTest   *n = (NullTest *) expr;
***************
*** 1272,1277 ****
--- 1278,1382 ----
      return (Node *) newm;
  }

+
+ static Node *
+ transformList(ParseState *pstate, List *list)
+ {
+     List *newlist = NIL;
+     ListCell *arg;
+     foreach(arg, list)
+     {
+             Node *e = (Node*)lfirst(arg);
+         Node *te = transformExpr(pstate, e);
+         newlist = lappend(newlist, te);
+     }
+     return (Node *)newlist;
+ }
+
+ static Node *
+ transformXmlList(ParseState *pstate, List *list, int level)
+ {
+     List *newlist = NIL;
+     ListCell *arg;
+     foreach(arg, list)
+     {
+             Node *e = (Node*)lfirst(arg);
+         ((XmlExpr *)e)->level = level;
+         Node *te = transformExpr(pstate, e);
+         newlist = lappend(newlist, te);
+     }
+     return (Node *)newlist;
+ }
+
+
+ /* transformation named expressions */
+
+ static Node *
+ transformNPList(ParseState *pstate, List *list)
+ {
+     List *newlist = NIL;
+     ListCell *arg;
+     foreach(arg, list)
+     {
+         ResTarget *r = (ResTarget *) lfirst(arg);
+         Node *expr = transformExpr(pstate, r->val);
+         char *colname = r->name;
+         if (colname == NULL)
+         colname = FigureColname(r->val);
+         newlist = lappend(newlist,
+                     makeTargetEntry((Expr *) expr, 0, colname, false));
+     }
+     return (Node *)newlist;
+ }
+
+ static Node *
+ transformXmlExpr(ParseState *pstate, XmlExpr *x)
+ {
+     XmlExpr *newx = makeNode(XmlExpr);
+
+     if (x->op == IS_XMLAGG)
+     {
+         /* set level */
+         if (x->xml_args)
+         {
+             XmlExpr *p = (XmlExpr *) linitial(x->xml_args);
+             p->level = x->level + 1;
+
+             FuncCall *n = makeNode(FuncCall);
+             n->funcname = SystemFuncName("xmlagg");
+             n->args = x->xml_args;
+             n->agg_star = FALSE;
+             n->agg_distinct = FALSE;
+             return transformExpr(pstate, (Node *) n);
+
+         } else
+         {
+             FuncCall *n = makeNode(FuncCall);
+             n->funcname = SystemFuncName("xmlagg");
+             n->args = x->args;
+             n->agg_star = FALSE;
+             n->agg_distinct = FALSE;
+
+             return transformExpr(pstate, (Node *) n);
+
+         }
+     }
+
+
+     /* Mechanismem transformace dokazu vnutit podrizenym xmlfunkcim level,
+      * v budoucnu napriklad ukazatel na hash s tagy a attributy */
+
+     newx->nargs = (List *)transformNPList(pstate, x->nargs);
+     newx->xml_args = (List *)transformXmlList(pstate, x->xml_args, x->level+1);
+         newx->args = (List *)transformList(pstate, x->args);
+
+     newx->params = x->params;
+     newx->op = x->op;
+     newx->level = x->level;
+
+     return (Node *) newx;
+ }
+
  static Node *
  transformBooleanTest(ParseState *pstate, BooleanTest *b)
  {
***************
*** 1549,1554 ****
--- 1654,1662 ----
          case T_MinMaxExpr:
              type = ((MinMaxExpr *) expr)->minmaxtype;
              break;
+         case T_XmlExpr:
+             type = TEXTOID;
+             break;
          case T_NullIfExpr:
              type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
              break;
Index: src/backend/parser/parse_target.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_target.c,v
retrieving revision 1.137
diff -c -r1.137 parse_target.c
*** src/backend/parser/parse_target.c    26 Jun 2005 22:05:40 -0000    1.137
--- src/backend/parser/parse_target.c    2 Oct 2005 23:50:30 -0000
***************
*** 1135,1140 ****
--- 1135,1173 ----
                      return 2;
              }
              break;
+         case T_XmlExpr:
+             /* make SQL/XML functions act like a regular function */
+             switch (((XmlExpr*) node)->op)
+             {
+                 case IS_XMLCOMMENT:
+                     *name = "xmlcomment";
+                     return 2;
+                 case IS_XMLCONCAT:
+                     *name = "xmlconcat";
+                     return 2;
+                 case IS_XMLELEMENT:
+                     *name = "xmlelement";
+                     return 2;
+                 case IS_XMLFOREST:
+                     *name = "xmlforest";
+                     return 2;
+                 case IS_XMLPI:
+                     *name = "xmlpi";
+                     return 2;
+                 case IS_XMLROOT:
+                     *name = "xmlroot";
+                     return 2;
+                 case IS_XMLSERIALIZE:
+                     *name = "xmlserialize";
+                     return 2;
+                 case IS_XMLUNKNOWN:
+                     *name = "unknown xml function";
+                     return 2;
+                 case IS_XMLAGG:
+                     *name = "xmlagg";
+                     return 2;
+             }
+             break;
          default:
              break;
      }
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.205
diff -c -r1.205 ruleutils.c
*** src/backend/utils/adt/ruleutils.c    1 Aug 2005 20:31:12 -0000    1.205
--- src/backend/utils/adt/ruleutils.c    2 Oct 2005 23:50:34 -0000
***************
*** 2793,2798 ****
--- 2793,2799 ----
          case T_CoalesceExpr:
          case T_MinMaxExpr:
          case T_NullIfExpr:
+         case T_XmlExpr:
          case T_Aggref:
          case T_FuncExpr:
              /* function-like: name(..) or name[..] */
***************
*** 2901,2906 ****
--- 2902,2908 ----
                  case T_CoalesceExpr:    /* own parentheses */
                  case T_MinMaxExpr:        /* own parentheses */
                  case T_NullIfExpr:        /* other separators */
+                 case T_XmlExpr:            /* own parentheses */
                  case T_Aggref:            /* own parentheses */
                  case T_CaseExpr:        /* other separators */
                      return true;
***************
*** 2949,2954 ****
--- 2951,2957 ----
                  case T_CoalesceExpr:    /* own parentheses */
                  case T_MinMaxExpr:        /* own parentheses */
                  case T_NullIfExpr:        /* other separators */
+                 case T_XmlExpr:            /* own parentheses */
                  case T_Aggref:            /* own parentheses */
                  case T_CaseExpr:        /* other separators */
                      return true;
***************
*** 3531,3537 ****
                  appendStringInfoChar(buf, ')');
              }
              break;
!
          case T_NullTest:
              {
                  NullTest   *ntest = (NullTest *) node;
--- 3534,3576 ----
                  appendStringInfoChar(buf, ')');
              }
              break;
!
!         case T_XmlExpr:
!             {
!                 XmlExpr *xexpr = (XmlExpr *) node;
!                 switch (xexpr->op)
!                 {
!                     case IS_XMLCOMMENT:
!                         appendStringInfo(buf,"XMLCOMMENT(");
!                         break;
!                     case IS_XMLCONCAT:
!                         appendStringInfo(buf,"XMLCONCAT(");
!                         break;
!                     case IS_XMLELEMENT:
!                         appendStringInfo(buf,"XMLELEMENT(");
!                         break;
!                     case IS_XMLFOREST:
!                         appendStringInfo(buf,"XMLFOREST(");
!                         break;
!                     case IS_XMLPI:
!                         appendStringInfo(buf,"XMLPI(");
!                         break;
!                     case IS_XMLROOT:
!                         appendStringInfo(buf,"XMLROOT(");
!                         break;
!                     case IS_XMLSERIALIZE:
!                         appendStringInfo(buf,"XMLSERIALIZE(");
!                         break;
!                     case IS_XMLUNKNOWN:  /* quite compiler warnings */
!                         break;
!                 }
!                 get_rule_expr((Node *) xexpr->nargs, context, true);
!                 get_rule_expr((Node *) xexpr->xml_args, context, true);
!                 get_rule_expr((Node *) xexpr->args, context, true);
!                 appendStringInfoChar(buf, ')');
!             }
!             break;
!
          case T_NullTest:
              {
                  NullTest   *ntest = (NullTest *) node;
Index: src/backend/utils/adt/varchar.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/varchar.c,v
retrieving revision 1.112
diff -c -r1.112 varchar.c
*** src/backend/utils/adt/varchar.c    29 Jul 2005 12:59:15 -0000    1.112
--- src/backend/utils/adt/varchar.c    2 Oct 2005 23:50:34 -0000
***************
*** 25,30 ****
--- 25,31 ----

  #include "mb/pg_wchar.h"

+ #include "nodes/execnodes.h"

  /*
   * CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
***************
*** 805,807 ****
--- 806,896 ----

      return result;
  }
+
+ /*
+  * Temp. aux. func for xmlagg function
+  *
+  */
+
+
+ typedef struct
+ {
+   int32 size;  // varlena requirment
+   int max;
+   int offset;
+   bool isNull;
+   char data[1];
+ } data;
+
+
+ static data *
+ makeData(AggState *aggstate, int sz)
+ {
+     data *d = (data *) MemoryContextAlloc(aggstate->aggcontext, sz+sizeof(data));
+     d->size = sz+sizeof(data);
+     d->max = sz;
+     d->offset = 0;
+     d->data[0] = '\0';
+     d->isNull = true;
+     return d;
+ }
+
+ static data *
+ reallocData(AggState *aggstate, data *d, int sz)
+ {
+     data *nd = makeData(aggstate, sz);
+     memcpy(nd->data, d->data, d->offset);
+     nd->offset = d->offset;
+     nd->isNull = d->isNull;
+     return nd;
+ }
+
+
+ Datum
+ text_xmlagg_accum(PG_FUNCTION_ARGS)
+ {
+     data *d;
+     if (PG_ARGISNULL(0))
+         d = NULL;
+     else
+         d = (data *) PG_GETARG_POINTER(0);
+     if (!d)
+         d = makeData((AggState *) fcinfo->context, 1000);
+
+     if (!PG_ARGISNULL(1))
+     {
+         text *str = PG_GETARG_TEXT_P(1);
+         d->isNull = false;
+         int len = VARSIZE(str) - VARHDRSZ;
+         while (d->max < d->offset + len)
+         {
+                 int nmax = d->max *2;
+                 data *dn = reallocData((AggState *) fcinfo->context, d, nmax);
+                 d = dn;
+         }
+         memcpy(&d->data[d->offset], VARDATA(str), len);
+         d->offset += len;
+     }
+
+   PG_RETURN_POINTER(d);
+ }
+
+ Datum
+ text_xmlagg(PG_FUNCTION_ARGS)
+ {
+     data *d;
+
+     if (PG_ARGISNULL(0))
+         elog(ERROR, "internal error");
+
+     d = (data *) PG_GETARG_POINTER(0);
+     if (d->isNull)
+         PG_RETURN_NULL();
+     else
+     {
+         text *str = palloc(d->offset+VARHDRSZ);
+         VARATT_SIZEP(str) = d->offset+VARHDRSZ;
+         memcpy(VARDATA(str), d->data, d->offset);
+         PG_RETURN_TEXT_P(str);
+     }
+ }
Index: src/include/catalog/pg_aggregate.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_aggregate.h,v
retrieving revision 1.51
diff -c -r1.51 pg_aggregate.h
*** src/include/catalog/pg_aggregate.h    14 Apr 2005 01:38:20 -0000    1.51
--- src/include/catalog/pg_aggregate.h    2 Oct 2005 23:50:35 -0000
***************
*** 175,180 ****
--- 175,183 ----
  DATA(insert ( 2242 bitand          -                    0    1560    _null_ ));
  DATA(insert ( 2243 bitor          -                    0    1560    _null_ ));

+ /* xmlagg */
+ DATA(insert ( 1079    text_xmlagg_accum    text_xmlagg    0    25    _null_ ));
+
  /*
   * prototypes for functions in pg_aggregate.c
   */
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.385
diff -c -r1.385 pg_proc.h
*** src/include/catalog/pg_proc.h    16 Sep 2005 05:35:40 -0000    1.385
--- src/include/catalog/pg_proc.h    2 Oct 2005 23:50:42 -0000
***************
*** 807,813 ****
  DESCR("convert name to char(n)");
  DATA(insert OID =  409 (  name               PGNSP PGUID 12 f f t f i 1 19 "1042" _null_ _null_ _null_    bpchar_name
-_null_ )); 
  DESCR("convert char(n) to name");
-
  DATA(insert OID = 440 (  hashgettuple       PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_
hashgettuple- _null_ )); 
  DESCR("hash(internal)");
  DATA(insert OID = 637 (  hashgetmulti       PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_
hashgetmulti- _null_ )); 
--- 807,812 ----
***************
*** 2710,2715 ****
--- 2709,2719 ----
  DESCR("AVG(int4) transition function");
  DATA(insert OID = 1964 (  int8_avg           PGNSP PGUID 12 f f t f i 1 1700 "1016" _null_ _null_ _null_  int8_avg -
_null_)); 
  DESCR("AVG(int) aggregate final function");
+ DATA(insert OID =  1136 ( text_xmlagg_accum      PGNSP PGUID 12 f f f f i 2 25 "25 25" _null_ _null_ _null_
text_xmlagg_accum- _null_ ));           
+ DESCR("trans fce for fast string");
+ DATA(insert OID =  1137 ( text_xmlagg          PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_  text_xmlagg -
_null_)); 
+ DESCR("final fce for fast string");
+

  /* To ASCII conversion */
  DATA(insert OID = 1845 ( to_ascii    PGNSP PGUID 12 f f t f i 1    25 "25" _null_ _null_ _null_    to_ascii_default -
_null_)); 
***************
*** 3135,3140 ****
--- 3139,3146 ----
  DATA(insert OID = 2158 (  stddev            PGNSP PGUID 12 t f f f i 1 701 "701" _null_ _null_ _null_
aggregate_dummy- _null_ )); 
  DATA(insert OID = 2159 (  stddev            PGNSP PGUID 12 t f f f i 1 1700 "1700" _null_ _null_ _null_
aggregate_dummy- _null_ )); 

+ DATA(insert OID = 1079 (  xmlagg            PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_
aggregate_dummy- _null_ )); 
+
  DATA(insert OID = 2160 ( text_pattern_lt     PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_
text_pattern_lt- _null_ )); 
  DATA(insert OID = 2161 ( text_pattern_le     PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_
text_pattern_le- _null_ )); 
  DATA(insert OID = 2162 ( text_pattern_eq     PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_
text_pattern_eq- _null_ )); 
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.138
diff -c -r1.138 execnodes.h
*** src/include/nodes/execnodes.h    25 Sep 2005 19:37:35 -0000    1.138
--- src/include/nodes/execnodes.h    2 Oct 2005 23:50:43 -0000
***************
*** 686,691 ****
--- 686,710 ----
  } MinMaxExprState;

  /* ----------------
+  *        MinMaxExprState node
+  * ----------------
+  */
+ typedef struct XmlExprState
+ {
+     ExprState    xprstate;
+     XmlExprOp    op;
+     List        *nargs;            /* the named arguments */
+     List        *args;            /* the arguments, only last should be non xml */
+     List       *xml_args;            /* xml arguments, result is always cstring */
+     Oid       *nargs_tcache;
+     char       **nargs_ncache;
+     Oid       arg_typeId;
+     XmlParams  *params;
+     int    level;                /* info about tabs now, shared tag's table in future */
+ } XmlExprState;
+
+
+ /* ----------------
   *        CoerceToDomainState node
   * ----------------
   */
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.175
diff -c -r1.175 nodes.h
*** src/include/nodes/nodes.h    1 Aug 2005 20:31:15 -0000    1.175
--- src/include/nodes/nodes.h    2 Oct 2005 23:50:44 -0000
***************
*** 137,142 ****
--- 137,144 ----
      T_RangeTblRef,
      T_JoinExpr,
      T_FromExpr,
+     T_XmlExpr,
+     T_XmlParams,

      /*
       * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
***************
*** 163,169 ****
      T_MinMaxExprState,
      T_CoerceToDomainState,
      T_DomainConstraintState,
!
      /*
       * TAGS FOR PLANNER NODES (relation.h)
       */
--- 165,172 ----
      T_MinMaxExprState,
      T_CoerceToDomainState,
      T_DomainConstraintState,
!     T_XmlExprState,
!
      /*
       * TAGS FOR PLANNER NODES (relation.h)
       */
Index: src/include/nodes/primnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/primnodes.h,v
retrieving revision 1.108
diff -c -r1.108 primnodes.h
*** src/include/nodes/primnodes.h    26 Jun 2005 22:05:41 -0000    1.108
--- src/include/nodes/primnodes.h    2 Oct 2005 23:50:44 -0000
***************
*** 675,680 ****
--- 675,731 ----
  } MinMaxExpr;

  /*
+  * XmlExpr - holder SQL/XML functions xmlroot, xmlforest, xmlelement, xmlpi,
+  * xmlcomment, xmlconcat
+  */
+ typedef enum XmlExprOp
+ {
+     IS_XMLUNKNOWN = 0,
+     IS_XMLAGG,
+     IS_XMLROOT,
+     IS_XMLELEMENT,
+     IS_XMLFOREST,
+     IS_XMLPI,
+     IS_XMLCOMMENT,
+     IS_XMLCONCAT,
+     IS_XMLSERIALIZE
+ } XmlExprOp;
+
+ typedef enum XmlParamOp
+ {
+     IS_XMLENCODING,
+     IS_XMLVERSION,
+     IS_XMLNAME,
+     IS_XMLSTANDALONE
+ } XmlParamOp;
+
+ typedef struct XmlParam
+ {
+     XmlParamOp op;
+     char *value;
+ } XmlParam;
+
+ typedef struct XmlParams
+ {
+     NodeTag type;
+     char *encoding;
+     char *version;
+     char *name;
+     char *standalone;
+ } XmlParams;
+
+ typedef struct XmlExpr
+ {
+     Expr        xpr;
+     XmlExprOp    op;                /* function to execute */
+     List     *xml_args;                /* xml arguments */
+     List    *nargs;                    /* named arguments */
+     List    *args;
+     XmlParams *params;                /* non xml argument */
+     int    level;
+ } XmlExpr;
+
+ /*
   * NullIfExpr - a NULLIF expression
   *
   * Like DistinctExpr, this is represented the same as an OpExpr referencing
***************
*** 940,943 ****
--- 991,995 ----
      Node       *quals;            /* qualifiers on join, if any */
  } FromExpr;

+
  #endif   /* PRIMNODES_H */

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: New pg_dump options: exclude tables/schemas, multiple
Next
From: Tom Lane
Date:
Subject: Re: SQL/XML publishing function experimental patch II