Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c0e977c

Browse files
committed
Use libxml's xmlwriter API for producing XML elements, instead of doing
our own printing dance. This does a better job of quoting and escaping the values.
1 parent f21d5b6 commit c0e977c

File tree

3 files changed

+81
-54
lines changed

3 files changed

+81
-54
lines changed

src/backend/executor/execQual.c

Lines changed: 6 additions & 51 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.204 2007/01/07 22:49:55 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.205 2007/01/10 20:33:54 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2654,7 +2654,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
26542654
char *str;
26552655
ListCell *arg;
26562656
ListCell *narg;
2657-
bool found_arg;
26582657
int i;
26592658

26602659
if (isDone)
@@ -2682,55 +2681,6 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
26822681
}
26832682
break;
26842683

2685-
case IS_XMLELEMENT:
2686-
initStringInfo(&buf);
2687-
*isNull = false;
2688-
appendStringInfo(&buf, "<%s", xexpr->name);
2689-
i = 0;
2690-
forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
2691-
{
2692-
ExprState *e = (ExprState *) lfirst(arg);
2693-
char *argname = strVal(lfirst(narg));
2694-
2695-
value = ExecEvalExpr(e, econtext, &isnull, NULL);
2696-
if (!isnull)
2697-
{
2698-
str = OutputFunctionCall(&xmlExpr->named_outfuncs[i],
2699-
value);
2700-
appendStringInfo(&buf, " %s=\"%s\"", argname, str);
2701-
pfree(str);
2702-
}
2703-
i++;
2704-
}
2705-
2706-
found_arg = false;
2707-
foreach(arg, xmlExpr->args)
2708-
{
2709-
ExprState *e = (ExprState *) lfirst(arg);
2710-
2711-
value = ExecEvalExpr(e, econtext, &isnull, NULL);
2712-
if (!isnull)
2713-
{
2714-
if (!found_arg)
2715-
{
2716-
appendStringInfoChar(&buf, '>');
2717-
found_arg = true;
2718-
}
2719-
2720-
/* we know the value is XML type */
2721-
str = DatumGetCString(DirectFunctionCall1(xml_out,
2722-
value));
2723-
appendStringInfoString(&buf, str);
2724-
pfree(str);
2725-
}
2726-
}
2727-
2728-
if (!found_arg)
2729-
appendStringInfo(&buf, "/>");
2730-
else
2731-
appendStringInfo(&buf, "</%s>", xexpr->name);
2732-
break;
2733-
27342684
case IS_XMLFOREST:
27352685
initStringInfo(&buf);
27362686
i = 0;
@@ -2754,6 +2704,11 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
27542704
break;
27552705

27562706
/* The remaining cases don't need to set up buf */
2707+
case IS_XMLELEMENT:
2708+
*isNull = false;
2709+
return PointerGetDatum(xmlelement(xmlExpr, econtext));
2710+
break;
2711+
27572712
case IS_XMLPARSE:
27582713
{
27592714
ExprState *e;

src/backend/utils/adt/xml.c

Lines changed: 72 additions & 2 deletions
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.13 2007/01/07 22:49:56 petere Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.14 2007/01/10 20:33:54 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -32,8 +32,10 @@
3232
#include <libxml/uri.h>
3333
#include <libxml/xmlerror.h>
3434
#include <libxml/xmlsave.h>
35+
#include <libxml/xmlwriter.h>
3536
#endif /* USE_LIBXML */
3637

38+
#include "executor/executor.h"
3739
#include "fmgr.h"
3840
#include "libpq/pqformat.h"
3941
#include "mb/pg_wchar.h"
@@ -239,6 +241,71 @@ texttoxml(PG_FUNCTION_ARGS)
239241
}
240242

241243

244+
xmltype *
245+
xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
246+
{
247+
#ifdef USE_LIBXML
248+
XmlExpr *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
249+
int i;
250+
ListCell *arg;
251+
ListCell *narg;
252+
bool isnull;
253+
xmltype *result;
254+
Datum value;
255+
char *str;
256+
257+
xmlBufferPtr buf;
258+
xmlTextWriterPtr writer;
259+
260+
buf = xmlBufferCreate();
261+
writer = xmlNewTextWriterMemory(buf, 0);
262+
263+
xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);
264+
265+
i = 0;
266+
forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
267+
{
268+
ExprState *e = (ExprState *) lfirst(arg);
269+
char *argname = strVal(lfirst(narg));
270+
271+
value = ExecEvalExpr(e, econtext, &isnull, NULL);
272+
if (!isnull)
273+
{
274+
str = OutputFunctionCall(&xmlExpr->named_outfuncs[i], value);
275+
xmlTextWriterWriteAttribute(writer, (xmlChar *) argname, (xmlChar *) str);
276+
pfree(str);
277+
}
278+
i++;
279+
}
280+
281+
foreach(arg, xmlExpr->args)
282+
{
283+
ExprState *e = (ExprState *) lfirst(arg);
284+
285+
value = ExecEvalExpr(e, econtext, &isnull, NULL);
286+
if (!isnull)
287+
{
288+
/* we know the value is XML type */
289+
str = DatumGetCString(DirectFunctionCall1(xml_out,
290+
value));
291+
xmlTextWriterWriteRaw(writer, (xmlChar *) str);
292+
pfree(str);
293+
}
294+
}
295+
296+
xmlTextWriterEndElement(writer);
297+
xmlFreeTextWriter(writer);
298+
299+
result = xmlBuffer_to_xmltype(buf);
300+
xmlBufferFree(buf);
301+
return result;
302+
#else
303+
NO_XML_SUPPORT();
304+
return NULL;
305+
#endif
306+
}
307+
308+
242309
xmltype *
243310
xmlparse(text *data, bool is_document, bool preserve_whitespace)
244311
{
@@ -313,6 +380,7 @@ xmltype *
313380
xmlroot(xmltype *data, text *version, int standalone)
314381
{
315382
#ifdef USE_LIBXML
383+
xmltype *result;
316384
xmlDocPtr doc;
317385
xmlBufferPtr buffer;
318386
xmlSaveCtxtPtr save;
@@ -344,7 +412,9 @@ xmlroot(xmltype *data, text *version, int standalone)
344412

345413
xmlFreeDoc(doc);
346414

347-
return xmlBuffer_to_xmltype(buffer);
415+
result = xmlBuffer_to_xmltype(buffer);
416+
xmlBufferFree(buffer);
417+
return result;
348418
#else
349419
NO_XML_SUPPORT();
350420
return NULL;

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.7 2007/01/07 22:49:56 petere Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.8 2007/01/10 20:33:54 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -16,6 +16,7 @@
1616
#define XML_H
1717

1818
#include "fmgr.h"
19+
#include "nodes/execnodes.h"
1920

2021
typedef struct varlena xmltype;
2122

@@ -32,6 +33,7 @@ extern Datum xmlcomment(PG_FUNCTION_ARGS);
3233
extern Datum texttoxml(PG_FUNCTION_ARGS);
3334
extern Datum xmlvalidate(PG_FUNCTION_ARGS);
3435

36+
extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
3537
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
3638
extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
3739
extern xmltype *xmlroot(xmltype *data, text *version, int standalone);

0 commit comments

Comments
 (0)