Skip to content

Commit b4c8d49

Browse files
committed
Fix xmlconcat by properly merging the XML declarations. Add aggregate
function xmlagg.
1 parent 9a83bd5 commit b4c8d49

File tree

9 files changed

+171
-19
lines changed

9 files changed

+171
-19
lines changed

src/backend/executor/execQual.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.207 2007/01/14 13:11:53 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.208 2007/01/20 09:27:19 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2651,7 +2651,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
26512651
StringInfoData buf;
26522652
Datum value;
26532653
bool isnull;
2654-
char *str;
26552654
ListCell *arg;
26562655
ListCell *narg;
26572656
int i;
@@ -2663,20 +2662,22 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
26632662
switch (xexpr->op)
26642663
{
26652664
case IS_XMLCONCAT:
2666-
initStringInfo(&buf);
2667-
foreach(arg, xmlExpr->args)
26682665
{
2669-
ExprState *e = (ExprState *) lfirst(arg);
2666+
List *values = NIL;
26702667

2671-
value = ExecEvalExpr(e, econtext, &isnull, NULL);
2672-
if (!isnull)
2668+
foreach(arg, xmlExpr->args)
2669+
{
2670+
ExprState *e = (ExprState *) lfirst(arg);
2671+
2672+
value = ExecEvalExpr(e, econtext, &isnull, NULL);
2673+
if (!isnull)
2674+
values = lappend(values, DatumGetPointer(value));
2675+
}
2676+
2677+
if (list_length(values) > 0)
26732678
{
2674-
/* we know the value is XML type */
2675-
str = DatumGetCString(DirectFunctionCall1(xml_out,
2676-
value));
2677-
appendStringInfoString(&buf, str);
2678-
pfree(str);
26792679
*isNull = false;
2680+
return PointerGetDatum(xmlconcat(values));
26802681
}
26812682
}
26822683
break;

src/backend/utils/adt/xml.c

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.19 2007/01/19 16:58:46 petere Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.20 2007/01/20 09:27:19 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -359,6 +359,102 @@ xmlcomment(PG_FUNCTION_ARGS)
359359
}
360360

361361

