mirror of
https://github.com/postgres/postgres.git
synced 2025-08-24 09:27:52 +03:00
Fix xmlconcat by properly merging the XML declarations. Add aggregate
function xmlagg.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2651,7 +2651,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
|
||||
StringInfoData buf;
|
||||
Datum value;
|
||||
bool isnull;
|
||||
char *str;
|
||||
ListCell *arg;
|
||||
ListCell *narg;
|
||||
int i;
|
||||
@@ -2663,20 +2662,22 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
|
||||
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;
|
||||
|
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user