Hello

This patch contains SQL/XML public function XMLFOREST, XMLELEMENT, ... based on CString type. This patch hasn't high quality, but can be usefull for testing funcionality, and maybe for some people. Patch needs initdb and following registration:

CREATE AGGREGATE pg_catalog.fast_cstring_concat (
        BASETYPE = cstring,
        SFUNC = xmlagg_trans,
        STYPE = text,
        FINALFUNC = xmlagg_final);

I invite all notes, ..

Best regards
Pavel Stehule

_________________________________________________________________
Chcete sdilet sve obrazky a hudbu s prateli? http://messenger.msn.cz/
diff -c -r pgsql.clean/src/backend/executor/execQual.c pgsql2/src/backend/executor/execQual.c
*** pgsql.clean/src/backend/executor/execQual.c	2005-06-27 00:05:36.000000000 +0200
--- pgsql2/src/backend/executor/execQual.c	2005-09-05 17:41:48.000000000 +0200
***************
*** 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,2498 ----
  		}
  	}
  
!  	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 Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
! 			    bool *isNull, ExprDoneCond *isDone)
! {
! 	    StringInfoData buf;
! 	    bool isnull;
! 	    ListCell *arg;
! 	
! 	    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)
! 					    {
! 						appendStringInfo(&buf, "%s",  (char *)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)
! 						    {
! 							    appendStringInfo(&buf, ">");
! 							    state = 1;
! 						    }	
! 						    appendStringInfo(&buf, "%s",  (char *)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, "?>%s", (char *)value);
! 			    }
! 			    break;
! 		    case IS_XMLSERIALIZE:
! 			    {
! 					ExprState  *arg = linitial(xmlExpr->xml_args);
! 					Datum value = ExecEvalExpr(arg, econtext, &isnull, NULL);
! 					int strl = strlen((char *)value);
! 					text * result = (text *) palloc (VARHDRSZ + strl);
! 					VARATT_SIZEP(result) = VARHDRSZ + strl;
! 					memcpy(VARDATA(result), (char *)value, strl);
! 					pfree((char *)value);
! 					PG_RETURN_TEXT_P(result);
! 			    }
! 			    break;
! 		    default:
! 			    break;
! 	    }
! 	    
! 	    PG_RETURN_CSTRING(buf.data);
! 	
  }
  
