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

Commit 4b48ad4

Browse files
committed
Add support for converting binary values (i.e. bytea) into xml values,
with new GUC parameter "xmlbinary" that controls the output encoding, as per SQL/XML standard.
1 parent 5b4a088 commit 4b48ad4

File tree

7 files changed

+117
-4
lines changed

7 files changed

+117
-4
lines changed

doc/src/sgml/config.sgml

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.102 2007/01/16 18:26:02 alvherre Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.103 2007/01/19 16:58:45 petere Exp $ -->
22

33
<chapter Id="runtime-config">
44
<title>Server Configuration</title>
@@ -3502,6 +3502,33 @@ SELECT * FROM parent WHERE key = 2400;
35023502
</listitem>
35033503
</varlistentry>
35043504

3505+
<varlistentry id="guc-xmlbinary" xreflabel="xmlbinary">
3506+
<term><varname>xmlbinary</varname> (<type>string</type>)</term>
3507+
<indexterm>
3508+
<primary><varname>xmlbinary</> configuration parameter</primary>
3509+
</indexterm>
3510+
<listitem>
3511+
<para>
3512+
Sets how binary values are to be encoded in XML. This applies
3513+
for example when <type>bytea</type> values are converted to
3514+
XML by the functions <function>xmlelement</function> or
3515+
<function>xmlforest</function>. Possible values are
3516+
<literal>base64</literal> and <literal>hex</literal>, which
3517+
are both defined in the XML Schema standard. The default is
3518+
<literal>base64</literal>. For further information about
3519+
XML-related functions, see <xref linkend="functions-xml">.
3520+
</para>
3521+
3522+
<para>
3523+
The actual choice here is mostly a matter of taste,
3524+
constrained only by possible restrictions in client
3525+
applications. Both methods support all possible values,
3526+
although the hex encoding will be somewhat larger than the
3527+
base64 encoding.
3528+
</para>
3529+
</listitem>
3530+
</varlistentry>
3531+
35053532
</variablelist>
35063533
</sect2>
35073534
<sect2 id="runtime-config-client-format">

src/backend/utils/adt/xml.c

