Thread: XML syntax patch

XML syntax patch

From
Bruce Momjian
Date:
I have received an update XML syntax patch from Nikolay (summer of code)
based on David Fetter's patch from 2005.

Comments?  It would be nice to have for 8.2.

--
  Bruce Momjian   bruce@momjian.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/include/utils/builtins.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.281
diff -u -r1.281 builtins.h
--- src/include/utils/builtins.h    28 Jul 2006 18:33:04 -0000    1.281
+++ src/include/utils/builtins.h    4 Sep 2006 23:33:10 -0000
@@ -905,4 +905,9 @@
 /* utils/mmgr/portalmem.c */
 extern Datum pg_cursor(PG_FUNCTION_ARGS);

+/* SQL/XML auxilliary functions (now as a part of varchar.c) */
+extern Datum text_xmlagg_accum(PG_FUNCTION_ARGS);
+extern Datum text_xmlagg(PG_FUNCTION_ARGS);
+
+
 #endif   /* BUILTINS_H */
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.422
diff -u -r1.422 pg_proc.h
--- src/include/catalog/pg_proc.h    19 Aug 2006 01:36:33 -0000    1.422
+++ src/include/catalog/pg_proc.h    4 Sep 2006 23:33:02 -0000
@@ -2756,6 +2756,12 @@
 DESCR("COVAR_SAMP(double, double) aggregate final function");
 DATA(insert OID = 2817 (  float8_corr                PGNSP PGUID 12 f f t f i 1 701 "1022" _null_ _null_ _null_
float8_corr- _null_ )); 
 DESCR("CORR(double, double) aggregate final function");
+DATA(insert OID = 5011 (  text_xmlagg_accum            PGNSP PGUID 12 f f f f i 2 25 "25 25" _null_ _null_ _null_
text_xmlagg_accum- _null_ )); 
+DESCR("XMLAGG accumulate function");
+DATA(insert OID = 5012 (  text_xmlagg                PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_
text_xmlagg- _null_ )); 
+DESCR("XMLAGG aggregate final function");
+DATA(insert OID = 5010 (  xmlagg                    PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_
aggregate_dummy- _null_ )); 
+DESCR("XMLAGG");

 /* 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_)); 
Index: src/include/catalog/pg_aggregate.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_aggregate.h,v
retrieving revision 1.57
diff -u -r1.57 pg_aggregate.h
--- src/include/catalog/pg_aggregate.h    28 Jul 2006 18:33:04 -0000    1.57
+++ src/include/catalog/pg_aggregate.h    4 Sep 2006 23:32:43 -0000
@@ -221,6 +221,9 @@
 DATA(insert ( 2242 bitand          -                    0    1560    _null_ ));
 DATA(insert ( 2243 bitor          -                    0    1560    _null_ ));

+/* xml */
+DATA(insert ( 5010    text_xmlagg_accum    text_xmlagg    0    25    _null_ ));
+
 /*
  * prototypes for functions in pg_aggregate.c
  */
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.187
diff -u -r1.187 nodes.h
--- src/include/nodes/nodes.h    2 Aug 2006 01:59:47 -0000    1.187
+++ src/include/nodes/nodes.h    4 Sep 2006 23:33:05 -0000
@@ -140,6 +140,8 @@
     T_RangeTblRef,
     T_JoinExpr,
     T_FromExpr,