362+
363+
/*
364+
* TODO: xmlconcat needs to merge the notations and unparsed entities
365+
* of the argument values. Not very important in practice, though.
366+
*/
367+
xmltype *
368+
xmlconcat(List *args)
369+
{
370+
#ifdef USE_LIBXML
371+
StringInfoData buf;
372+
ListCell *v;
373+
374+
int global_standalone = 1;
375+
xmlChar *global_version = NULL;
376+
bool global_version_no_value = false;
377+
378+
initStringInfo(&buf);
379+
foreach(v, args)
380+
{
381+
size_t len;
382+
xmlChar *version;
383+
int standalone;
384+
xmltype *x = DatumGetXmlP(PointerGetDatum(lfirst(v)));
385+
char *str;
386+
387+
len = VARSIZE(x) - VARHDRSZ;
388+
str = palloc(len + 1);
389+
memcpy(str, VARDATA(x), len);
390+
str[len] = '\0';
391+
392+
parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
393+
394+
if (standalone == 0 && global_standalone == 1)
395+
global_standalone = 0;
396+
if (standalone < 0)
397+
global_standalone = -1;
398+
399+
if (!global_version)
400+
global_version = xmlStrdup(version);
401+
else if (version && xmlStrcmp(version, global_version) != 0)
402+
global_version_no_value = true;
403+
404+
appendStringInfoString(&buf, str + len);
405+
pfree(str);
406+
}
407+
408+
if (!global_version_no_value || global_standalone >= 0)
409+
{
410+
StringInfoData buf2;
411+
412+
initStringInfo(&buf2);
413+
414+
if (!global_version_no_value && global_version)
415+
appendStringInfo(&buf2, "<?xml version=\"%s\"", global_version);
416+
else
417+
appendStringInfo(&buf2, "<?xml version=\"%s\"", PG_XML_DEFAULT_VERSION);
418+
419+
if (global_standalone == 1)
420+
appendStringInfoString(&buf2, " standalone=\"yes\"");
421+
else if (global_standalone == 0)
422+
appendStringInfoString(&buf2, " standalone=\"no\"");
423+
424+
appendStringInfoString(&buf2, "?>");
425+
426+
appendStringInfoString(&buf2, buf.data);
427+
buf = buf2;
428+
}
429+
430+
return stringinfo_to_xmltype(&buf);
431+
#else
432+
NO_XML_SUPPORT();
433+
return NULL;
434+
#endif
435+
}
436+
437+
438+
/*
439+
* XMLAGG support
440+
*/
441+
Datum
442+
xmlconcat2(PG_FUNCTION_ARGS)
443+
{
444+
if (PG_ARGISNULL(0))
445+
{
446+
if (PG_ARGISNULL(1))
447+
PG_RETURN_NULL();
448+
else
449+
PG_RETURN_XML_P(PG_GETARG_XML_P(1));
450+
}
451+
else if (PG_ARGISNULL(1))
452+
PG_RETURN_XML_P(PG_GETARG_XML_P(0));
453+
else
454+
PG_RETURN_XML_P(xmlconcat(list_make2(PG_GETARG_XML_P(0), PG_GETARG_XML_P(1))));
455+
}
456+
457+
362458
Datum
363459
texttoxml(PG_FUNCTION_ARGS)
364460
{

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.372 2007/01/16 21:41:13 neilc Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.373 2007/01/20 09:27:19 petere Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200701161
56+
#define CATALOG_VERSION_NO 200701201
5757

5858
#endif

src/include/catalog/pg_aggregate.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/pg_aggregate.h,v 1.59 2007/01/05 22:19:52 momjian Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/pg_aggregate.h,v 1.60 2007/01/20 09:27:19 petere Exp $
1212
*
1313
* NOTES
1414
* the genbki.sh script reads this file and generates .bki
@@ -221,6 +221,9 @@ DATA(insert ( 2241 int8or - 0 20 _null_ ));
221221
DATA(insert ( 2242 bitand - 0 1560 _null_ ));
222222
DATA(insert ( 2243 bitor - 0 1560 _null_ ));
223223

224+
/* xml */
225+
DATA(insert ( 2901 xmlconcat2 - 0 142 _null_ ));
226+
224227
/*
225228
* prototypes for functions in pg_aggregate.c
226229
*/

src/include/catalog/pg_proc.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.437 2007/01/16 21:41:13 neilc Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.438 2007/01/20 09:27:19 petere Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -4037,6 +4037,10 @@ DATA(insert OID = 2898 ( xml_recv PGNSP PGUID 12 f f t f s 1 142 "2281" _nu
40374037
DESCR("I/O");
40384038
DATA(insert OID = 2899 ( xml_send PGNSP PGUID 12 f f t f s 1 17 "142" _null_ _null_ _null_ xml_send - _null_ ));
40394039
DESCR("I/O");
4040+
DATA(insert OID = 2900 ( xmlconcat2 PGNSP PGUID 12 f f f f i 2 142 "142 142" _null_ _null_ _null_ xmlconcat2 - _null_ ));
4041+
DESCR("aggregate transition function");
4042+
DATA(insert OID = 2901 ( xmlagg PGNSP PGUID 12 t f f f i 1 142 "142" _null_ _null_ _null_ aggregate_dummy - _null_ ));
4043+
DESCR("concatenate XML values");
40404044

40414045

40424046
/*

src/include/utils/xml.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.11 2007/01/19 16:58:46 petere Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.12 2007/01/20 09:27:20 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -30,9 +30,11 @@ extern Datum xml_out(PG_FUNCTION_ARGS);
3030
extern Datum xml_recv(PG_FUNCTION_ARGS);
3131
extern Datum xml_send(PG_FUNCTION_ARGS);
3232
extern Datum xmlcomment(PG_FUNCTION_ARGS);
33+
extern Datum xmlconcat2(PG_FUNCTION_ARGS);
3334
extern Datum texttoxml(PG_FUNCTION_ARGS);
3435
extern Datum xmlvalidate(PG_FUNCTION_ARGS);
3536

37+
extern xmltype *xmlconcat(List *args);
3638
extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
3739
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
3840
extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);

src/test/regress/expected/xml.out

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ ERROR: argument of XMLCONCAT must be type xml, not type integer
5555
SELECT xmlconcat('bad', '<syntax');
5656
ERROR: invalid XML content
5757
DETAIL: Expected '>'
58+
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
59+
xmlconcat
60+
---------------------------------------------------
61+
<?xml version="1.1" standalone="no"?><foo/><bar/>
62+
(1 row)
63+
5864
SELECT xmlelement(name element,
5965
xmlattributes (1 as one, 'deuce' as two),
6066
'content');
@@ -190,7 +196,7 @@ SELECT xmlpi(name foo, ' bar');
190196
(1 row)
191197

192198
SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
193-
xmlroot
199+
xmlroot
194200
---------
195201
<foo/>
196202

@@ -268,6 +274,24 @@ SELECT xml 'abc' IS NOT DOCUMENT;
268274
SELECT '<>' IS NOT DOCUMENT;
269275
ERROR: invalid XML content
270276
DETAIL: Element name not found
277+
SELECT xmlagg(data) FROM xmltest;
278+
xmlagg
279+
--------------------------------------
280+
<value>one</value><value>two</value>
281+
(1 row)
282+
283+
SELECT xmlagg(data) FROM xmltest WHERE id > 10;
284+
xmlagg
285+
--------
286+
287+
(1 row)
288+
289+
SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
290+
xmlelement
291+
--------------------------------------------------------------------------------------------------------------------------------
292+
<employees><name>sharon</name><name>sam</name><name>bill</name><name>jeff</name><name>cim</name><name>linda</name></employees>
293+
(1 row)
294+
271295
-- Check mapping SQL identifier to XML name
272296
SELECT xmlpi(name ":::_xml_abc135.%-&_");
273297
xmlpi

src/test/regress/expected/xml_1.out

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ SELECT xmlconcat(1, 2);
3333
ERROR: argument of XMLCONCAT must be type xml, not type integer
3434
SELECT xmlconcat('bad', '<syntax');
3535
ERROR: no XML support in this installation
36+
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
37+
ERROR: no XML support in this installation
3638
SELECT xmlelement(name element,
3739
xmlattributes (1 as one, 'deuce' as two),
3840
'content');
@@ -123,6 +125,20 @@ SELECT xml 'abc' IS NOT DOCUMENT;
123125
ERROR: no XML support in this installation
124126
SELECT '<>' IS NOT DOCUMENT;
125127
ERROR: no XML support in this installation
128+
SELECT xmlagg(data) FROM xmltest;
129+
xmlagg
130+
--------
131+
132+
(1 row)
133+
134+
SELECT xmlagg(data) FROM xmltest WHERE id > 10;
135+
xmlagg
136+
--------
137+
138+
(1 row)
139+
140+
SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
141+
ERROR: no XML support in this installation
126142
-- Check mapping SQL identifier to XML name
127143
SELECT xmlpi(name ":::_xml_abc135.%-&_");
128144
ERROR: no XML support in this installation

src/test/regress/sql/xml.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ SELECT xmlconcat(xmlcomment('hello'),
2424
SELECT xmlconcat('hello', 'you');
2525
SELECT xmlconcat(1, 2);
2626
SELECT xmlconcat('bad', '<syntax');
27+
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
2728

2829

2930
SELECT xmlelement(name element,
@@ -97,6 +98,11 @@ SELECT xml 'abc' IS NOT DOCUMENT;
9798
SELECT '<>' IS NOT DOCUMENT;
9899

99100

101+
SELECT xmlagg(data) FROM xmltest;
102+
SELECT xmlagg(data) FROM xmltest WHERE id > 10;
103+
SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
104+
105+
100106
-- Check mapping SQL identifier to XML name
101107

102108
SELECT xmlpi(name ":::_xml_abc135.%-&_");

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy