Do we want this XML patch in the backend? It needs syntax support so I
don't see how it could be done in /contrib. Attached.
---------------------------------------------------------------------------
David Fetter wrote:
> On Wed, Sep 28, 2005 at 04:30:54PM +0200, Pavel Stehule wrote:
> > Hello
> >
> > base type changed to text, better registration xmlagg function
> >
> > Regards Pavel Stehule
>
> Now with some slightly improved documentation, works vs. CVS tip as of
> this writing.
>
> Cheers,
> D
> --
> David Fetter david@fetter.org http://fetter.org/
> phone: +1 510 893 6100 mobile: +1 415 235 3778
>
> Remember to vote!
[ Attachment, skipping... ]
>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: explain analyze is your friend
--
Bruce Momjian http://candle.pha.pa.us
EnterpriseDB http://www.enterprisedb.com
+ If your life is a hard drive, Christ can be your backup. +
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.286
diff -c -r1.286 func.sgml
*** doc/src/sgml/func.sgml 16 Sep 2005 05:35:39 -0000 1.286
--- doc/src/sgml/func.sgml 2 Oct 2005 23:50:12 -0000
***************
*** 9707,9712 ****
--- 9707,9836 ----
</para>
</sect1>
+
+ <sect1 id="functions-sqlxml">
+ <title>SQL/XML public functions</title>
+
+ <sect2>
+ <title><literal>XMLAGG</literal></title>
+
+ <indexterm>
+ <primary>XMLAGG</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLAGG</function>(<replaceable>xml expr</replaceable>)
+ </synopsis>
+
+ <para>
+ This combines a collection of rows, each containing a single XML
+ value, to create a single value containing an XML forest.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><literal>XMLCOMMENT</literal></title>
+
+ <indexterm>
+ <primary>XMLCOMMENT</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLCOMMENT</function>(<replaceable>text</replaceable>)
+ </synopsis>
+
+ <para>
+ Creates an XML comment.
+ </para>
+ </sect2>
+
+
+ <sect2>
+ <title><literal>XMLCONCAT</literal></title>
+
+ <indexterm>
+ <primary>XMLCONCAT</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLCONCAT</function>(<replaceable>xml expr</replaceable><optional>, xml expr</optional>)
+ </synopsis>
+
+ <para>
+ Combines a list of individual XML values to create a
+ single value containing an XML forest.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><literal>XMLELEMENT</literal></title>
+
+ <indexterm>
+ <primary>XMLELEMENT</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLELEMENT</function>(Name <replaceable>name</replaceable><optional>,
XMLATTRIBUTES(<replaceable>value</replaceable><optional>AS <replaceable>label</replaceable></optional><optional>, ...
</optional>)</optional>
+ <optional>, xml expr list</optional>
+ <optional><replaceable>, value</replaceable></optional>)
+ </synopsis>
+
+ <para>
+ Creates an XML element, allowing the name to be specified.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><literal>XMLFOREST</literal></title>
+
+ <indexterm>
+ <primary>XMLFOREST</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLFOREST</function>(<replaceable>value</replaceable> <optional>AS
<replaceable>label</replaceable></optional><optional>,...</optional>)
+ </synopsis>
+
+ <para>
+ Creates XML elements from columns, using the name of each
+ column as the name of the corresponding element.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><literal>XMLPI</literal></title>
+
+ <indexterm>
+ <primary>XMLPI</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLPI</function>(<replaceable>text</replaceable>)
+ </synopsis>
+
+ <para>
+ Creates an XML processing instruction.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><literal>XMLROOT</literal></title>
+
+ <indexterm>
+ <primary>XMLROOT</primary>
+ </indexterm>
+
+ <synopsis>
+ <function>XMLROOT</function>(<replaceable>xml expr</replaceable>
+ <optional>, VERSION|ENCODING|STANDALONE = <replaceable>text<replaceable>, ... </optional>)
+ </synopsis>
+
+ <para>
+ Creates the root node of an XML document.
+ </para>
+ </sect2>
+
+ </sect1>
</chapter>
<!-- Keep this comment at the end of the file
Index: src/backend/executor/execQual.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/execQual.c,v
retrieving revision 1.180
diff -c -r1.180 execQual.c
*** src/backend/executor/execQual.c 26 Jun 2005 22:05:36 -0000 1.180
--- src/backend/executor/execQual.c 2 Oct 2005 23:50:15 -0000
***************
*** 53,59 ****
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/typcache.h"
!
/* static function decls */
static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
--- 53,60 ----
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/typcache.h"
! #include "lib/stringinfo.h"
! #include <string.h>
/* static function decls */
static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
***************
*** 111,116 ****
--- 112,119 ----
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+ static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(GenericExprState *nstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
***************
*** 218,223 ****
--- 221,228 ----
* have to know the difference (that's what they need refattrlength for).
*----------
*/
+
+
static Datum
ExecEvalArrayRef(ArrayRefExprState *astate,
ExprContext *econtext,
***************
*** 2304,2312 ****
}
}
! return result;
}
/* ----------------------------------------------------------------
* ExecEvalNullIf
*
--- 2309,2507 ----
}
}
! return result;
! }
!
! /* ----------------------------------------------------------------
! * ExecEvalXml
! * ----------------------------------------------------------------
! */
!
! static char *
! getXmlParam(XmlParams *params, XmlParamOp op)
! {
! if (params == NULL)
! return NULL;
! switch (op)
! {
! case IS_XMLNAME:
! return params->name;
! case IS_XMLVERSION:
! return params->version;
! case IS_XMLENCODING:
! return params->encoding;
! case IS_XMLSTANDALONE:
! return params->standalone;
! }
! return NULL;
! }
!
! static void
! appendStringInfoText(StringInfo str, const text *t)
! {
! appendBinaryStringInfo(str, VARDATA(t), VARSIZE(t) - VARHDRSZ);
! }
!
! static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
! bool *isNull, ExprDoneCond *isDone)
! {
! StringInfoData buf;
! bool isnull;
! ListCell *arg;
! text *result = NULL;
! int len;
!
! initStringInfo(&buf);
!
! *isNull = false;
!
! if (isDone)
! *isDone = ExprSingleResult;
!
!
! switch (xmlExpr->op)
! {
! case IS_XMLCONCAT:
! {
! *isNull = true;
! foreach(arg, xmlExpr->xml_args)
! {
! ExprState *e = (ExprState *) lfirst(arg);
! Datum value = ExecEvalExpr(e, econtext, &isnull, NULL);
! if (!isnull)
! {
! appendStringInfoText(&buf, (text *)value);
! *isNull = false;
! }
! }
! }
! break;
! case IS_XMLELEMENT:
! {
! appendStringInfo(&buf, "<%s", getXmlParam(xmlExpr->params, IS_XMLNAME));
! int state = 0;
! int i = 0;
! foreach(arg, xmlExpr->nargs)
! {
! GenericExprState *gstate = (GenericExprState *) lfirst(arg);
! Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
! if (!isnull)
! {
! char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->nargs_tcache[i], value));
! appendStringInfo(&buf, " %s=\"%s\"", xmlExpr->nargs_ncache[i], outstr);
! pfree(outstr);
! }
! i += 1;
! }
! foreach(arg, xmlExpr->xml_args)
! {
! ExprState *e = (ExprState *) lfirst(arg);
! Datum value = ExecEvalExpr(e, econtext, &isnull, NULL);
! if (!isnull)
! {
! if (state == 0)
! {
! appendStringInfoChar(&buf, '>');
! state = 1;
! }
! appendStringInfoText(&buf, (text *)value);
! }
! }
! if (xmlExpr->args)
! {
! ExprState *expr = linitial(xmlExpr->args);
! Datum value = ExecEvalExpr(expr, econtext, &isnull, NULL);
!
! if (!isnull)
! {
! char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeId, value));
! if (state == 0)
! {
! appendStringInfoChar(&buf, '>');
! state = 1;
! }
! appendStringInfo(&buf, "%s", outstr);
! pfree(outstr);
! }
! }
!
! if (state == 0)
! appendStringInfo(&buf, "/>");
! else if (state == 1)
! appendStringInfo(&buf, "</%s>", getXmlParam(xmlExpr->params, IS_XMLNAME));
!
! }
! break;
! case IS_XMLFOREST:
! {
! /* only if all argumets are null returns null */
! int i = 0; *isNull = true;
! foreach(arg, xmlExpr->nargs)
! {
! GenericExprState *gstate = (GenericExprState *) lfirst(arg);
! Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
! if (!isnull)
! {
! char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->nargs_tcache[i], value));
! appendStringInfo(&buf, "<%s>%s</%s>", xmlExpr->nargs_ncache[i], outstr,
xmlExpr->nargs_ncache[i]);
! pfree(outstr);
! *isNull = false;
! }
! i += 1;
! }
! }
! break;
! case IS_XMLCOMMENT:
! case IS_XMLPI:
! {
! bool isnull;
! ExprState *arg = linitial(xmlExpr->args);
! Datum value = ExecEvalExpr(arg, econtext, &isnull, NULL);
! char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeId, value));
! if (xmlExpr->op == IS_XMLCOMMENT)
! appendStringInfo(&buf, "<-- %s -->", outstr);
! if (xmlExpr->op == IS_XMLPI)
! appendStringInfo(&buf, "<? %s ?>", outstr);
! pfree(outstr);
! }
! break;
! case IS_XMLROOT:
! {
! ExprState *xarg = linitial(xmlExpr->xml_args);
! Datum value = ExecEvalExpr(xarg, econtext, &isnull, NULL);
!
! appendStringInfo(&buf,"<?xml");
! if (getXmlParam(xmlExpr->params, IS_XMLVERSION))
! appendStringInfo(&buf, " version=\"%s\"", getXmlParam(xmlExpr->params, IS_XMLVERSION));
! if (getXmlParam(xmlExpr->params, IS_XMLENCODING))
! appendStringInfo(&buf, " encoding=\"%s\"", getXmlParam(xmlExpr->params,IS_XMLENCODING));
! if (getXmlParam(xmlExpr->params, IS_XMLSTANDALONE))
! appendStringInfo(&buf, " standalone=\"%s\"", getXmlParam(xmlExpr->params,IS_XMLSTANDALONE));
! appendStringInfo(&buf, "?>");
! appendStringInfoText(&buf, (text *) value);
! }
! break;
! case IS_XMLSERIALIZE:
! {
! ExprState *arg = linitial(xmlExpr->xml_args);
! Datum value = ExecEvalExpr(arg, econtext, isNull, NULL);
! PG_RETURN_TEXT_P(value);
! }
! break;
! default:
! break;
! }
!
! len = buf.len + VARHDRSZ;
! result = palloc(len);
! VARATT_SIZEP(result) = len;
! memcpy(VARDATA(result), buf.data, buf.len);
! pfree(buf.data);
! PG_RETURN_TEXT_P(result);
!
}
+
/* ----------------------------------------------------------------
* ExecEvalNullIf
*
***************
*** 3296,3301 ****
--- 3491,3565 ----
state = (ExprState *) mstate;
}
break;
+ case T_XmlExpr:
+ {
+ List *outlist; ListCell *arg;
+ XmlExpr *xexpr = (XmlExpr *) node;
+ XmlExprState *xstate = makeNode(XmlExprState);
+ int i = 0; Oid typid;
+
+ xstate->level = xexpr->level;
+ xstate->params = xexpr->params;
+
+ xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
+ xstate->op = xexpr->op;
+
+ outlist = NIL;
+ if (xexpr->nargs)
+ {
+ xstate->nargs_tcache = (int*)palloc(list_length(xexpr->nargs)*sizeof(int));
+ xstate->nargs_ncache = (char**)palloc(list_length(xexpr->nargs)*sizeof(char*));
+
+ i = 0;
+ foreach(arg, xexpr->nargs)
+ {
+ bool tpisvarlena;
+ Expr *e = (Expr *) lfirst(arg);
+ ExprState *estate = ExecInitExpr(e, parent);
+
+ outlist = lappend(outlist, estate);
+ TargetEntry *tle = (TargetEntry *) ((GenericExprState *) estate)->xprstate.expr;
+ getTypeOutputInfo(exprType((Node *)tle->expr), &typid, &tpisvarlena);
+ xstate->nargs_ncache[i] = tle->resname;
+ xstate->nargs_tcache[i++] = typid;
+ }
+ }
+ else
+ {
+ xstate->nargs_tcache = NULL;
+ xstate->nargs_ncache = NULL;
+ }
+ xstate->nargs = outlist;
+
+ outlist = NIL;
+ if (xexpr->xml_args)
+ {
+ foreach(arg, xexpr->xml_args)
+ {
+ Expr *e = (Expr *) lfirst(arg);
+ ExprState *estate = ExecInitExpr(e, parent);
+
+ outlist = lappend(outlist, estate);
+ }
+ }
+ xstate->xml_args = outlist;
+
+ outlist = NIL;
+ foreach(arg, xexpr->args)
+ {
+ bool tpisvarlena;
+ Expr *e = (Expr *) lfirst(arg);
+ getTypeOutputInfo(exprType((Node *)e), &typid, &tpisvarlena);
+ ExprState *estate = ExecInitExpr(e, parent);
+ outlist = lappend(outlist, estate);
+ }
+ xstate->arg_typeId = typid;
+ xstate->args = outlist;
+
+ state = (ExprState *) xstate;
+ }
+ break;
+
case T_NullIfExpr:
{
NullIfExpr *nullifexpr = (NullIfExpr *) node;
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.315
diff -c -r1.315 copyfuncs.c
*** src/backend/nodes/copyfuncs.c 1 Aug 2005 20:31:08 -0000 1.315
--- src/backend/nodes/copyfuncs.c 2 Oct 2005 23:50:17 -0000
***************
*** 1063,1068 ****
--- 1063,1098 ----
}
/*
+ * _copyXmlExpr
+ */
+
+ static XmlParams *
+ _copyXmlParams(XmlParams *from)
+ {
+ XmlParams *newnode = makeNode(XmlParams);
+ COPY_STRING_FIELD(name);
+ COPY_STRING_FIELD(version);
+ COPY_STRING_FIELD(encoding);
+ COPY_STRING_FIELD(standalone);
+
+ return newnode;
+ }
+
+ static XmlExpr *
+ _copyXmlExpr(XmlExpr *from)
+ {
+ XmlExpr *newnode = makeNode(XmlExpr);
+ COPY_SCALAR_FIELD(op);
+ COPY_NODE_FIELD(xml_args);
+ COPY_NODE_FIELD(nargs);
+ COPY_NODE_FIELD(args);
+ COPY_NODE_FIELD(params);
+ COPY_SCALAR_FIELD(level);
+
+ return newnode;
+ }
+
+ /*
* _copyNullIfExpr (same as OpExpr)
*/
static NullIfExpr *
***************
*** 2843,2848 ****
--- 2873,2884 ----
case T_MinMaxExpr:
retval = _copyMinMaxExpr(from);
break;
+ case T_XmlParams:
+ retval = _copyXmlParams(from);
+ break;
+ case T_XmlExpr:
+ retval = _copyXmlExpr(from);
+ break;
case T_NullIfExpr:
retval = _copyNullIfExpr(from);
break;
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.252
diff -c -r1.252 equalfuncs.c
*** src/backend/nodes/equalfuncs.c 1 Aug 2005 20:31:08 -0000 1.252
--- src/backend/nodes/equalfuncs.c 2 Oct 2005 23:50:18 -0000
***************
*** 460,465 ****
--- 460,488 ----
return true;
}
+
+ static bool
+ _equalXmlParams(XmlParams *a, XmlParams *b)
+ {
+ COMPARE_STRING_FIELD(name);
+ COMPARE_STRING_FIELD(version);
+ COMPARE_STRING_FIELD(encoding);
+ COMPARE_STRING_FIELD(standalone);
+ }
+
+ static bool
+ _equalXmlExpr(XmlExpr *a, XmlExpr *b)
+ {
+ COMPARE_SCALAR_FIELD(op);
+ COMPARE_NODE_FIELD(xml_args);
+ COMPARE_NODE_FIELD(args);
+ COMPARE_NODE_FIELD(nargs);
+ COMPARE_NODE_FIELD(params);
+ COMPARE_SCALAR_FIELD(level);
+
+ return true;
+ }
+
static bool
_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
{
***************
*** 1899,1904 ****
--- 1922,1933 ----
case T_MinMaxExpr:
retval = _equalMinMaxExpr(a, b);
break;
+ case T_XmlParams:
+ retval = _equalXmlParams(a, b);
+ break;
+ case T_XmlExpr:
+ retval = _equalXmlExpr(a, b);
+ break;
case T_NullIfExpr:
retval = _equalNullIfExpr(a, b);
break;
Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.260
diff -c -r1.260 outfuncs.c
*** src/backend/nodes/outfuncs.c 27 Aug 2005 22:13:43 -0000 1.260
--- src/backend/nodes/outfuncs.c 2 Oct 2005 23:50:19 -0000
***************
*** 875,880 ****
--- 875,904 ----
}
static void
+ _outXmlParams(StringInfo str, XmlParams *node)
+ {
+ WRITE_NODE_TYPE("XMLPARAMS");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_STRING_FIELD(encoding);
+ WRITE_STRING_FIELD(version);
+ WRITE_STRING_FIELD(standalone);
+ }
+
+ static void
+ _outXmlExpr(StringInfo str, XmlExpr *node)
+ {
+ WRITE_NODE_TYPE("XMLEXPR");
+
+ WRITE_ENUM_FIELD(op, XmlExprOp);
+ WRITE_NODE_FIELD(xml_args);
+ WRITE_NODE_FIELD(nargs);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(params);
+ WRITE_INT_FIELD(level);
+ }
+
+ static void
_outNullIfExpr(StringInfo str, NullIfExpr *node)
{
WRITE_NODE_TYPE("NULLIFEXPR");
***************
*** 1925,1930 ****
--- 1949,1957 ----
case T_MinMaxExpr:
_outMinMaxExpr(str, obj);
break;
+ case T_XmlExpr:
+ _outXmlExpr(str, obj);
+ break;
case T_NullIfExpr:
_outNullIfExpr(str, obj);
break;
Index: src/backend/nodes/readfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/readfuncs.c,v
retrieving revision 1.181
diff -c -r1.181 readfuncs.c
*** src/backend/nodes/readfuncs.c 1 Aug 2005 20:31:08 -0000 1.181
--- src/backend/nodes/readfuncs.c 2 Oct 2005 23:50:20 -0000
***************
*** 81,87 ****
/* Read a float field */
#define READ_FLOAT_FIELD(fldname) \
! token = pg_strtok(&length); /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atof(token)
--- 81,87 ----
/* Read a float field */
#define READ_FLOAT_FIELD(fldname) \
! /* skip :fldname */ \
token = pg_strtok(&length); /* get field value */ \
local_node->fldname = atof(token)
***************
*** 674,679 ****
--- 674,707 ----
READ_DONE();
}
+ static XmlParams *
+ _readXmlParams(void)
+ {
+ READ_LOCALS(XmlParams);
+
+ READ_STRING_FIELD(name);
+ READ_STRING_FIELD(encoding);
+ READ_STRING_FIELD(version);
+ READ_STRING_FIELD(standalone);
+
+ READ_DONE();
+ }
+
+ static XmlExpr *
+ _readXmlExpr(void)
+ {
+ READ_LOCALS(XmlExpr);
+
+ READ_ENUM_FIELD(op, XmlExprOp);
+ READ_NODE_FIELD(xml_args);
+ READ_NODE_FIELD(nargs);
+ READ_NODE_FIELD(args);
+ READ_NODE_FIELD(params);
+ READ_INT_FIELD(level);
+
+ READ_DONE();
+ }
+
/*
* _readNullIfExpr
*/
***************
*** 1000,1005 ****
--- 1028,1037 ----
return_value = _readCoalesceExpr();
else if (MATCH("MINMAX", 6))
return_value = _readMinMaxExpr();
+ else if (MATCH("XMLPARAMS", 9))
+ return_value = _readXmlParams();
+ else if (MATCH("XMLEXPR", 7))
+ return_value = _readXmlExpr();
else if (MATCH("NULLIFEXPR", 10))
return_value = _readNullIfExpr();
else if (MATCH("NULLTEST", 8))
Index: src/backend/optimizer/util/clauses.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v
retrieving revision 1.200
diff -c -r1.200 clauses.c
*** src/backend/optimizer/util/clauses.c 3 Jul 2005 21:14:17 -0000 1.200
--- src/backend/optimizer/util/clauses.c 2 Oct 2005 23:50:22 -0000
***************
*** 546,551 ****
--- 546,553 ----
return false;
if (IsA(node, NullIfExpr))
return false;
+ if (IsA(node, XmlExpr))
+ return false;
return expression_tree_walker(node, expression_returns_set_walker,
context);
***************
*** 853,858 ****
--- 855,862 ----
return true;
if (IsA(node, NullIfExpr))
return true;
+ if (IsA(node, XmlExpr))
+ return true;
if (IsA(node, NullTest))
return true;
if (IsA(node, BooleanTest))
***************
*** 2944,2949 ****
--- 2948,2964 ----
return walker(((MinMaxExpr *) node)->args, context);
case T_NullIfExpr:
return walker(((NullIfExpr *) node)->args, context);
+ case T_XmlExpr:
+ {
+ XmlExpr *xexpr = (XmlExpr *) node;
+ if (walker(xexpr->nargs, context))
+ return true;
+ if (walker(xexpr->xml_args, context))
+ return true;
+ if (walker(xexpr->args, context))
+ return true;
+ }
+ break;
case T_NullTest:
return walker(((NullTest *) node)->arg, context);
case T_BooleanTest:
***************
*** 3422,3427 ****
--- 3437,3454 ----
return (Node *) newnode;
}
break;
+ case T_XmlExpr:
+ {
+ XmlExpr *xexpr = (XmlExpr *) node;
+ XmlExpr *newnode;
+
+ FLATCOPY(newnode, xexpr, XmlExpr);
+ MUTATE(newnode->nargs, xexpr->nargs, List *);
+ MUTATE(newnode->xml_args, xexpr->xml_args, List *);
+ MUTATE(newnode->args, xexpr->args, List *);
+ return (Node *) newnode;
+ }
+ break;
case T_NullTest:
{
NullTest *ntest = (NullTest *) node;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.511
diff -c -r2.511 gram.y
*** src/backend/parser/gram.y 23 Sep 2005 22:25:25 -0000 2.511
--- src/backend/parser/gram.y 2 Oct 2005 23:50:28 -0000
***************
*** 91,96 ****
--- 91,101 ----
Node *limitOffset, Node *limitCount);
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
static Node *doNegate(Node *n);
+ static XmlExpr *makeXmlExpr(XmlExprOp op, char *name,
+ List *xml_attr, List *xml_args,
+ List *args, XmlParams *params);
+ static XmlParams *setXmlParam(XmlParams *params, XmlParamOp op, char *value);
+
static void doNegateFloat(Value *v);
%}
***************
*** 128,133 ****
--- 133,141 ----
InsertStmt *istmt;
VariableSetStmt *vsetstmt;
+ XmlExpr *xmlexpr;
+ XmlParams *xmlparams;
+ XmlParam xmlparam;
}
%type <node> stmt schema_stmt
***************
*** 325,330 ****
--- 333,345 ----
%type <boolean> constraints_set_mode
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
+ %type <target> n_expr_el
+ %type <xmlexpr> xmlexpr xml_args
+ %type <list> xmlexpr_list n_expr_list
+ %type <xmlparams> xmlroot_par_list
+ %type <xmlparam> xmlroot_param
+
+
/*
* If you make any token changes, update the keyword table in
***************
*** 377,383 ****
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
! NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
--- 392,398 ----
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
! NAME NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
***************
*** 398,404 ****
SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
! SYSID SYSTEM_P
TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
TO TOAST TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
--- 413,419 ----
SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
! SYSID SYSTEM_P STANDALONE
TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
TO TOAST TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
***************
*** 408,416 ****
UPDATE USER USING
VACUUM VALID VALIDATOR VALUES VARCHAR VARYING
! VERBOSE VIEW VOLATILE
WHEN WHERE WITH WITHOUT WORK WRITE
YEAR_P
--- 423,434 ----
UPDATE USER USING
VACUUM VALID VALIDATOR VALUES VARCHAR VARYING
! VERBOSE VERSION VIEW VOLATILE
WHEN WHERE WITH WITHOUT WORK WRITE
+
+ XMLAGG XMLATTRIBUTES XMLCOMMENT XMLCONCAT XMLELEMENT XMLFOREST
+ XMLPI XMLROOT XMLSERIALIZE
YEAR_P
***************
*** 7408,7413 ****
--- 7426,7560 ----
v->op = IS_LEAST;
$$ = (Node *)v;
}
+ | XMLSERIALIZE '(' xmlexpr ')'
+ {
+ $$ = (Node *)
+ makeXmlExpr(IS_XMLSERIALIZE, NULL, NULL, list_make1($3), NULL, NULL);
+ }
+ ;
+
+ /*
+ * Supporting SQL/XML functions, use only for publishing. For storing results
+ * to tables and using them in pub. functions is neccessery support xml datatype,
+ * one part of xmlexpr will be col with xml value.
+ */
+
+ xmlexpr: XMLAGG '(' a_expr ')' /* for nested xmlagg */
+ {
+ $$ = makeXmlExpr(IS_XMLAGG, NULL, NULL, NULL, list_make1($3), NULL);
+ }
+ | XMLAGG '(' xmlexpr ')'
+ {
+ $$ = makeXmlExpr(IS_XMLAGG, NULL, NULL, list_make1($3), NULL, NULL);
+ }
+ | XMLCOMMENT '(' a_expr ')'
+ {
+ $$ = makeXmlExpr(IS_XMLCOMMENT, NULL, NULL, NULL, list_make1($3), NULL);
+ }
+ | XMLCONCAT '(' xmlexpr_list ')'
+ {
+ $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NULL, $3, NULL, NULL);
+ }
+ | XMLELEMENT '(' NAME ColLabel ',' xml_args ')'
+ {
+ $6->params = setXmlParam($6->params, IS_XMLNAME, $4);
+ $6->op = IS_XMLELEMENT;
+ $$ = $6;
+ }
+ | XMLELEMENT '(' NAME ColLabel ')'
+ {
+ $$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, NULL, NULL, NULL);
+ }
+
+ | XMLELEMENT '(' NAME ColLabel ',' XMLATTRIBUTES '(' n_expr_list ')' ',' xml_args ')'
+ {
+ $11->params = setXmlParam($11->params, IS_XMLNAME, $4);
+ $11->nargs = $8;
+ $11->op = IS_XMLELEMENT;
+ $$ = $11;
+ }
+ | XMLELEMENT '(' NAME ColLabel ',' XMLATTRIBUTES '(' n_expr_list ')' ')'
+ {
+ $$ = makeXmlExpr(IS_XMLELEMENT, $4, $8, NULL, NULL, NULL);
+ }
+ | XMLFOREST '(' n_expr_list ')'
+ {
+ $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NULL, NULL, NULL);
+ }
+ | XMLPI '(' a_expr ')'
+ {
+ $$ = makeXmlExpr(IS_XMLPI, NULL, NULL, NULL, list_make1($3), NULL);
+ }
+ | XMLROOT '(' xmlexpr ',' xmlroot_par_list ')'
+ {
+ $$ = makeXmlExpr(IS_XMLROOT, NULL, NULL, list_make1($3), NULL, $5);
+ }
+ | XMLROOT '(' xmlexpr ')'
+ {
+ $$ = makeXmlExpr(IS_XMLROOT, NULL, NULL, list_make1($3), NULL, NULL);
+ }
+ ;
+
+
+ xmlroot_par_list: xmlroot_param { $$ = setXmlParam(NULL, $1.op, $1.value); }
+ | xmlroot_par_list ',' xmlroot_param { $$ = setXmlParam($1, $3.op, $3.value); }
+ ;
+
+
+ xmlroot_param: VERSION Sconst
+ {
+ $$.op = IS_XMLVERSION;
+ $$.value = $2;
+ }
+ | ENCODING Sconst
+ {
+ $$.op = IS_XMLENCODING;
+ $$.value = $2;
+ }
+ | STANDALONE Sconst
+ {
+ $$.op = IS_XMLSTANDALONE;
+ $$.value = $2;
+ }
+ ;
+
+ xml_args: xmlexpr_list ',' a_expr
+ {
+ $$ = makeXmlExpr(IS_XMLUNKNOWN, NULL, NULL, $1, list_make1($3), NULL);
+ }
+ | a_expr
+ {
+ $$ = makeXmlExpr(IS_XMLUNKNOWN, NULL, NULL, NULL, list_make1($1), NULL);
+ }
+ | xmlexpr_list
+ {
+ $$ = makeXmlExpr(IS_XMLUNKNOWN, NULL, NULL, $1, NULL, NULL);
+ }
+ ;
+
+ xmlexpr_list: xmlexpr { $$ = list_make1($1); }
+ | xmlexpr_list ',' xmlexpr { $$ = lappend($1, $3); }
+ ;
+
+ n_expr_list: n_expr_el { $$ = list_make1($1); }
+ | n_expr_list ',' n_expr_el { $$ = lappend($1, $3); }
+ ;
+
+ n_expr_el: a_expr AS ColLabel
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = $3;
+ $$->indirection = NULL;
+ $$->val = (Node *) $1;
+
+ }
+ | a_expr
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = NULL;
+ $$->indirection = NULL;
+ $$->val = (Node *) $1;
+ }
;
/*
***************
*** 7770,7775 ****
--- 7917,7936 ----
$$->indirection = NIL;
$$->val = (Node *)n;
}
+ | xmlexpr AS ColLabel
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = $3;
+ $$->indirection = NIL;
+ $$->val = (Node *)$1;
+ }
+ | xmlexpr
+ {
+ $$ = makeNode(ResTarget);
+ $$->name = NULL;
+ $$->indirection = NIL;
+ $$->val = (Node *)$1;
+ }
;
update_target_list:
***************
*** 8240,8245 ****
--- 8401,8407 ----
| SHOW
| SIMPLE
| STABLE
+ | STANDALONE
| START
| STATEMENT
| STATISTICS
***************
*** 8279,8284 ****
--- 8441,8448 ----
| WRITE
| YEAR_P
| ZONE
+ | NAME
+ | VERSION
;
/* Column identifier --- keywords that can be column, table, etc names.
***************
*** 8329,8334 ****
--- 8493,8507 ----
| TREAT
| TRIM
| VARCHAR
+ | XMLAGG
+ | XMLATTRIBUTES
+ | XMLELEMENT
+ | XMLCOMMENT
+ | XMLCONCAT
+ | XMLFOREST
+ | XMLROOT
+ | XMLSERIALIZE
+ | XMLPI
;
/* Function identifier --- keywords that can be function names.
***************
*** 8914,8917 ****
--- 9087,9138 ----
}
}
+ static XmlParams *
+ setXmlParam(XmlParams *params, XmlParamOp op, char *value)
+ {
+ if (value == NULL)
+ return params;
+
+ if (params == NULL)
+ {
+ params = makeNode(XmlParams);
+ params->encoding = NULL;
+ params->name = NULL;
+ params->version = NULL;
+ params->standalone = NULL;
+ }
+ switch (op)
+ {
+ case IS_XMLENCODING:
+ params->encoding = value;
+ break;
+ case IS_XMLVERSION:
+ params->version = value;
+ break;
+ case IS_XMLNAME:
+ params->name = value;
+ break;
+ case IS_XMLSTANDALONE:
+ params->standalone = value;
+ break;
+ }
+ return params;
+ }
+
+ static XmlExpr *
+ makeXmlExpr(XmlExprOp op, char *name, List *nargs, List *xml_args,
+ List *args, XmlParams *params)
+ {
+
+ XmlExpr *x = makeNode(XmlExpr);
+ x->op = op;
+ x->nargs = nargs;
+ x->xml_args = xml_args;
+ x->args = args;
+ x->level = 0;
+ x->params = setXmlParam(params, IS_XMLNAME, name);
+ return x;
+ }
+
+
#include "scan.c"
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.165
diff -c -r1.165 keywords.c
*** src/backend/parser/keywords.c 23 Aug 2005 22:40:27 -0000 1.165
--- src/backend/parser/keywords.c 2 Oct 2005 23:50:28 -0000
***************
*** 213,218 ****
--- 213,219 ----
{"mode", MODE},
{"month", MONTH_P},
{"move", MOVE},
+ {"name", NAME},
{"names", NAMES},
{"national", NATIONAL},
{"natural", NATURAL},
***************
*** 306,311 ****
--- 307,313 ----
{"smallint", SMALLINT},
{"some", SOME},
{"stable", STABLE},
+ {"standalone", STANDALONE},
{"start", START},
{"statement", STATEMENT},
{"statistics", STATISTICS},
***************
*** 354,359 ****
--- 356,362 ----
{"varchar", VARCHAR},
{"varying", VARYING},
{"verbose", VERBOSE},
+ {"version", VERSION},
{"view", VIEW},
{"volatile", VOLATILE},
{"when", WHEN},
***************
*** 362,367 ****
--- 365,379 ----
{"without", WITHOUT},
{"work", WORK},
{"write", WRITE},
+ {"xmlagg", XMLAGG},
+ {"xmlattributes", XMLATTRIBUTES},
+ {"xmlcomment", XMLCOMMENT},
+ {"xmlconcat", XMLCONCAT},
+ {"xmlelement", XMLELEMENT},
+ {"xmlforest", XMLFOREST},
+ {"xmlpi", XMLPI},
+ {"xmlroot", XMLROOT},
+ {"xmlserialize", XMLSERIALIZE},
{"year", YEAR_P},
{"zone", ZONE},
};
Index: src/backend/parser/parse_expr.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.184
diff -c -r1.184 parse_expr.c
*** src/backend/parser/parse_expr.c 26 Jun 2005 22:05:39 -0000 1.184
--- src/backend/parser/parse_expr.c 2 Oct 2005 23:50:30 -0000
***************
*** 54,59 ****
--- 54,60 ----
static Node *transformRowExpr(ParseState *pstate, RowExpr *r);
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
+ static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
***************
*** 70,75 ****
--- 71,77 ----
static Expr *make_distinct_op(ParseState *pstate, List *opname,
Node *ltree, Node *rtree);
+ extern char *FigureColname(Node *e);
/*
* transformExpr -
***************
*** 213,219 ****
case T_MinMaxExpr:
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break;
!
case T_NullTest:
{
NullTest *n = (NullTest *) expr;
--- 215,225 ----
case T_MinMaxExpr:
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break;
!
! case T_XmlExpr:
! result = transformXmlExpr(pstate, (XmlExpr *) expr);
! break;
!
case T_NullTest:
{
NullTest *n = (NullTest *) expr;
***************
*** 1272,1277 ****
--- 1278,1382 ----
return (Node *) newm;
}
+
+ static Node *
+ transformList(ParseState *pstate, List *list)
+ {
+ List *newlist = NIL;
+ ListCell *arg;
+ foreach(arg, list)
+ {
+ Node *e = (Node*)lfirst(arg);
+ Node *te = transformExpr(pstate, e);
+ newlist = lappend(newlist, te);
+ }
+ return (Node *)newlist;
+ }
+
+ static Node *
+ transformXmlList(ParseState *pstate, List *list, int level)
+ {
+ List *newlist = NIL;
+ ListCell *arg;
+ foreach(arg, list)
+ {
+ Node *e = (Node*)lfirst(arg);
+ ((XmlExpr *)e)->level = level;
+ Node *te = transformExpr(pstate, e);
+ newlist = lappend(newlist, te);
+ }
+ return (Node *)newlist;
+ }
+
+
+ /* transformation named expressions */
+
+ static Node *
+ transformNPList(ParseState *pstate, List *list)
+ {
+ List *newlist = NIL;
+ ListCell *arg;
+ foreach(arg, list)
+ {
+ ResTarget *r = (ResTarget *) lfirst(arg);
+ Node *expr = transformExpr(pstate, r->val);
+ char *colname = r->name;
+ if (colname == NULL)
+ colname = FigureColname(r->val);
+ newlist = lappend(newlist,
+ makeTargetEntry((Expr *) expr, 0, colname, false));
+ }
+ return (Node *)newlist;
+ }
+
+ static Node *
+ transformXmlExpr(ParseState *pstate, XmlExpr *x)
+ {
+ XmlExpr *newx = makeNode(XmlExpr);
+
+ if (x->op == IS_XMLAGG)
+ {
+ /* set level */
+ if (x->xml_args)
+ {
+ XmlExpr *p = (XmlExpr *) linitial(x->xml_args);
+ p->level = x->level + 1;
+
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = SystemFuncName("xmlagg");
+ n->args = x->xml_args;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+ return transformExpr(pstate, (Node *) n);
+
+ } else
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = SystemFuncName("xmlagg");
+ n->args = x->args;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+
+ return transformExpr(pstate, (Node *) n);
+
+ }
+ }
+
+
+ /* Mechanismem transformace dokazu vnutit podrizenym xmlfunkcim level,
+ * v budoucnu napriklad ukazatel na hash s tagy a attributy */
+
+ newx->nargs = (List *)transformNPList(pstate, x->nargs);
+ newx->xml_args = (List *)transformXmlList(pstate, x->xml_args, x->level+1);
+ newx->args = (List *)transformList(pstate, x->args);
+
+ newx->params = x->params;
+ newx->op = x->op;
+ newx->level = x->level;
+
+ return (Node *) newx;
+ }
+
static Node *
transformBooleanTest(ParseState *pstate, BooleanTest *b)
{
***************
*** 1549,1554 ****
--- 1654,1662 ----
case T_MinMaxExpr:
type = ((MinMaxExpr *) expr)->minmaxtype;
break;
+ case T_XmlExpr:
+ type = TEXTOID;
+ break;
case T_NullIfExpr:
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
break;
Index: src/backend/parser/parse_target.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_target.c,v
retrieving revision 1.137
diff -c -r1.137 parse_target.c
*** src/backend/parser/parse_target.c 26 Jun 2005 22:05:40 -0000 1.137
--- src/backend/parser/parse_target.c 2 Oct 2005 23:50:30 -0000
***************
*** 1135,1140 ****
--- 1135,1173 ----
return 2;
}
break;
+ case T_XmlExpr:
+ /* make SQL/XML functions act like a regular function */
+ switch (((XmlExpr*) node)->op)
+ {
+ case IS_XMLCOMMENT:
+ *name = "xmlcomment";
+ return 2;
+ case IS_XMLCONCAT:
+ *name = "xmlconcat";
+ return 2;
+ case IS_XMLELEMENT:
+ *name = "xmlelement";
+ return 2;
+ case IS_XMLFOREST:
+ *name = "xmlforest";
+ return 2;
+ case IS_XMLPI:
+ *name = "xmlpi";
+ return 2;
+ case IS_XMLROOT:
+ *name = "xmlroot";
+ return 2;
+ case IS_XMLSERIALIZE:
+ *name = "xmlserialize";
+ return 2;
+ case IS_XMLUNKNOWN:
+ *name = "unknown xml function";
+ return 2;
+ case IS_XMLAGG:
+ *name = "xmlagg";
+ return 2;
+ }
+ break;
default:
break;
}
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.205
diff -c -r1.205 ruleutils.c
*** src/backend/utils/adt/ruleutils.c 1 Aug 2005 20:31:12 -0000 1.205
--- src/backend/utils/adt/ruleutils.c 2 Oct 2005 23:50:34 -0000
***************
*** 2793,2798 ****
--- 2793,2799 ----
case T_CoalesceExpr:
case T_MinMaxExpr:
case T_NullIfExpr:
+ case T_XmlExpr:
case T_Aggref:
case T_FuncExpr:
/* function-like: name(..) or name[..] */
***************
*** 2901,2906 ****
--- 2902,2908 ----
case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
+ case T_XmlExpr: /* own parentheses */
case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */
return true;
***************
*** 2949,2954 ****
--- 2951,2957 ----
case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
+ case T_XmlExpr: /* own parentheses */
case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */
return true;
***************
*** 3531,3537 ****
appendStringInfoChar(buf, ')');
}
break;
!
case T_NullTest:
{
NullTest *ntest = (NullTest *) node;
--- 3534,3576 ----
appendStringInfoChar(buf, ')');
}
break;
!
! case T_XmlExpr:
! {
! XmlExpr *xexpr = (XmlExpr *) node;
! switch (xexpr->op)
! {
! case IS_XMLCOMMENT:
! appendStringInfo(buf,"XMLCOMMENT(");
! break;
! case IS_XMLCONCAT:
! appendStringInfo(buf,"XMLCONCAT(");
! break;
! case IS_XMLELEMENT:
! appendStringInfo(buf,"XMLELEMENT(");
! break;
! case IS_XMLFOREST:
! appendStringInfo(buf,"XMLFOREST(");
! break;
! case IS_XMLPI:
! appendStringInfo(buf,"XMLPI(");
! break;
! case IS_XMLROOT:
! appendStringInfo(buf,"XMLROOT(");
! break;
! case IS_XMLSERIALIZE:
! appendStringInfo(buf,"XMLSERIALIZE(");
! break;
! case IS_XMLUNKNOWN: /* quite compiler warnings */
! break;
! }
! get_rule_expr((Node *) xexpr->nargs, context, true);
! get_rule_expr((Node *) xexpr->xml_args, context, true);
! get_rule_expr((Node *) xexpr->args, context, true);
! appendStringInfoChar(buf, ')');
! }
! break;
!
case T_NullTest:
{
NullTest *ntest = (NullTest *) node;
Index: src/backend/utils/adt/varchar.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/varchar.c,v
retrieving revision 1.112
diff -c -r1.112 varchar.c
*** src/backend/utils/adt/varchar.c 29 Jul 2005 12:59:15 -0000 1.112
--- src/backend/utils/adt/varchar.c 2 Oct 2005 23:50:34 -0000
***************
*** 25,30 ****
--- 25,31 ----
#include "mb/pg_wchar.h"
+ #include "nodes/execnodes.h"
/*
* CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
***************
*** 805,807 ****
--- 806,896 ----
return result;
}
+
+ /*
+ * Temp. aux. func for xmlagg function
+ *
+ */
+
+
+ typedef struct
+ {
+ int32 size; // varlena requirment
+ int max;
+ int offset;
+ bool isNull;
+ char data[1];
+ } data;
+
+
+ static data *
+ makeData(AggState *aggstate, int sz)
+ {
+ data *d = (data *) MemoryContextAlloc(aggstate->aggcontext, sz+sizeof(data));
+ d->size = sz+sizeof(data);
+ d->max = sz;
+ d->offset = 0;
+ d->data[0] = '\0';
+ d->isNull = true;
+ return d;
+ }
+
+ static data *
+ reallocData(AggState *aggstate, data *d, int sz)
+ {
+ data *nd = makeData(aggstate, sz);
+ memcpy(nd->data, d->data, d->offset);
+ nd->offset = d->offset;
+ nd->isNull = d->isNull;
+ return nd;
+ }
+
+
+ Datum
+ text_xmlagg_accum(PG_FUNCTION_ARGS)
+ {
+ data *d;
+ if (PG_ARGISNULL(0))
+ d = NULL;
+ else
+ d = (data *) PG_GETARG_POINTER(0);
+ if (!d)
+ d = makeData((AggState *) fcinfo->context, 1000);
+
+ if (!PG_ARGISNULL(1))
+ {
+ text *str = PG_GETARG_TEXT_P(1);
+ d->isNull = false;
+ int len = VARSIZE(str) - VARHDRSZ;
+ while (d->max < d->offset + len)
+ {
+ int nmax = d->max *2;
+ data *dn = reallocData((AggState *) fcinfo->context, d, nmax);
+ d = dn;
+ }
+ memcpy(&d->data[d->offset], VARDATA(str), len);
+ d->offset += len;
+ }
+
+ PG_RETURN_POINTER(d);
+ }
+
+ Datum
+ text_xmlagg(PG_FUNCTION_ARGS)
+ {
+ data *d;
+
+ if (PG_ARGISNULL(0))
+ elog(ERROR, "internal error");
+
+ d = (data *) PG_GETARG_POINTER(0);
+ if (d->isNull)
+ PG_RETURN_NULL();
+ else
+ {
+ text *str = palloc(d->offset+VARHDRSZ);
+ VARATT_SIZEP(str) = d->offset+VARHDRSZ;
+ memcpy(VARDATA(str), d->data, d->offset);
+ PG_RETURN_TEXT_P(str);
+ }
+ }
Index: src/include/catalog/pg_aggregate.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_aggregate.h,v
retrieving revision 1.51
diff -c -r1.51 pg_aggregate.h
*** src/include/catalog/pg_aggregate.h 14 Apr 2005 01:38:20 -0000 1.51
--- src/include/catalog/pg_aggregate.h 2 Oct 2005 23:50:35 -0000
***************
*** 175,180 ****
--- 175,183 ----
DATA(insert ( 2242 bitand - 0 1560 _null_ ));
DATA(insert ( 2243 bitor - 0 1560 _null_ ));
+ /* xmlagg */
+ DATA(insert ( 1079 text_xmlagg_accum text_xmlagg 0 25 _null_ ));
+
/*
* prototypes for functions in pg_aggregate.c
*/
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.385
diff -c -r1.385 pg_proc.h
*** src/include/catalog/pg_proc.h 16 Sep 2005 05:35:40 -0000 1.385
--- src/include/catalog/pg_proc.h 2 Oct 2005 23:50:42 -0000
***************
*** 807,813 ****
DESCR("convert name to char(n)");
DATA(insert OID = 409 ( name PGNSP PGUID 12 f f t f i 1 19 "1042" _null_ _null_ _null_ bpchar_name
-_null_ ));
DESCR("convert char(n) to name");
-
DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" _null_ _null_ _null_
hashgettuple- _null_ ));
DESCR("hash(internal)");
DATA(insert OID = 637 ( hashgetmulti PGNSP PGUID 12 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_
hashgetmulti- _null_ ));
--- 807,812 ----
***************
*** 2710,2715 ****
--- 2709,2719 ----
DESCR("AVG(int4) transition function");
DATA(insert OID = 1964 ( int8_avg PGNSP PGUID 12 f f t f i 1 1700 "1016" _null_ _null_ _null_ int8_avg -
_null_));
DESCR("AVG(int) aggregate final function");
+ DATA(insert OID = 1136 ( text_xmlagg_accum PGNSP PGUID 12 f f f f i 2 25 "25 25" _null_ _null_ _null_
text_xmlagg_accum- _null_ ));
+ DESCR("trans fce for fast string");
+ DATA(insert OID = 1137 ( text_xmlagg PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ text_xmlagg -
_null_));
+ DESCR("final fce for fast string");
+
/* To ASCII conversion */
DATA(insert OID = 1845 ( to_ascii PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ to_ascii_default -
_null_));
***************
*** 3135,3140 ****
--- 3139,3146 ----
DATA(insert OID = 2158 ( stddev PGNSP PGUID 12 t f f f i 1 701 "701" _null_ _null_ _null_
aggregate_dummy- _null_ ));
DATA(insert OID = 2159 ( stddev PGNSP PGUID 12 t f f f i 1 1700 "1700" _null_ _null_ _null_
aggregate_dummy- _null_ ));
+ DATA(insert OID = 1079 ( xmlagg PGNSP PGUID 12 t f f f i 1 25 "25" _null_ _null_ _null_
aggregate_dummy- _null_ ));
+
DATA(insert OID = 2160 ( text_pattern_lt PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_
text_pattern_lt- _null_ ));
DATA(insert OID = 2161 ( text_pattern_le PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_
text_pattern_le- _null_ ));
DATA(insert OID = 2162 ( text_pattern_eq PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_
text_pattern_eq- _null_ ));
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.138
diff -c -r1.138 execnodes.h
*** src/include/nodes/execnodes.h 25 Sep 2005 19:37:35 -0000 1.138
--- src/include/nodes/execnodes.h 2 Oct 2005 23:50:43 -0000
***************
*** 686,691 ****
--- 686,710 ----
} MinMaxExprState;
/* ----------------
+ * MinMaxExprState node
+ * ----------------
+ */
+ typedef struct XmlExprState
+ {
+ ExprState xprstate;
+ XmlExprOp op;
+ List *nargs; /* the named arguments */
+ List *args; /* the arguments, only last should be non xml */
+ List *xml_args; /* xml arguments, result is always cstring */
+ Oid *nargs_tcache;
+ char **nargs_ncache;
+ Oid arg_typeId;
+ XmlParams *params;
+ int level; /* info about tabs now, shared tag's table in future */
+ } XmlExprState;
+
+
+ /* ----------------
* CoerceToDomainState node
* ----------------
*/
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.175
diff -c -r1.175 nodes.h
*** src/include/nodes/nodes.h 1 Aug 2005 20:31:15 -0000 1.175
--- src/include/nodes/nodes.h 2 Oct 2005 23:50:44 -0000
***************
*** 137,142 ****
--- 137,144 ----
T_RangeTblRef,
T_JoinExpr,
T_FromExpr,
+ T_XmlExpr,
+ T_XmlParams,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
***************
*** 163,169 ****
T_MinMaxExprState,
T_CoerceToDomainState,
T_DomainConstraintState,
!
/*
* TAGS FOR PLANNER NODES (relation.h)
*/
--- 165,172 ----
T_MinMaxExprState,
T_CoerceToDomainState,
T_DomainConstraintState,
! T_XmlExprState,
!
/*
* TAGS FOR PLANNER NODES (relation.h)
*/
Index: src/include/nodes/primnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/primnodes.h,v
retrieving revision 1.108
diff -c -r1.108 primnodes.h
*** src/include/nodes/primnodes.h 26 Jun 2005 22:05:41 -0000 1.108
--- src/include/nodes/primnodes.h 2 Oct 2005 23:50:44 -0000
***************
*** 675,680 ****
--- 675,731 ----
} MinMaxExpr;
/*
+ * XmlExpr - holder SQL/XML functions xmlroot, xmlforest, xmlelement, xmlpi,
+ * xmlcomment, xmlconcat
+ */
+ typedef enum XmlExprOp
+ {
+ IS_XMLUNKNOWN = 0,
+ IS_XMLAGG,
+ IS_XMLROOT,
+ IS_XMLELEMENT,
+ IS_XMLFOREST,
+ IS_XMLPI,
+ IS_XMLCOMMENT,
+ IS_XMLCONCAT,
+ IS_XMLSERIALIZE
+ } XmlExprOp;
+
+ typedef enum XmlParamOp
+ {
+ IS_XMLENCODING,
+ IS_XMLVERSION,
+ IS_XMLNAME,
+ IS_XMLSTANDALONE
+ } XmlParamOp;
+
+ typedef struct XmlParam
+ {
+ XmlParamOp op;
+ char *value;
+ } XmlParam;
+
+ typedef struct XmlParams
+ {
+ NodeTag type;
+ char *encoding;
+ char *version;
+ char *name;
+ char *standalone;
+ } XmlParams;
+
+ typedef struct XmlExpr
+ {
+ Expr xpr;
+ XmlExprOp op; /* function to execute */
+ List *xml_args; /* xml arguments */
+ List *nargs; /* named arguments */
+ List *args;
+ XmlParams *params; /* non xml argument */
+ int level;
+ } XmlExpr;
+
+ /*
* NullIfExpr - a NULLIF expression
*
* Like DistinctExpr, this is represented the same as an OpExpr referencing
***************
*** 940,943 ****
--- 991,995 ----
Node *quals; /* qualifiers on join, if any */
} FromExpr;
+
#endif /* PRIMNODES_H */