+    T_XmlExpr,
+    T_XmlParams,

     /*
      * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
@@ -167,6 +169,7 @@
     T_MinMaxExprState,
     T_CoerceToDomainState,
     T_DomainConstraintState,
+    T_XmlExprState,

     /*
      * TAGS FOR PLANNER NODES (relation.h)
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.160
diff -u -r1.160 execnodes.h
--- src/include/nodes/execnodes.h    25 Aug 2006 04:06:56 -0000    1.160
+++ src/include/nodes/execnodes.h    4 Sep 2006 23:33:05 -0000
@@ -706,6 +706,24 @@
 } MinMaxExprState;

 /* ----------------
+ *        XmlExprState 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/primnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/primnodes.h,v
retrieving revision 1.115
diff -u -r1.115 primnodes.h
--- src/include/nodes/primnodes.h    27 Jul 2006 19:52:07 -0000    1.115
+++ src/include/nodes/primnodes.h    4 Sep 2006 23:33:07 -0000
@@ -706,6 +706,57 @@
 } 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
Index: src/backend/optimizer/util/clauses.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v
retrieving revision 1.219
diff -u -r1.219 clauses.c
--- src/backend/optimizer/util/clauses.c    12 Aug 2006 20:05:55 -0000    1.219
+++ src/backend/optimizer/util/clauses.c    4 Sep 2006 23:32:11 -0000
@@ -557,6 +557,8 @@
         return false;
     if (IsA(node, MinMaxExpr))
         return false;
+    if (IsA(node, XmlExpr))
+        return false;
     if (IsA(node, NullIfExpr))
         return false;

@@ -870,6 +872,8 @@
         return true;
     if (IsA(node, MinMaxExpr))
         return true;
+    if (IsA(node, XmlExpr))
+        return true;
     if (IsA(node, NullIfExpr))
         return true;
     if (IsA(node, NullTest))
@@ -3243,6 +3247,18 @@
             return walker(((CoalesceExpr *) node)->args, context);
         case T_MinMaxExpr:
             return walker(((MinMaxExpr *) 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_NullIfExpr:
             return walker(((NullIfExpr *) node)->args, context);
         case T_NullTest:
@@ -3740,6 +3756,18 @@
                 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_NullIfExpr:
             {
                 NullIfExpr *expr = (NullIfExpr *) node;
Index: src/backend/utils/adt/varchar.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/varchar.c,v
retrieving revision 1.118
diff -u -r1.118 varchar.c
--- src/backend/utils/adt/varchar.c    14 Jul 2006 14:52:24 -0000    1.118
+++ src/backend/utils/adt/varchar.c    4 Sep 2006 23:32:43 -0000
@@ -19,7 +19,7 @@
 #include "libpq/pqformat.h"
 #include "utils/builtins.h"
 #include "mb/pg_wchar.h"
-
+#include "nodes/execnodes.h"

 /*
  * CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
@@ -806,3 +806,95 @@

     return result;
 }
+
+/*
+ * Temp. aux. functions for XMLAGG SQL/XML function.
+ * In the future, this should be adapted for XML type.
+ *
+ */
+
+/* TODO this (struct and next 2 funcs) should be moved from here */
+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;
+    int     len;
+    text     *str;
+
+    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))
+    {
+        str = PG_GETARG_TEXT_P(1);
+        d->isNull = false;
+        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;
+    text     *str;
+
+    if (PG_ARGISNULL(0))
+        elog(ERROR, "internal error");
+
+    d = (data *) PG_GETARG_POINTER(0);
+    if (d->isNull)
+        PG_RETURN_NULL();
+    else
+    {
+        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/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.232
diff -u -r1.232 ruleutils.c
--- src/backend/utils/adt/ruleutils.c    21 Aug 2006 00:57:25 -0000    1.232
+++ src/backend/utils/adt/ruleutils.c    4 Sep 2006 23:32:42 -0000
@@ -2984,6 +2984,7 @@
         case T_RowExpr:
         case T_CoalesceExpr:
         case T_MinMaxExpr:
+        case T_XmlExpr:
         case T_NullIfExpr:
         case T_Aggref:
         case T_FuncExpr:
@@ -3092,6 +3093,7 @@
                 case T_RowExpr:    /* other separators */
                 case T_CoalesceExpr:    /* own parentheses */
                 case T_MinMaxExpr:        /* own parentheses */
+                case T_XmlExpr:            /* own parentheses */
                 case T_NullIfExpr:        /* other separators */
                 case T_Aggref:    /* own parentheses */
                 case T_CaseExpr:        /* other separators */
@@ -3140,6 +3142,7 @@
                 case T_RowExpr:    /* other separators */
                 case T_CoalesceExpr:    /* own parentheses */
                 case T_MinMaxExpr:        /* own parentheses */
+                case T_XmlExpr:            /* own parentheses */
                 case T_NullIfExpr:        /* other separators */
                 case T_Aggref:    /* own parentheses */
                 case T_CaseExpr:        /* other separators */
@@ -3767,6 +3770,43 @@
             }
             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_XMLAGG:
+                    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_NullIfExpr:
             {
                 NullIfExpr *nullifexpr = (NullIfExpr *) node;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.565
diff -u -r2.565 gram.y
--- src/backend/parser/gram.y    3 Sep 2006 22:37:05 -0000    2.565
+++ src/backend/parser/gram.y    4 Sep 2006 23:32:27 -0000
@@ -107,6 +107,10 @@
 static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
 static Node *doNegate(Node *n, int location);
 static void doNegateFloat(Value *v);
+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);

 %}

