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 [EMAIL PROTECTED] 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
---------------------------(end of broadcast)--------------------------- TIP 1: if posting/reading through Usenet, please send an appropriate subscribe-nomail command to [EMAIL PROTECTED] so that your message can get through to the mailing list cleanly