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.
This commit is contained in:
Peter Eisentraut 2007-01-19 16:58:46 +00:00
parent 5b4a08896b
commit 4b48ad4fb2
7 changed files with 117 additions and 4 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.102 2007/01/16 18:26:02 alvherre Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.103 2007/01/19 16:58:45 petere Exp $ -->
<chapter Id="runtime-config">
<title>Server Configuration</title>
@ -3502,6 +3502,33 @@ SELECT * FROM parent WHERE key = 2400;
</listitem>
</varlistentry>
<varlistentry id="guc-xmlbinary" xreflabel="xmlbinary">
<term><varname>xmlbinary</varname> (<type>string</type>)</term>
<indexterm>
<primary><varname>xmlbinary</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Sets how binary values are to be encoded in XML. This applies
for example when <type>bytea</type> values are converted to
XML by the functions <function>xmlelement</function> or
<function>xmlforest</function>. Possible values are
<literal>base64</literal> and <literal>hex</literal>, which
are both defined in the XML Schema standard. The default is
<literal>base64</literal>. For further information about
XML-related functions, see <xref linkend="functions-xml">.
</para>
<para>
The actual choice here is mostly a matter of taste,
constrained only by possible restrictions in client
applications. Both methods support all possible values,
although the hex encoding will be somewhat larger than the
base64 encoding.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="runtime-config-client-format">

View File

@ -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.18 2007/01/18 13:59:11 petere Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.19 2007/01/19 16:58:46 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -73,6 +73,8 @@ static xmlDocPtr xml_parse(text *data, bool is_document, bool preserve_whitespac
#endif /* USE_LIBXML */
XmlBinaryType xmlbinary;
#define NO_XML_SUPPORT() \
ereport(ERROR, \
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
@ -1500,6 +1502,28 @@ map_sql_value_to_xml_value(Datum value, Oid type)
if (type == XMLOID)
return str;
#ifdef USE_LIBXML
if (type == BYTEAOID)
{
xmlBufferPtr buf;
xmlTextWriterPtr writer;
char *result;
buf = xmlBufferCreate();
writer = xmlNewTextWriterMemory(buf, 0);
if (xmlbinary == XMLBINARY_BASE64)
xmlTextWriterWriteBase64(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);
else
xmlTextWriterWriteBinHex(writer, VARDATA(value), 0, VARSIZE(value) - VARHDRSZ);
xmlFreeTextWriter(writer);
result = pstrdup((const char *) xmlBufferContent(buf));
xmlBufferFree(buf);
return result;
}
#endif /* USE_LIBXML */
for (p = str; *p; p += pg_mblen(p))
{
switch (*p)

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.368 2007/01/16 18:26:02 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.369 2007/01/19 16:58:46 petere Exp $
*
*--------------------------------------------------------------------
*/
@ -61,6 +61,7 @@
#include "utils/pg_locale.h"
#include "utils/ps_status.h"
#include "utils/tzparser.h"
#include "utils/xml.h"
#ifndef PG_KRB_SRVTAB
#define PG_KRB_SRVTAB ""
@ -142,6 +143,7 @@ static bool assign_transaction_read_only(bool newval, bool doit, GucSource sourc
static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
static const char *assign_backslash_quote(const char *newval, bool doit, GucSource source);
static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
static const char *assign_xmlbinary(const char *newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
@ -229,6 +231,7 @@ static char *timezone_abbreviations_string;
static char *XactIsoLevel_string;
static char *data_directory;
static char *custom_variable_classes;
static char *xmlbinary_string;
static int max_function_args;
static int max_index_keys;
static int max_identifier_length;
@ -2279,6 +2282,15 @@ static struct config_string ConfigureNamesString[] =
NULL, assign_canonical_path, NULL
},
{
{"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
gettext_noop("Sets how binary values are to be encoded in XML."),
gettext_noop("Valid values are BASE64 and HEX.")
},
&xmlbinary_string,
"base64", assign_xmlbinary, NULL
},
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
@ -6475,6 +6487,24 @@ pg_timezone_abbrev_initialize(void)
}
}
static const char *
assign_xmlbinary(const char *newval, bool doit, GucSource source)
{
XmlBinaryType xb;
if (pg_strcasecmp(newval, "base64") == 0)
xb = XMLBINARY_BASE64;
else if (pg_strcasecmp(newval, "hex") == 0)
xb = XMLBINARY_HEX;
else
return NULL; /* reject */
if (doit)
xmlbinary = xb;
return newval;
}
static bool
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
{

View File

@ -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/include/utils/xml.h,v 1.10 2007/01/14 13:11:54 petere Exp $
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.11 2007/01/19 16:58:46 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -43,4 +43,12 @@ extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
extern char *map_xml_name_to_sql_identifier(char *name);
extern char *map_sql_value_to_xml_value(Datum value, Oid type);
typedef enum
{
XMLBINARY_BASE64,
XMLBINARY_HEX
} XmlBinaryType;
extern XmlBinaryType xmlbinary;
#endif /* XML_H */

View File

@ -121,6 +121,20 @@ SELECT xmlelement(name foo, array[1, 2, 3]);
<foo><element>1</element><element>2</element><element>3</element></foo>
(1 row)
SET xmlbinary TO base64;
SELECT xmlelement(name foo, bytea 'bar');
xmlelement
-----------------
<foo>YmFy</foo>
(1 row)
SET xmlbinary TO hex;
SELECT xmlelement(name foo, bytea 'bar');
xmlelement
-------------------
<foo>626172</foo>
(1 row)
SELECT xmlparse(content 'abc');
xmlparse
----------

View File

@ -58,6 +58,12 @@ SELECT xmlelement(name foo, xml 'b<a/>r');
ERROR: no XML support in this installation
SELECT xmlelement(name foo, array[1, 2, 3]);
ERROR: no XML support in this installation
SET xmlbinary TO base64;
SELECT xmlelement(name foo, bytea 'bar');
ERROR: no XML support in this installation
SET xmlbinary TO hex;
SELECT xmlelement(name foo, bytea 'bar');
ERROR: no XML support in this installation
SELECT xmlparse(content 'abc');
ERROR: no XML support in this installation
SELECT xmlparse(content '<abc>x</abc>');

View File

@ -45,6 +45,10 @@ SELECT xmlelement(name foo, xml 'bar');
SELECT xmlelement(name foo, text 'b<a/>r');
SELECT xmlelement(name foo, xml 'b<a/>r');
SELECT xmlelement(name foo, array[1, 2, 3]);
SET xmlbinary TO base64;
SELECT xmlelement(name foo, bytea 'bar');
SET xmlbinary TO hex;
SELECT xmlelement(name foo, bytea 'bar');
SELECT xmlparse(content 'abc');