@@ -144,6 +148,10 @@

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

 %type <node>    stmt schema_stmt
@@ -346,6 +354,12 @@
 %type <str>        OptTableSpace OptConsTableSpace OptTableSpaceOwner
 %type <list>    opt_check_option

+%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
@@ -399,7 +413,7 @@

     MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE

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

@@ -418,7 +432,7 @@

     SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
     SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
-    SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
+    SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE START STATEMENT
     STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
     SYSID SYSTEM_P

@@ -430,10 +444,13 @@
     UPDATE USER USING

     VACUUM VALID VALIDATOR VALUES VARCHAR VARYING
-    VERBOSE VIEW VOLATILE
+    VERBOSE VERSION VIEW VOLATILE

     WHEN WHERE WITH WITHOUT WORK WRITE

+    XMLAGG XMLATTRIBUTES XMLCOMMENT XMLCONCAT XMLELEMENT XMLFOREST
+    XMLPI XMLROOT XMLSERIALIZE
+
     YEAR_P

     ZONE
@@ -7889,6 +7906,139 @@
                     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 '(' NAME ColLabel ')'
+                {
+                    $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NULL, NULL, NULL);
+                }
+            | XMLPI '(' NAME ColLabel ',' a_expr ')'
+                {
+                    $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NULL, list_make1($6), 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;
+                }
         ;

 /*
@@ -8290,6 +8440,20 @@
                     $$->val = (Node *)n;
                     $$->location = @1;
                 }
+            | xmlexpr AS ColLabel
+                {
+                    $$ = makeNode(ResTarget);
+                    $$->name = $3;
+                    $$->indirection = NIL;
+                    $$->val = (Node *)$1;
+                }
+            | xmlexpr
+                {
+                    $$ = makeNode(ResTarget);
+                    $$->name = NULL;
+                    $$->indirection = NIL;
+                    $$->val = (Node *)$1;
+                }
         ;


@@ -8661,6 +8825,7 @@
             | MODE
             | MONTH_P
             | MOVE
+            | NAME
             | NAMES
             | NEXT
             | NO
@@ -8721,6 +8886,7 @@
             | SHOW
             | SIMPLE
             | STABLE
+            | STANDALONE
             | START
             | STATEMENT
             | STATISTICS
@@ -8750,6 +8916,7 @@
             | VALID
             | VALIDATOR
             | VARYING
+            | VERSION
             | VIEW
             | VOLATILE
             | WITH
@@ -8809,6 +8976,15 @@
             | TRIM
             | VALUES
             | VARCHAR
+            | XMLAGG
+            | XMLATTRIBUTES
+            | XMLELEMENT
+            | XMLCOMMENT
+            | XMLCONCAT
+            | XMLFOREST
+            | XMLPI
+            | XMLROOT
+            | XMLSERIALIZE
         ;

 /* Function identifier --- keywords that can be function names.
@@ -9380,10 +9556,56 @@
     }
 }

+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;
+}
+
 /*
  * Must undefine base_yylex before including scan.c, since we want it
  * to create the function base_yylex not filtered_base_yylex.
  */
 #undef base_yylex

-#include "scan.c"
+#include "scan.c"
\ No newline at end of file
Index: src/backend/parser/parse_target.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_target.c,v
retrieving revision 1.148
diff -u -r1.148 parse_target.c
--- src/backend/parser/parse_target.c    14 Aug 2006 23:39:32 -0000    1.148
+++ src/backend/parser/parse_target.c    4 Sep 2006 23:32:34 -0000
@@ -1315,6 +1315,39 @@
                     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/parser/parse_expr.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.197