+ 
  /* ----------------------------------------------------------------
   *		ExecEvalNullIf
   *
***************
*** 3296,3301 ****
--- 3482,3556 ----
  				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;
diff -c -r pgsql.clean/src/backend/nodes/copyfuncs.c pgsql2/src/backend/nodes/copyfuncs.c
*** pgsql.clean/src/backend/nodes/copyfuncs.c	2005-08-01 22:31:08.000000000 +0200
--- pgsql2/src/backend/nodes/copyfuncs.c	2005-09-06 14:44:28.000000000 +0200
***************
*** 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;
diff -c -r pgsql.clean/src/backend/nodes/equalfuncs.c pgsql2/src/backend/nodes/equalfuncs.c
*** pgsql.clean/src/backend/nodes/equalfuncs.c	2005-08-01 22:31:08.000000000 +0200
--- pgsql2/src/backend/nodes/equalfuncs.c	2005-09-06 14:42:30.000000000 +0200
***************
*** 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;
diff -c -r pgsql.clean/src/backend/nodes/outfuncs.c pgsql2/src/backend/nodes/outfuncs.c
*** pgsql.clean/src/backend/nodes/outfuncs.c	2005-08-01 22:31:08.000000000 +0200
--- pgsql2/src/backend/nodes/outfuncs.c	2005-09-06 14:57:19.000000000 +0200
***************
*** 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");
***************
*** 1922,1927 ****
--- 1946,1954 ----
  			case T_MinMaxExpr:
  				_outMinMaxExpr(str, obj);
  				break;
+ 			case T_XmlExpr:
+ 				_outXmlExpr(str, obj);
+ 				break;
  			case T_NullIfExpr:
  				_outNullIfExpr(str, obj);
  				break;
diff -c -r pgsql.clean/src/backend/nodes/readfuncs.c pgsql2/src/backend/nodes/readfuncs.c
*** pgsql.clean/src/backend/nodes/readfuncs.c	2005-08-01 22:31:08.000000000 +0200
--- pgsql2/src/backend/nodes/readfuncs.c	2005-09-06 14:47:24.000000000 +0200
***************
*** 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))
diff -c -r pgsql.clean/src/backend/optimizer/util/clauses.c pgsql2/src/backend/optimizer/util/clauses.c
*** pgsql.clean/src/backend/optimizer/util/clauses.c	2005-07-03 23:14:17.000000000 +0200
--- pgsql2/src/backend/optimizer/util/clauses.c	2005-08-27 13:08:48.000000000 +0200
***************
*** 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;
diff -c -r pgsql.clean/src/backend/parser/gram.y pgsql2/src/backend/parser/gram.y
*** pgsql.clean/src/backend/parser/gram.y	2005-08-24 00:40:20.000000000 +0200
--- pgsql2/src/backend/parser/gram.y	2005-09-06 14:37:09.000000000 +0200
***************
*** 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
  
***************
*** 7395,7400 ****
--- 7413,7546 ----
  					v->op = IS_LEAST;
  					$$ = (Node *)v;
  				}
+ 			| XMLSERIALIZE '(' xmlexpr ')'
+ 				{
+ 					$$ = (Node *)
+ 					    makeXmlExpr(IS_XMLSERIALIZE, NULL, NULL, list_make1($3), NULL, NULL);
+ 				}
+ 		;
+ 		
+ /*
+  *  Supporting SQL/XML functions
+  */
+  
+ xmlexpr:		XMLAGG '(' a_expr ')'
+ 				{
+ 					$$ = makeXmlExpr(IS_XMLAGG, NULL, NULL, NULL, list_make1($3), NULL);
+ 				}
+ 			| XMLAGG '(' xmlexpr ')'
+ 				{	
+ 					/* Musi se udelat az pri transformaci */
+ 					$$ = 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;				
+ 				}
  		;
  
  /*
***************
*** 7757,7762 ****
--- 7903,7922 ----
  					$$->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:
***************
*** 8227,8232 ****
--- 8387,8393 ----
  			| SHOW
  			| SIMPLE
  			| STABLE
+ 			| STANDALONE
  			| START
  			| STATEMENT
  			| STATISTICS
***************
*** 8266,8271 ****
--- 8427,8434 ----
  			| WRITE
  			| YEAR_P
  			| ZONE
+ 			| NAME
+ 			| VERSION
  		;
  
  /* Column identifier --- keywords that can be column, table, etc names.
***************
*** 8316,8321 ****
--- 8479,8493 ----
  			| TREAT
  			| TRIM
  			| VARCHAR
+ 			| XMLAGG
+ 			| XMLATTRIBUTES
+ 			| XMLELEMENT
+ 			| XMLCOMMENT
+ 			| XMLCONCAT
+ 			| XMLFOREST
+ 			| XMLROOT
+ 			| XMLSERIALIZE
+ 			| XMLPI
  		;
  
  /* Function identifier --- keywords that can be function names.
***************
*** 8901,8904 ****
--- 9073,9124 ----
  	}
  }
  
+ 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"
diff -c -r pgsql.clean/src/backend/parser/keywords.c pgsql2/src/backend/parser/keywords.c
*** pgsql.clean/src/backend/parser/keywords.c	2005-08-24 00:40:27.000000000 +0200
--- pgsql2/src/backend/parser/keywords.c	2005-08-27 14:23:47.000000000 +0200
***************
*** 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},
  };
diff -c -r pgsql.clean/src/backend/parser/parse_expr.c pgsql2/src/backend/parser/parse_expr.c
*** pgsql.clean/src/backend/parser/parse_expr.c	2005-06-27 00:05:39.000000000 +0200
--- pgsql2/src/backend/parser/parse_expr.c	2005-09-05 16:50:09.000000000 +0200
***************
*** 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("fast_cstring_concat");
+ 		    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("fast_cstring_concat");
+ 		    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,1665 ----
  		case T_MinMaxExpr:
  			type = ((MinMaxExpr *) expr)->minmaxtype;
  			break;
+ 		case T_XmlExpr:
+ 			if (((XmlExpr *) expr)->op == IS_XMLSERIALIZE)
+ 			    type = TEXTOID;
+ 			else
+ 			    type = CSTRINGOID;
+ 			break;
  		case T_NullIfExpr:
  			type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
  			break;
***************
*** 1720,1725 ****
--- 1831,1838 ----
  			return ((CoerceToDomainValue *) expr)->typeMod;
  		case T_SetToDefault:
  			return ((SetToDefault *) expr)->typeMod;
+ 		case T_XmlExpr:
+ 			return -1;
  		default:
  			break;
  	}
diff -c -r pgsql.clean/src/backend/parser/parse_target.c pgsql2/src/backend/parser/parse_target.c
*** pgsql.clean/src/backend/parser/parse_target.c	2005-06-27 00:05:40.000000000 +0200
--- pgsql2/src/backend/parser/parse_target.c	2005-08-27 03:43:56.000000000 +0200
***************
*** 1135,1140 ****
--- 1135,1170 ----
  					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;
+ 			} 
+ 			break;
  		default:
  			break;
  	}
diff -c -r pgsql.clean/src/backend/utils/adt/ruleutils.c pgsql2/src/backend/utils/adt/ruleutils.c
*** pgsql.clean/src/backend/utils/adt/ruleutils.c	2005-08-01 22:31:12.000000000 +0200
--- pgsql2/src/backend/utils/adt/ruleutils.c	2005-08-27 13:06:53.000000000 +0200
***************
*** 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;
diff -c -r pgsql.clean/src/backend/utils/adt/varchar.c pgsql2/src/backend/utils/adt/varchar.c
*** pgsql.clean/src/backend/utils/adt/varchar.c	2005-07-29 14:59:15.000000000 +0200
--- pgsql2/src/backend/utils/adt/varchar.c	2005-09-02 22:08:24.000000000 +0200
***************
*** 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,897 ----
  
  	return result;
  }
+ 
+ /*
+  * Temp. aux. func for xmlagg function
+  *
+  */
+  
+ PG_FUNCTION_INFO_V1(xmlagg_trans);
+ PG_FUNCTION_INFO_V1(xmlagg_final);
+ 
+ typedef struct 
+ {
+   int32 size;  // varlena requirment
+   int max;
+   int offset;
+   bool isNull;
+   char data[1];
+ } data;
+ 
+ 
+ Datum xmlagg_trans(PG_FUNCTION_ARGS);
+ Datum xmlagg_final(PG_FUNCTION_ARGS);
+ 
+ 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
+ xmlagg_trans(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))
+     {
+       char *c = PG_GETARG_CSTRING(1);
+       d->isNull = false;
+       while(*c)
+ 	{
+ 	  if (d->max == d->offset)
+ 	    {
+ 	      int nmax = d->max *2;
+ 	      data *dn = reallocData((AggState *) fcinfo->context, d, nmax);
+ 	      d = dn;	      
+ 	    }
+ 	  d->data[d->offset++] = *c++;
+ 	}
+       d->data[d->offset] = '\0';
+     }
+ 
+   PG_RETURN_POINTER(d);
+ }
+ 		    
+ Datum
+ xmlagg_final(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
+     PG_RETURN_CSTRING(d->data);
+ }
diff -c -r pgsql.clean/src/include/catalog/pg_proc.h pgsql2/src/include/catalog/pg_proc.h
*** pgsql.clean/src/include/catalog/pg_proc.h	2005-08-13 21:02:34.000000000 +0200
--- pgsql2/src/include/catalog/pg_proc.h	2005-09-06 17:02:19.000000000 +0200
***************
*** 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,816 ----
  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 =  410 ( xmlagg_trans              PGNSP PGUID 12 f f f f i 2 25 "25 2275" _null_ _null_ _null_  xmlagg_trans - _null_ ));  		
