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 [EMAIL PROTECTED] 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 */
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to