diff -u -r1.197 parse_expr.c
--- src/backend/parser/parse_expr.c    12 Aug 2006 20:05:55 -0000    1.197
+++ src/backend/parser/parse_expr.c    4 Sep 2006 23:32:29 -0000
@@ -55,6 +55,8 @@
 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 *transformXmlList(ParseState *pstate, List *list, int level);
 static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
 static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
 static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
@@ -71,6 +73,7 @@
 static Expr *make_distinct_op(ParseState *pstate, List *opname,
                  Node *ltree, Node *rtree, int location);

+extern char *FigureColname(Node *e);

 /*
  * transformExpr -
@@ -218,6 +221,10 @@
             result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
             break;

+        case T_XmlExpr:
+            result = transformXmlExpr(pstate, (XmlExpr *) expr);
+            break;
+
         case T_NullTest:
             {
                 NullTest   *n = (NullTest *) expr;
@@ -1368,6 +1375,98 @@
 }

 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 *te;
+        Node *e = (Node *) lfirst(arg);
+        ((XmlExpr *)e)->level = level;
+        te = transformExpr(pstate, e);
+        newlist = lappend(newlist, te);
+    }
+    return (Node *) newlist;
+}
+
+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)
+        {
+            FuncCall     *n;
+            XmlExpr     *p = (XmlExpr *) linitial(x->xml_args);
+            p->level = x->level + 1;
+            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);
+        }
+    }
+
+    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)
 {
     const char *clausename;
@@ -1399,10 +1498,7 @@
     }

     b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg);
-
-    b->arg = (Expr *) coerce_to_boolean(pstate,
-                                        (Node *) b->arg,
-                                        clausename);
+    b->arg = (Expr *) coerce_to_boolean(pstate, (Node *) b->arg, clausename);

     return (Node *) b;
 }
@@ -1657,6 +1753,9 @@
         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/keywords.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.176
diff -u -r1.176 keywords.c
--- src/backend/parser/keywords.c    25 Aug 2006 04:06:52 -0000    1.176
+++ src/backend/parser/keywords.c    4 Sep 2006 23:32:28 -0000
@@ -217,6 +217,7 @@
     {"mode", MODE},
     {"month", MONTH_P},
     {"move", MOVE},
+    {"name", NAME},
     {"names", NAMES},
     {"national", NATIONAL},
     {"natural", NATURAL},
@@ -313,6 +314,7 @@
     {"smallint", SMALLINT},
     {"some", SOME},
     {"stable", STABLE},
+    {"standalone", STANDALONE},
     {"start", START},
     {"statement", STATEMENT},
     {"statistics", STATISTICS},
@@ -360,6 +362,7 @@
     {"varchar", VARCHAR},
     {"varying", VARYING},
     {"verbose", VERBOSE},
+    {"version", VERSION},
     {"view", VIEW},
     {"volatile", VOLATILE},
     {"when", WHEN},
@@ -368,6 +371,15 @@
     {"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/nodes/readfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/readfuncs.c,v
retrieving revision 1.195
diff -u -r1.195 readfuncs.c
--- src/backend/nodes/readfuncs.c    12 Aug 2006 02:52:04 -0000    1.195
+++ src/backend/nodes/readfuncs.c    4 Sep 2006 23:32:05 -0000
@@ -707,6 +707,34 @@
     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
  */
@@ -1007,6 +1035,10 @@
         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/nodes/outfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.284
diff -u -r1.284 outfuncs.c
--- src/backend/nodes/outfuncs.c    25 Aug 2006 04:06:50 -0000    1.284
+++ src/backend/nodes/outfuncs.c    4 Sep 2006 23:32:02 -0000
@@ -890,6 +890,19 @@
 }

 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");
@@ -2008,6 +2021,9 @@
             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/equalfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.284
