function xmlagg.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.207 2007/01/14 13:11:53 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.208 2007/01/20 09:27:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
StringInfoData buf;
Datum value;
bool isnull;
- char *str;
ListCell *arg;
ListCell *narg;
int i;
switch (xexpr->op)
{
case IS_XMLCONCAT:
- initStringInfo(&buf);
- foreach(arg, xmlExpr->args)
{
- ExprState *e = (ExprState *) lfirst(arg);
+ List *values = NIL;
- value = ExecEvalExpr(e, econtext, &isnull, NULL);
- if (!isnull)
+ foreach(arg, xmlExpr->args)
+ {
+ ExprState *e = (ExprState *) lfirst(arg);
+
+ value = ExecEvalExpr(e, econtext, &isnull, NULL);
+ if (!isnull)
+ values = lappend(values, DatumGetPointer(value));
+ }
+
+ if (list_length(values) > 0)
{
- /* we know the value is XML type */
- str = DatumGetCString(DirectFunctionCall1(xml_out,
- value));
- appendStringInfoString(&buf, str);
- pfree(str);
*isNull = false;
+ return PointerGetDatum(xmlconcat(values));
}
}
break;
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.19 2007/01/19 16:58:46 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.20 2007/01/20 09:27:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
}
+
+/*
+ * TODO: xmlconcat needs to merge the notations and unparsed entities
+ * of the argument values. Not very important in practice, though.
+ */
+xmltype *
+xmlconcat(List *args)
+{
+#ifdef USE_LIBXML
+ StringInfoData buf;
+ ListCell *v;
+
+ int global_standalone = 1;
+ xmlChar *global_version = NULL;
+ bool global_version_no_value = false;
+
+ initStringInfo(&buf);
+ foreach(v, args)
+ {
+ size_t len;
+ xmlChar *version;
+ int standalone;
+ xmltype *x = DatumGetXmlP(PointerGetDatum(lfirst(v)));
+ char *str;
+
+ len = VARSIZE(x) - VARHDRSZ;
+ str = palloc(len + 1);
+ memcpy(str, VARDATA(x), len);
+ str[len] = '\0';
+
+ parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
+
+ if (standalone == 0 && global_standalone == 1)
+ global_standalone = 0;
+ if (standalone < 0)
+ global_standalone = -1;
+
+ if (!global_version)
+ global_version = xmlStrdup(version);
+ else if (version && xmlStrcmp(version, global_version) != 0)
+ global_version_no_value = true;
+
+ appendStringInfoString(&buf, str + len);
+ pfree(str);
+ }
+
+ if (!global_version_no_value || global_standalone >= 0)
+ {
+ StringInfoData buf2;
+
+ initStringInfo(&buf2);
+
+ if (!global_version_no_value && global_version)
+ appendStringInfo(&buf2, "<?xml version=\"%s\"", global_version);
+ else
+ appendStringInfo(&buf2, "<?xml version=\"%s\"", PG_XML_DEFAULT_VERSION);
+
+ if (global_standalone == 1)
+ appendStringInfoString(&buf2, " standalone=\"yes\"");
+ else if (global_standalone == 0)
+ appendStringInfoString(&buf2, " standalone=\"no\"");
+
+ appendStringInfoString(&buf2, "?>");
+
+ appendStringInfoString(&buf2, buf.data);
+ buf = buf2;
+ }
+
+ return stringinfo_to_xmltype(&buf);
+#else
+ NO_XML_SUPPORT();
+ return NULL;
+#endif
+}
+
+
+/*
+ * XMLAGG support
+ */
+Datum
+xmlconcat2(PG_FUNCTION_ARGS)
+{
+ if (PG_ARGISNULL(0))
+ {
+ if (PG_ARGISNULL(1))
+ PG_RETURN_NULL();
+ else
+ PG_RETURN_XML_P(PG_GETARG_XML_P(1));
+ }
+ else if (PG_ARGISNULL(1))
+ PG_RETURN_XML_P(PG_GETARG_XML_P(0));
+ else
+ PG_RETURN_XML_P(xmlconcat(list_make2(PG_GETARG_XML_P(0), PG_GETARG_XML_P(1))));
+}
+
+
Datum
texttoxml(PG_FUNCTION_ARGS)
{
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.372 2007/01/16 21:41:13 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.373 2007/01/20 09:27:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200701161
+#define CATALOG_VERSION_NO 200701201
#endif
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_aggregate.h,v 1.59 2007/01/05 22:19:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_aggregate.h,v 1.60 2007/01/20 09:27:19 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
DATA(insert ( 2242 bitand - 0 1560 _null_ ));
DATA(insert ( 2243 bitor - 0 1560 _null_ ));
+/* xml */
+DATA(insert ( 2901 xmlconcat2 - 0 142 _null_ ));
+
/*
* prototypes for functions in pg_aggregate.c
*/
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.437 2007/01/16 21:41:13 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.438 2007/01/20 09:27:19 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
DESCR("I/O");
DATA(insert OID = 2899 ( xml_send PGNSP PGUID 12 f f t f s 1 17 "142" _null_ _null_ _null_ xml_send - _null_ ));
DESCR("I/O");
+DATA(insert OID = 2900 ( xmlconcat2 PGNSP PGUID 12 f f f f i 2 142 "142 142" _null_ _null_ _null_ xmlconcat2 - _null_ ));
+DESCR("aggregate transition function");
+DATA(insert OID = 2901 ( xmlagg PGNSP PGUID 12 t f f f i 1 142 "142" _null_ _null_ _null_ aggregate_dummy - _null_ ));
+DESCR("concatenate XML values");
/*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.11 2007/01/19 16:58:46 petere Exp $
+ * $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.12 2007/01/20 09:27:20 petere Exp $
*
*-------------------------------------------------------------------------
*/
extern Datum xml_recv(PG_FUNCTION_ARGS);
extern Datum xml_send(PG_FUNCTION_ARGS);
extern Datum xmlcomment(PG_FUNCTION_ARGS);
+extern Datum xmlconcat2(PG_FUNCTION_ARGS);
extern Datum texttoxml(PG_FUNCTION_ARGS);
extern Datum xmlvalidate(PG_FUNCTION_ARGS);
+extern xmltype *xmlconcat(List *args);
extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
SELECT xmlconcat('bad', '<syntax');
ERROR: invalid XML content
DETAIL: Expected '>'
+SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
+ xmlconcat
+---------------------------------------------------
+ <?xml version="1.1" standalone="no"?><foo/><bar/>
+(1 row)
+
SELECT xmlelement(name element,
xmlattributes (1 as one, 'deuce' as two),
'content');
(1 row)
SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
- xmlroot
+ xmlroot
---------
<foo/>
SELECT '<>' IS NOT DOCUMENT;
ERROR: invalid XML content
DETAIL: Element name not found
+SELECT xmlagg(data) FROM xmltest;
+ xmlagg
+--------------------------------------
+ <value>one</value><value>two</value>
+(1 row)
+
+SELECT xmlagg(data) FROM xmltest WHERE id > 10;
+ xmlagg
+--------
+
+(1 row)
+
+SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
+ xmlelement
+--------------------------------------------------------------------------------------------------------------------------------
+ <employees><name>sharon</name><name>sam</name><name>bill</name><name>jeff</name><name>cim</name><name>linda</name></employees>
+(1 row)
+
-- Check mapping SQL identifier to XML name
SELECT xmlpi(name ":::_xml_abc135.%-&_");
xmlpi
ERROR: argument of XMLCONCAT must be type xml, not type integer
SELECT xmlconcat('bad', '<syntax');
ERROR: no XML support in this installation
+SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
+ERROR: no XML support in this installation
SELECT xmlelement(name element,
xmlattributes (1 as one, 'deuce' as two),
'content');
ERROR: no XML support in this installation
SELECT '<>' IS NOT DOCUMENT;
ERROR: no XML support in this installation
+SELECT xmlagg(data) FROM xmltest;
+ xmlagg
+--------
+
+(1 row)
+
+SELECT xmlagg(data) FROM xmltest WHERE id > 10;
+ xmlagg
+--------
+
+(1 row)
+
+SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
+ERROR: no XML support in this installation
-- Check mapping SQL identifier to XML name
SELECT xmlpi(name ":::_xml_abc135.%-&_");
ERROR: no XML support in this installation
SELECT xmlconcat('hello', 'you');
SELECT xmlconcat(1, 2);
SELECT xmlconcat('bad', '<syntax');
+SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
SELECT xmlelement(name element,
SELECT '<>' IS NOT DOCUMENT;
+SELECT xmlagg(data) FROM xmltest;
+SELECT xmlagg(data) FROM xmltest WHERE id > 10;
+SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
+
+
-- Check mapping SQL identifier to XML name
SELECT xmlpi(name ":::_xml_abc135.%-&_");