aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/xml.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2007-01-20 09:27:20 +0000
committerPeter Eisentraut <peter_e@gmx.net>2007-01-20 09:27:20 +0000
commitb4c8d49036b971d892b2dfe1c71d3f0cee116e7f (patch)
treea3db0050c3ea8815e44b2a4014502bfaa9822796 /src/backend/utils/adt/xml.c
parent9a83bd50b7ec61140fc400350b3e5b1f0cd15722 (diff)
downloadpostgresql-b4c8d49036b971d892b2dfe1c71d3f0cee116e7f.tar.gz
postgresql-b4c8d49036b971d892b2dfe1c71d3f0cee116e7f.zip
Fix xmlconcat by properly merging the XML declarations. Add aggregate
function xmlagg.
Diffstat (limited to 'src/backend/utils/adt/xml.c')
-rw-r--r--src/backend/utils/adt/xml.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 5f3fafe1e70..fdf7f8e0a91 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -359,6 +359,102 @@ xmlcomment(PG_FUNCTION_ARGS)
}
+
+/*
+ * 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)
{