Lines changed: 25 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.18 2007/01/18 13:59:11 petere Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.19 2007/01/19 16:58:46 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -73,6 +73,8 @@ static xmlDocPtr xml_parse(text *data, bool is_document, bool preserve_whitespac
7373

7474
#endif /* USE_LIBXML */
7575

76+
XmlBinaryType xmlbinary;
77+
7678
#define NO_XML_SUPPORT() \
7779
ereport(ERROR, \
7880
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
@@ -1500,6 +1502,28 @@ map_sql_value_to_xml_value(Datum value, Oid type)
15001502
if (type == XMLOID)
15011503
return str;
15021504

1505+
#ifdef USE_LIBXML
1506+
if (type == BYTEAOID)
1507+
{
1508+
xmlBufferPtr buf;
1509+
xmlTextWriterPtr writer;
1510+
char *result;
1511+
1512+
buf = xmlBufferCreate();
1513+
writer = xmlNewTextWriterMemory(buf, 0);
1514+
1515+
if (xmlbinary == XMLBINARY_BASE64)
1516+
xmlTextWriterWriteBase64(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);
1517+
else
1518+
xmlTextWriterWriteBinHex(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);
1519+
1520+
xmlFreeTextWriter(writer);
1521+
result = pstrdup((const char *) xmlBufferContent(buf));
1522+
xmlBufferFree(buf);
1523+
return result;
1524+
}
1525+
#endif /* USE_LIBXML */
1526+
15031527
for (p = str; *p; p += pg_mblen(p))
15041528
{
15051529
switch (*p)

src/backend/utils/misc/guc.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Written by Peter Eisentraut <peter_e@gmx.net>.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.368 2007/01/16 18:26:02 alvherre Exp $
13+
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.369 2007/01/19 16:58:46 petere Exp $
1414
*
1515
*--------------------------------------------------------------------
1616
*/
@@ -61,6 +61,7 @@
6161
#include "utils/pg_locale.h"
6262
#include "utils/ps_status.h"
6363
#include "utils/tzparser.h"
64+
#include "utils/xml.h"
6465

6566
#ifndef PG_KRB_SRVTAB
6667
#define PG_KRB_SRVTAB ""
@@ -142,6 +143,7 @@ static bool assign_transaction_read_only(bool newval, bool doit, GucSource sourc
142143
static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
143144
static const char *assign_backslash_quote(const char *newval, bool doit, GucSource source);
144145
static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
146+
static const char *assign_xmlbinary(const char *newval, bool doit, GucSource source);
145147

146148
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
147149
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
@@ -229,6 +231,7 @@ static char *timezone_abbreviations_string;
229231
static char *XactIsoLevel_string;
230232
static char *data_directory;
231233
static char *custom_variable_classes;
234+
static char *xmlbinary_string;
232235
static int max_function_args;
233236
static int max_index_keys;
234237
static int max_identifier_length;
@@ -2279,6 +2282,15 @@ static struct config_string ConfigureNamesString[] =
22792282
NULL, assign_canonical_path, NULL
22802283
},
22812284

2285+
{
2286+
{"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
2287+
gettext_noop("Sets how binary values are to be encoded in XML."),
2288+
gettext_noop("Valid values are BASE64 and HEX.")
2289+
},
2290+
&xmlbinary_string,
2291+
"base64", assign_xmlbinary, NULL
2292+
},
2293+
22822294
/* End-of-list marker */
22832295
{
22842296
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
@@ -6475,6 +6487,24 @@ pg_timezone_abbrev_initialize(void)
64756487
}
64766488
}
64776489

6490+
static const char *
6491+
assign_xmlbinary(const char *newval, bool doit, GucSource source)
6492+
{
6493+
XmlBinaryType xb;
6494+
6495+
if (pg_strcasecmp(newval, "base64") == 0)
6496+
xb = XMLBINARY_BASE64;
6497+
else if (pg_strcasecmp(newval, "hex") == 0)
6498+
xb = XMLBINARY_HEX;
6499+
else
6500+
return NULL; /* reject */
6501+
6502+
if (doit)
6503+
xmlbinary = xb;
6504+
6505+
return newval;
6506+
}
6507+
64786508
static bool
64796509
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
64806510
{

src/include/utils/xml.h

Lines changed: 9 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.10 2007/01/14 13:11:54 petere Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.11 2007/01/19 16:58:46 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -43,4 +43,12 @@ extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
4343
extern char *map_xml_name_to_sql_identifier(char *name);
4444
extern char *map_sql_value_to_xml_value(Datum value, Oid type);
4545

46+
typedef enum
47+
{
48+
XMLBINARY_BASE64,
49+
XMLBINARY_HEX
50+
} XmlBinaryType;
51+
52+
extern XmlBinaryType xmlbinary;
53+
4654
#endif /* XML_H */

src/test/regress/expected/xml.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ SELECT xmlelement(name foo, array[1, 2, 3]);
121121
<foo><element>1</element><element>2</element><element>3</element></foo>
122122
(1 row)
123123

124+
SET xmlbinary TO base64;
125+
SELECT xmlelement(name foo, bytea 'bar');
126+
xmlelement
127+
-----------------
128+
<foo>YmFy</foo>
129+
(1 row)
130+
131+
SET xmlbinary TO hex;
132+
SELECT xmlelement(name foo, bytea 'bar');
133+
xmlelement
134+
-------------------
135+
<foo>626172</foo>
136+
(1 row)
137+
124138
SELECT xmlparse(content 'abc');
125139
xmlparse
126140
----------

src/test/regress/expected/xml_1.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ SELECT xmlelement(name foo, xml 'b<a/>r');
5858
ERROR: no XML support in this installation
5959
SELECT xmlelement(name foo, array[1, 2, 3]);
6060
ERROR: no XML support in this installation
61+
SET xmlbinary TO base64;
62+
SELECT xmlelement(name foo, bytea 'bar');
63+
ERROR: no XML support in this installation
64+
SET xmlbinary TO hex;
65+
SELECT xmlelement(name foo, bytea 'bar');
66+
ERROR: no XML support in this installation
6167
SELECT xmlparse(content 'abc');
6268
ERROR: no XML support in this installation
6369
SELECT xmlparse(content '<abc>x</abc>');

src/test/regress/sql/xml.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ SELECT xmlelement(name foo, xml 'bar');
4545
SELECT xmlelement(name foo, text 'b<a/>r');
4646
SELECT xmlelement(name foo, xml 'b<a/>r');
4747
SELECT xmlelement(name foo, array[1, 2, 3]);
48+
SET xmlbinary TO base64;
49+
SELECT xmlelement(name foo, bytea 'bar');
50+
SET xmlbinary TO hex;
51+
SELECT xmlelement(name foo, bytea 'bar');
4852

4953

5054
SELECT xmlparse(content 'abc');

0 commit comments

Comments
 (0)