! DESCR("trans fce for fast string");
! DATA(insert OID =  411 ( xmlagg_final		   PGNSP PGUID 12 f f t f i 1 2275 "25" _null_ _null_ _null_  xmlagg_final - _null_ ));
!  
  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_ ));
diff -c -r pgsql.clean/src/include/nodes/execnodes.h pgsql2/src/include/nodes/execnodes.h
*** pgsql.clean/src/include/nodes/execnodes.h	2005-08-01 22:31:15.000000000 +0200
--- pgsql2/src/include/nodes/execnodes.h	2005-09-05 17:31:23.000000000 +0200
***************
*** 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
   * ----------------
   */
diff -c -r pgsql.clean/src/include/nodes/nodes.h pgsql2/src/include/nodes/nodes.h
*** pgsql.clean/src/include/nodes/nodes.h	2005-08-01 22:31:15.000000000 +0200
--- pgsql2/src/include/nodes/nodes.h	2005-09-06 14:30:51.000000000 +0200
***************
*** 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)
  	 */
diff -c -r pgsql.clean/src/include/nodes/primnodes.h pgsql2/src/include/nodes/primnodes.h
*** pgsql.clean/src/include/nodes/primnodes.h	2005-06-27 00:05:41.000000000 +0200
--- pgsql2/src/include/nodes/primnodes.h	2005-09-06 14:31:53.000000000 +0200
***************
*** 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 5: don't forget to increase your free space map settings

Reply via email to