diff -u -r1.284 equalfuncs.c
--- src/backend/nodes/equalfuncs.c    30 Aug 2006 23:34:21 -0000    1.284
+++ src/backend/nodes/equalfuncs.c    4 Sep 2006 23:32:01 -0000
@@ -454,6 +454,28 @@
 }

 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)
 {
     COMPARE_SCALAR_FIELD(opno);
@@ -1959,6 +1981,12 @@
         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/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.350
diff -u -r1.350 copyfuncs.c
--- src/backend/nodes/copyfuncs.c    30 Aug 2006 23:34:21 -0000    1.350
+++ src/backend/nodes/copyfuncs.c    4 Sep 2006 23:31:57 -0000
@@ -1091,6 +1091,36 @@
 }

 /*
+ * _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 *
@@ -2957,6 +2987,12 @@
         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/executor/execQual.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/execQual.c,v
retrieving revision 1.193
diff -u -r1.193 execQual.c
--- src/backend/executor/execQual.c    27 Jul 2006 19:52:05 -0000    1.193
+++ src/backend/executor/execQual.c    4 Sep 2006 23:31:53 -0000
@@ -52,6 +52,9 @@
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/typcache.h"
+#include "lib/stringinfo.h"
+
+#include <string.h>


 /* static function decls */
@@ -119,6 +122,8 @@
 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);
@@ -2613,6 +2618,230 @@
 }

 /* ----------------------------------------------------------------
+ *        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:
+            {
+                int state = 0, i = 0;
+                appendStringInfo(&buf, "<%s", getXmlParam(xmlExpr->params, IS_XMLNAME));
+                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++;
+                }
+                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:
+            {
+                bool         isnull;
+                char         *outstr;
+                ExprState     *arg = linitial(xmlExpr->args);
+                Datum         value = ExecEvalExpr(arg, econtext, &isnull, NULL);
+                /* In case of NULL input, return NULL, according SQL/XML standard */
+                if (isnull)
+                    *isNull = true;
+                else
+                {
+                    outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeId, value));
+                    appendStringInfo(&buf, "<!--%s-->", outstr);
+                    pfree(outstr);
+                }
+            }
+            break;
+        case IS_XMLPI:
+            {
+                bool         isnull;
+                char        *piname = getXmlParam(xmlExpr->params, IS_XMLNAME);
+                int32        pinamelen = strlen(piname);
+                if (pinamelen > 2
+                    && (piname[0] == 'x' || piname[0] == 'X')
+                    && (piname[1] == 'm' || piname[1] == 'M')
+                    && (piname[2] == 'l' || piname[2] == 'L'))
+                {
+                    ereport(ERROR, (
+                        errmsg("invalid name of XML processing instruction"),
+                        errdetail("XML processing instruction name cannot start with 'xml' ('%s' provided)",
piname)));
+                }
+                appendStringInfo(&buf, "<?%s", piname);
+                if (xmlExpr->args != NULL)
+                {
+                    char         *outstr;
+                    ExprState     *arg = linitial(xmlExpr->args);
+                    Datum         value = ExecEvalExpr(arg, econtext, &isnull, NULL);
+                    /* In case of NULL input, return NULL, according SQL/XML standard */
+                    if (isnull)
+                        *isNull = true;
+                    else
+                    {
+                        outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeId, value));
+                        appendStringInfo(&buf, " %s", outstr);
+                        pfree(outstr);
+                    }
+                }
+                appendStringInfo(&buf, "?>");
+            }
+            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
  *
  * Note that this is *always* derived from the equals operator,
@@ -3594,6 +3823,77 @@
                 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 = (Oid *) 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);
+                        TargetEntry    *tle;
+                        outlist = lappend(outlist, estate);
+                        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;
+                    ExprState     *estate;
+                    Expr         *e = (Expr *) lfirst(arg);
+                    getTypeOutputInfo(exprType((Node *)e), &typid, &tpisvarlena);
+                    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: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.333
diff -u -r1.333 func.sgml
--- doc/src/sgml/func.sgml    4 Sep 2006 21:47:25 -0000    1.333
+++ doc/src/sgml/func.sgml    4 Sep 2006 23:31:46 -0000
@@ -10530,8 +10530,129 @@
    </para>

   </sect1>
-</chapter>
+  <sect1 id="functions-sqlxml">
+   <title>SQL/XML publishing 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><optional>,
...</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
 Local variables:
 mode:sgml
@@ -10547,4 +10668,4 @@
 sgml-local-catalogs:("/usr/lib/sgml/catalog")
 sgml-local-ecat-files:nil
 End:
--->
+-->
\ No newline at end of file

Re: XML syntax patch

From
"Nikolay Samokhvalov"
Date:
Two minor notes:
 - this is "SQL/XML publishing functions" patch actually
 - Initial author of the patch is Pavel Stehule, David added some
documentation (AFAIK)

On 9/5/06, Bruce Momjian <bruce@momjian.us> wrote:
> I have received an update XML syntax patch from Nikolay (summer of code)
> based on David Fetter's patch from 2005.
>
> Comments?  It would be nice to have for 8.2.
>
> --
>   Bruce Momjian   bruce@momjian.us
>   EnterpriseDB    http://www.enterprisedb.com
>
>   + If your life is a hard drive, Christ can be your backup. +
>
>
>


--
Best regards,
Nikolay

Re: XML syntax patch

From
David Fetter
Date:
On Mon, Sep 04, 2006 at 09:21:12PM -0400, Bruce Momjian wrote:
> I have received an update XML syntax patch from Nikolay (summer of
> code) based on David Fetter's patch from 2005.
>
> Comments?  It would be nice to have for 8.2.

It was Pavel Stehule's patch.  I just added a little bit of
documentation.

Cheers,
D
--
David Fetter <david@fetter.org> http://fetter.org/
phone: +1 415 235 3778        AIM: dfetter666
                              Skype: davidfetter

Remember to vote!

Re: XML syntax patch

From
Bruce Momjian
Date:
David Fetter wrote:
> On Mon, Sep 04, 2006 at 09:21:12PM -0400, Bruce Momjian wrote:
> > I have received an update XML syntax patch from Nikolay (summer of
> > code) based on David Fetter's patch from 2005.
> >
> > Comments?  It would be nice to have for 8.2.
>
> It was Pavel Stehule's patch.  I just added a little bit of
> documentation.

OK, thanks.  I will make sure everyone gets credit.

--
  Bruce Momjian   bruce@momjian.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

Re: XML syntax patch

From
Peter Eisentraut
Date:
Am Dienstag, 5. September 2006 03:21 schrieb Bruce Momjian:
> I have received an update XML syntax patch from Nikolay (summer of code)
> based on David Fetter's patch from 2005.
>
> Comments?  It would be nice to have for 8.2.

I've told you privately already, I think it would be a grave mistake to add
this now.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

Re: XML syntax patch

From
Peter Eisentraut
Date:
Am Mittwoch, 6. September 2006 17:28 schrieb Bruce Momjian:
> Uh, when?  You had Nikolay review David's patch to see if it could be
> made consistent enough so it could go into 8.2 and not conflict with the
> additions in 8.3.

The only thing we could justify under the feature freeze regime is to add the
XML syntax into 8.2, operating on text data.  That will change when the xml
type goes into 8.3.  So we'd be adding a feature right now with the
announcement that the feature will break incompatibly in the next release.
That doesn't seem very useful to me.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

Re: XML syntax patch

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Am Mittwoch, 6. September 2006 17:28 schrieb Bruce Momjian:
> > Uh, when?  You had Nikolay review David's patch to see if it could be
> > made consistent enough so it could go into 8.2 and not conflict with the
> > additions in 8.3.
>
> The only thing we could justify under the feature freeze regime is to add the
> XML syntax into 8.2, operating on text data.  That will change when the xml
> type goes into 8.3.  So we'd be adding a feature right now with the
> announcement that the feature will break incompatibly in the next release.
> That doesn't seem very useful to me.

Right, that is exactly what I remember, but you had Nikolay look at the
patch in case he could make it not break incompatibly in 8.3.  Anyway,
patch shelved for 8.3.  I just wanted to make sure I didn't miss an
email from you.

--
  Bruce Momjian   bruce@momjian.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

Re: XML syntax patch

From
Bruce Momjian
Date:
Peter Eisentraut wrote:
> Am Dienstag, 5. September 2006 03:21 schrieb Bruce Momjian:
> > I have received an update XML syntax patch from Nikolay (summer of code)
> > based on David Fetter's patch from 2005.
> >
> > Comments?  It would be nice to have for 8.2.
>
> I've told you privately already, I think it would be a grave mistake to add
> this now.

Uh, when?  You had Nikolay review David's patch to see if it could be
made consistent enough so it could go into 8.2 and not conflict with the
additions in 8.3.

Now that I know, it will be pushed to 8.3 --- another feature that will
_not_ be in 8.2.

--
  Bruce Momjian   bruce@momjian.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +