Various fixes in the logic of XML functions:
- Add new SQL command SET XML OPTION (also available via regular GUC) to control the DOCUMENT vs. CONTENT option in implicit parsing and serialization operations. - Subtle corrections in the handling of the standalone property in xmlroot(). - Allow xmlroot() to work on content fragments. - Subtle corrections in the handling of the version property in xmlconcat(). - Code refactoring for producing XML declarations.
This commit is contained in:
parent
9597446d11
commit
22bd156ff0
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.105 2007/01/25 04:35:10 momjian Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.106 2007/01/25 11:53:50 petere Exp $ -->
|
||||
|
||||
<chapter Id="runtime-config">
|
||||
<title>Server Configuration</title>
|
||||
@ -3558,6 +3558,38 @@ SELECT * FROM parent WHERE key = 2400;
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="guc-xmloption" xreflabel="xmloption">
|
||||
<term><varname>xmloption</varname> (<type>string</type>)</term>
|
||||
<indexterm>
|
||||
<primary><varname>xmloption</> configuration parameter</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary><varname>SET XML OPTION</></primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary><varname>XML option</></primary>
|
||||
</indexterm>
|
||||
<listitem>
|
||||
<para>
|
||||
Sets whether <literal>DOCUMENT</literal> or
|
||||
<literal>CONTENT</literal> is implicit when converting between
|
||||
XML and character string values. See <xref
|
||||
linkend="datatype-xml"> for a description of this. Valid
|
||||
values are <literal>DOCUMENT</literal> and
|
||||
<literal>CONTENT</literal>. The default is
|
||||
<literal>CONTENT</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
According to the SQL standard, the command to set this option is
|
||||
<synopsis>
|
||||
SET XML OPTION { DOCUMENT | CONTENT };
|
||||
</synopsis>
|
||||
This syntax is also available in PostgreSQL.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</sect2>
|
||||
<sect2 id="runtime-config-client-format">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.185 2007/01/18 13:59:11 petere Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.186 2007/01/25 11:53:50 petere Exp $ -->
|
||||
|
||||
<chapter id="datatype">
|
||||
<title id="datatype-title">Data Types</title>
|
||||
@ -3474,6 +3474,24 @@ XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <repla
|
||||
you to simply cast the value.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When character string values are cast to or from type
|
||||
<type>xml</type> without going through <type>XMLPARSE</type> or
|
||||
<type>XMLSERIALIZE</type>, respectively, the choice of
|
||||
<literal>DOCUMENT</literal> versus <literal>CONTENT</literal> is
|
||||
determined by the <quote>XML option</quote> session configuration
|
||||
parameter, which can be set using the standard command
|
||||
<synopsis>
|
||||
SET XML OPTION { DOCUMENT | CONTENT };
|
||||
</synopsis>
|
||||
or the more PostgreSQL-like syntax
|
||||
<synopsis>
|
||||
SET xmloption TO { DOCUMENT | CONTENT };
|
||||
</synopsis>
|
||||
The default is <literal>CONTENT</literal>, so all forms of XML
|
||||
data are allowed.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Care must be taken when dealing with multiple character encodings
|
||||
on the client, server, and in the XML data passed through them.
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.208 2007/01/20 09:27:19 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.209 2007/01/25 11:53:50 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -2797,10 +2797,7 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
|
||||
|
||||
e = (ExprState *) lthird(xmlExpr->args);
|
||||
value = ExecEvalExpr(e, econtext, &isnull, NULL);
|
||||
if (isnull)
|
||||
standalone = 0;
|
||||
else
|
||||
standalone = (DatumGetBool(value) ? 1 : -1);
|
||||
standalone = DatumGetInt32(value);
|
||||
|
||||
*isNull = false;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.576 2007/01/23 05:07:17 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.577 2007/01/25 11:53:51 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -60,6 +60,7 @@
|
||||
#include "utils/date.h"
|
||||
#include "utils/datetime.h"
|
||||
#include "utils/numeric.h"
|
||||
#include "utils/xml.h"
|
||||
|
||||
|
||||
/* Location tracking support --- simpler than bison's default */
|
||||
@ -439,7 +440,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
|
||||
|
||||
WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRITE
|
||||
|
||||
XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
|
||||
XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
|
||||
XMLPI XMLROOT XMLSERIALIZE
|
||||
|
||||
YEAR_P YES_P
|
||||
@ -1112,6 +1113,13 @@ set_rest: var_name TO var_list_or_default
|
||||
n->args = NIL;
|
||||
$$ = n;
|
||||
}
|
||||
| XML_P OPTION document_or_content
|
||||
{
|
||||
VariableSetStmt *n = makeNode(VariableSetStmt);
|
||||
n->name = "xmloption";
|
||||
n->args = list_make1(makeStringConst($3 ? "DOCUMENT" : "CONTENT", NULL));
|
||||
$$ = n;
|
||||
}
|
||||
;
|
||||
|
||||
var_name:
|
||||
@ -7938,21 +7946,13 @@ xml_root_version: VERSION_P a_expr
|
||||
;
|
||||
|
||||
opt_xml_root_standalone: ',' STANDALONE_P YES_P
|
||||
{ $$ = (Node *) makeBoolAConst(true); }
|
||||
{ $$ = (Node *) makeIntConst(XML_STANDALONE_YES); }
|
||||
| ',' STANDALONE_P NO
|
||||
{ $$ = (Node *) makeBoolAConst(false); }
|
||||
{ $$ = (Node *) makeIntConst(XML_STANDALONE_NO); }
|
||||
| ',' STANDALONE_P NO VALUE_P
|
||||
{
|
||||
A_Const *val = makeNode(A_Const);
|
||||
val->val.type = T_Null;
|
||||
$$ = (Node *) val;
|
||||
}
|
||||
{ $$ = (Node *) makeIntConst(XML_STANDALONE_NO_VALUE); }
|
||||
| /*EMPTY*/
|
||||
{
|
||||
A_Const *val = makeNode(A_Const);
|
||||
val->val.type = T_Null;
|
||||
$$ = (Node *) val;
|
||||
}
|
||||
{ $$ = (Node *) makeIntConst(XML_STANDALONE_OMITTED); }
|
||||
;
|
||||
|
||||
xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; }
|
||||
@ -8864,6 +8864,7 @@ unreserved_keyword:
|
||||
| WITHOUT
|
||||
| WORK
|
||||
| WRITE
|
||||
| XML_P
|
||||
| YEAR_P
|
||||
| YES_P
|
||||
| ZONE
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.183 2007/01/23 05:07:18 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.184 2007/01/25 11:53:51 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -380,6 +380,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"without", WITHOUT},
|
||||
{"work", WORK},
|
||||
{"write", WRITE},
|
||||
{"xml", XML_P},
|
||||
{"xmlattributes", XMLATTRIBUTES},
|
||||
{"xmlconcat", XMLCONCAT},
|
||||
{"xmlelement", XMLELEMENT},
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.208 2007/01/14 13:11:53 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.209 2007/01/25 11:53:51 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1481,7 +1481,8 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
|
||||
newe = coerce_to_specific_type(pstate, newe, TEXTOID,
|
||||
"XMLROOT");
|
||||
else
|
||||
newe = coerce_to_boolean(pstate, newe, "XMLROOT");
|
||||
newe = coerce_to_specific_type(pstate, newe, INT4OID,
|
||||
"XMLROOT");
|
||||
break;
|
||||
case IS_DOCUMENT:
|
||||
newe = coerce_to_specific_type(pstate, newe, XMLOID,
|
||||
|
@ -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.21 2007/01/23 23:39:16 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.22 2007/01/25 11:53:51 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -67,11 +67,14 @@ static void xml_ereport_by_code(int level, int sqlcode,
|
||||
const char *msg, int errcode);
|
||||
static xmlChar *xml_text2xmlChar(text *in);
|
||||
static int parse_xml_decl(const xmlChar *str, size_t *lenp, xmlChar **version, xmlChar **encoding, int *standalone);
|
||||
static bool print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int standalone);
|
||||
static xmlDocPtr xml_parse(text *data, bool is_document, bool preserve_whitespace, xmlChar *encoding);
|
||||
|
||||
#endif /* USE_LIBXML */
|
||||
|
||||
XmlBinaryType xmlbinary;
|
||||
XmlOptionType xmloption;
|
||||
|
||||
|
||||
#define NO_XML_SUPPORT() \
|
||||
ereport(ERROR, \
|
||||
@ -97,7 +100,7 @@ xml_in(PG_FUNCTION_ARGS)
|
||||
* Parse the data to check if it is well-formed XML data. Assume
|
||||
* that ERROR occurred if parsing failed.
|
||||
*/
|
||||
doc = xml_parse(vardata, false, true, NULL);
|
||||
doc = xml_parse(vardata, (xmloption == XMLOPTION_DOCUMENT), true, NULL);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
PG_RETURN_XML_P(vardata);
|
||||
@ -129,48 +132,13 @@ xml_out_internal(xmltype *x, pg_enc target_encoding)
|
||||
str[len] = '\0';
|
||||
|
||||
#ifdef USE_LIBXML
|
||||
/*
|
||||
* On output, we adjust the XML declaration as follows. (These
|
||||
* rules are the moral equivalent of the clause "Serialization of
|
||||
* an XML value" in the SQL standard.)
|
||||
*
|
||||
* We try to avoid generating an XML declaration if possible.
|
||||
* This is so that you don't get trivial things like xml '<foo/>'
|
||||
* resulting in '<?xml version="1.0"?><foo/>', which would surely
|
||||
* be annoying. We must provide a declaration if the standalone
|
||||
* property is specified or if we include an encoding
|
||||
* specification. If we have a declaration, we must specify a
|
||||
* version (XML requires this). Otherwise we only make a
|
||||
* declaration if the version is not "1.0", which is the default
|
||||
* version specified in SQL:2003.
|
||||
*/
|
||||
if ((res_code = parse_xml_decl((xmlChar *) str, &len, &version, &encoding, &standalone)) == 0)
|
||||
{
|
||||
StringInfoData buf;
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
if ((version && strcmp((char *) version, PG_XML_DEFAULT_VERSION) != 0)
|
||||
|| (target_encoding && target_encoding != PG_UTF8)
|
||||
|| standalone != -1)
|
||||
{
|
||||
appendStringInfoString(&buf, "<?xml");
|
||||
if (version)
|
||||
appendStringInfo(&buf, " version=\"%s\"", version);
|
||||
else
|
||||
appendStringInfo(&buf, " version=\"%s\"", PG_XML_DEFAULT_VERSION);
|
||||
if (target_encoding && target_encoding != PG_UTF8)
|
||||
/* XXX might be useful to convert this to IANA names
|
||||
* (ISO-8859-1 instead of LATIN1 etc.); needs field
|
||||
* experience */
|
||||
appendStringInfo(&buf, " encoding=\"%s\"", pg_encoding_to_char(target_encoding));
|
||||
if (standalone == 1)
|
||||
appendStringInfoString(&buf, " standalone=\"yes\"");
|
||||
else if (standalone == 0)
|
||||
appendStringInfoString(&buf, " standalone=\"no\"");
|
||||
appendStringInfoString(&buf, "?>");
|
||||
}
|
||||
else
|
||||
if (!print_xml_decl(&buf, version, target_encoding, standalone))
|
||||
{
|
||||
/*
|
||||
* If we are not going to produce an XML declaration, eat
|
||||
@ -231,7 +199,7 @@ xml_recv(PG_FUNCTION_ARGS)
|
||||
* Parse the data to check if it is well-formed XML data. Assume
|
||||
* that ERROR occurred if parsing failed.
|
||||
*/
|
||||
doc = xml_parse(result, false, true, encoding);
|
||||
doc = xml_parse(result, (xmloption == XMLOPTION_DOCUMENT), true, encoding);
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
newstr = (char *) pg_do_encoding_conversion((unsigned char *) str,
|
||||
@ -296,6 +264,7 @@ stringinfo_to_xmltype(StringInfo buf)
|
||||
}
|
||||
|
||||
|
||||
#ifdef NOT_USED
|
||||
static xmltype *
|
||||
cstring_to_xmltype(const char *string)
|
||||
{
|
||||
@ -309,6 +278,7 @@ cstring_to_xmltype(const char *string)
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static xmltype *
|
||||
@ -394,9 +364,11 @@ xmlconcat(List *args)
|
||||
if (standalone < 0)
|
||||
global_standalone = -1;
|
||||
|
||||
if (!global_version)
|
||||
if (!version)
|
||||
global_version_no_value = true;
|
||||
else if (!global_version)
|
||||
global_version = xmlStrdup(version);
|
||||
else if (version && xmlStrcmp(version, global_version) != 0)
|
||||
else if (xmlStrcmp(version, global_version) != 0)
|
||||
global_version_no_value = true;
|
||||
|
||||
appendStringInfoString(&buf, str + len);
|
||||
@ -409,17 +381,10 @@ xmlconcat(List *args)
|
||||
|
||||
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, "?>");
|
||||
print_xml_decl(&buf2,
|
||||
(!global_version_no_value && global_version) ? global_version : NULL,
|
||||
0,
|
||||
global_standalone);
|
||||
|
||||
appendStringInfoString(&buf2, buf.data);
|
||||
buf = buf2;
|
||||
@ -458,7 +423,7 @@ texttoxml(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *data = PG_GETARG_TEXT_P(0);
|
||||
|
||||
PG_RETURN_XML_P(xmlparse(data, false, true));
|
||||
PG_RETURN_XML_P(xmlparse(data, (xmloption == XMLOPTION_DOCUMENT), true));
|
||||
}
|
||||
|
||||
|
||||
@ -595,44 +560,45 @@ xmltype *
|
||||
xmlroot(xmltype *data, text *version, int standalone)
|
||||
{
|
||||
#ifdef USE_LIBXML
|
||||
xmltype *result;
|
||||
xmlDocPtr doc;
|
||||
xmlBufferPtr buffer;
|
||||
xmlSaveCtxtPtr save;
|
||||
char *str;
|
||||
size_t len;
|
||||
xmlChar *orig_version;
|
||||
int orig_standalone;
|
||||
StringInfoData buf;
|
||||
|
||||
doc = xml_parse((text *) data, true, true, NULL);
|
||||
len = VARSIZE(data) - VARHDRSZ;
|
||||
str = palloc(len + 1);
|
||||
memcpy(str, VARDATA(data), len);
|
||||
str[len] = '\0';
|
||||
|
||||
parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);
|
||||
|
||||
if (version)
|
||||
doc->version = xmlStrdup(xml_text2xmlChar(version));
|
||||
orig_version = xml_text2xmlChar(version);
|
||||
else
|
||||
doc->version = NULL;
|
||||
orig_version = NULL;
|
||||
|
||||
switch (standalone)
|
||||
{
|
||||
case 1:
|
||||
doc->standalone = 1;
|
||||
case XML_STANDALONE_YES:
|
||||
orig_standalone = 1;
|
||||
break;
|
||||
case -1:
|
||||
doc->standalone = 0;
|
||||
case XML_STANDALONE_NO:
|
||||
orig_standalone = 0;
|
||||
break;
|
||||
default:
|
||||
doc->standalone = -1;
|
||||
case XML_STANDALONE_NO_VALUE:
|
||||
orig_standalone = -1;
|
||||
break;
|
||||
case XML_STANDALONE_OMITTED:
|
||||
/* leave original value */
|
||||
break;
|
||||
}
|
||||
|
||||
buffer = xmlBufferCreate();
|
||||
save = xmlSaveToBuffer(buffer, "UTF-8", 0);
|
||||
xmlSaveDoc(save, doc);
|
||||
xmlSaveClose(save);
|
||||
initStringInfo(&buf);
|
||||
print_xml_decl(&buf, orig_version, 0, orig_standalone);
|
||||
appendStringInfoString(&buf, str + len);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
result = cstring_to_xmltype((char *) pg_do_encoding_conversion((unsigned char *) xmlBufferContent(buffer),
|
||||
xmlBufferLength(buffer),
|
||||
PG_UTF8,
|
||||
GetDatabaseEncoding()));
|
||||
xmlBufferFree(buffer);
|
||||
return result;
|
||||
return stringinfo_to_xmltype(&buf);
|
||||
#else
|
||||
NO_XML_SUPPORT();
|
||||
return NULL;
|
||||
@ -971,6 +937,53 @@ finished:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write an XML declaration. On output, we adjust the XML declaration
|
||||
* as follows. (These rules are the moral equivalent of the clause
|
||||
* "Serialization of an XML value" in the SQL standard.)
|
||||
*
|
||||
* We try to avoid generating an XML declaration if possible. This is
|
||||
* so that you don't get trivial things like xml '<foo/>' resulting in
|
||||
* '<?xml version="1.0"?><foo/>', which would surely be annoying. We
|
||||
* must provide a declaration if the standalone property is specified
|
||||
* or if we include an encoding declaration. If we have a
|
||||
* declaration, we must specify a version (XML requires this).
|
||||
* Otherwise we only make a declaration if the version is not "1.0",
|
||||
* which is the default version specified in SQL:2003.
|
||||
*/
|
||||
static bool
|
||||
print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int standalone)
|
||||
{
|
||||
if ((version && strcmp((char *) version, PG_XML_DEFAULT_VERSION) != 0)
|
||||
|| (encoding && encoding != PG_UTF8)
|
||||
|| standalone != -1)
|
||||
{
|
||||
appendStringInfoString(buf, "<?xml");
|
||||
|
||||
if (version)
|
||||
appendStringInfo(buf, " version=\"%s\"", version);
|
||||
else
|
||||
appendStringInfo(buf, " version=\"%s\"", PG_XML_DEFAULT_VERSION);
|
||||
|
||||
if (encoding && encoding != PG_UTF8)
|
||||
/* XXX might be useful to convert this to IANA names
|
||||
* (ISO-8859-1 instead of LATIN1 etc.); needs field
|
||||
* experience */
|
||||
appendStringInfo(buf, " encoding=\"%s\"", pg_encoding_to_char(encoding));
|
||||
|
||||
if (standalone == 1)
|
||||
appendStringInfoString(buf, " standalone=\"yes\"");
|
||||
else if (standalone == 0)
|
||||
appendStringInfoString(buf, " standalone=\"no\"");
|
||||
appendStringInfoString(buf, "?>");
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Convert a C string to XML internal representation
|
||||
*
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.370 2007/01/25 04:35:11 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.371 2007/01/25 11:53:51 petere Exp $
|
||||
*
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
@ -145,6 +145,7 @@ static const char *assign_canonical_path(const char *newval, bool doit, GucSourc
|
||||
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 const char *assign_xmloption(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);
|
||||
@ -233,6 +234,7 @@ static char *XactIsoLevel_string;
|
||||
static char *data_directory;
|
||||
static char *custom_variable_classes;
|
||||
static char *xmlbinary_string;
|
||||
static char *xmloption_string;
|
||||
static int max_function_args;
|
||||
static int max_index_keys;
|
||||
static int max_identifier_length;
|
||||
@ -2292,6 +2294,16 @@ static struct config_string ConfigureNamesString[] =
|
||||
"base64", assign_xmlbinary, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
|
||||
gettext_noop("Sets whether XML data in implicit parsing and serialization "
|
||||
"operations is to be considered as documents or content fragments."),
|
||||
gettext_noop("Valid values are DOCUMENT and CONTENT.")
|
||||
},
|
||||
&xmloption_string,
|
||||
"content", assign_xmloption, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"temp_tablespaces", PGC_USERSET, PGC_S_FILE,
|
||||
gettext_noop("Sets the tablespaces suitable for creating new objects and sort files."),
|
||||
@ -6516,6 +6528,24 @@ assign_xmlbinary(const char *newval, bool doit, GucSource source)
|
||||
return newval;
|
||||
}
|
||||
|
||||
static const char *
|
||||
assign_xmloption(const char *newval, bool doit, GucSource source)
|
||||
{
|
||||
XmlOptionType xo;
|
||||
|
||||
if (pg_strcasecmp(newval, "document") == 0)
|
||||
xo = XMLOPTION_DOCUMENT;
|
||||
else if (pg_strcasecmp(newval, "content") == 0)
|
||||
xo = XMLOPTION_CONTENT;
|
||||
else
|
||||
return NULL; /* reject */
|
||||
|
||||
if (doit)
|
||||
xmloption = xo;
|
||||
|
||||
return newval;
|
||||
}
|
||||
|
||||
static bool
|
||||
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
|
||||
{
|
||||
|
@ -406,6 +406,8 @@
|
||||
#default_transaction_read_only = off
|
||||
#statement_timeout = 0 # 0 is disabled
|
||||
#vacuum_freeze_min_age = 100000000
|
||||
#xmlbinary = 'base64'
|
||||
#xmloption = 'content'
|
||||
|
||||
# - Locale and Formatting -
|
||||
|
||||
|
@ -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.12 2007/01/20 09:27:20 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.13 2007/01/25 11:53:51 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -34,6 +34,14 @@ extern Datum xmlconcat2(PG_FUNCTION_ARGS);
|
||||
extern Datum texttoxml(PG_FUNCTION_ARGS);
|
||||
extern Datum xmlvalidate(PG_FUNCTION_ARGS);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XML_STANDALONE_YES,
|
||||
XML_STANDALONE_NO,
|
||||
XML_STANDALONE_NO_VALUE,
|
||||
XML_STANDALONE_OMITTED
|
||||
} XmlStandaloneType;
|
||||
|
||||
extern xmltype *xmlconcat(List *args);
|
||||
extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
|
||||
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
|
||||
@ -53,4 +61,12 @@ typedef enum
|
||||
|
||||
extern XmlBinaryType xmlbinary;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
XMLOPTION_DOCUMENT,
|
||||
XMLOPTION_CONTENT
|
||||
} XmlOptionType;
|
||||
|
||||
extern XmlOptionType xmloption;
|
||||
|
||||
#endif /* XML_H */
|
||||
|
@ -53,13 +53,19 @@ SELECT xmlconcat('hello', 'you');
|
||||
(1 row)
|
||||
|
||||
SELECT xmlconcat(1, 2);
|
||||
ERROR: argument of XMLCONCAT must be type xml, not type integer
|
||||
ERROR: argument of XMLCONCAT must be type "xml", not type integer
|
||||
SELECT xmlconcat('bad', '<syntax');
|
||||
ERROR: invalid XML content
|
||||
DETAIL: Entity: line 1: parser error : Couldn't find end of Start Tag syntax line 1
|
||||
<syntax
|
||||
^
|
||||
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
|
||||
xmlconcat
|
||||
--------------
|
||||
<foo/><bar/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
|
||||
xmlconcat
|
||||
-----------------------------------
|
||||
<?xml version="1.1"?><foo/><bar/>
|
||||
@ -205,23 +211,48 @@ SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
|
||||
xmlroot
|
||||
---------
|
||||
<foo/>
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot(xml '<foo/>', version '2.0');
|
||||
xmlroot
|
||||
-----------------------
|
||||
<?xml version="2.0"?>
|
||||
<foo/>
|
||||
|
||||
xmlroot
|
||||
-----------------------------
|
||||
<?xml version="2.0"?><foo/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot(xml '<foo/>', version no value, standalone yes);
|
||||
xmlroot
|
||||
----------------------------------------------
|
||||
<?xml version="1.0" standalone="yes"?><foo/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot(xml '<?xml version="1.1"?><foo/>', version no value, standalone yes);
|
||||
xmlroot
|
||||
----------------------------------------------
|
||||
<?xml version="1.0" standalone="yes"?><foo/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot(xmlroot(xml '<foo/>', version '1.0'), version '1.1', standalone no);
|
||||
xmlroot
|
||||
---------------------------------------
|
||||
<?xml version="1.1" standalone="no"?>
|
||||
xmlroot
|
||||
---------------------------------------------
|
||||
<?xml version="1.1" standalone="no"?><foo/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no);
|
||||
xmlroot
|
||||
---------------------------------------------
|
||||
<?xml version="1.0" standalone="no"?><foo/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no value);
|
||||
xmlroot
|
||||
---------
|
||||
<foo/>
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value);
|
||||
xmlroot
|
||||
----------------------------------------------
|
||||
<?xml version="1.0" standalone="yes"?><foo/>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlroot (
|
||||
@ -239,11 +270,9 @@ SELECT xmlroot (
|
||||
version '1.0',
|
||||
standalone yes
|
||||
);
|
||||
xmlroot
|
||||
----------------------------------------------------
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<gazonk name="val" num="2"><qux>foo</qux></gazonk>
|
||||
|
||||
xmlroot
|
||||
------------------------------------------------------------------------------------------
|
||||
<?xml version="1.0" standalone="yes"?><gazonk name="val" num="2"><qux>foo</qux></gazonk>
|
||||
(1 row)
|
||||
|
||||
SELECT xmlserialize(content data as character varying) FROM xmltest;
|
||||
@ -313,3 +342,29 @@ SELECT xmlpi(name "123");
|
||||
<?_x0031_23?>
|
||||
(1 row)
|
||||
|
||||
PREPARE foo (xml) AS SELECT xmlconcat('<foo/>', $1);
|
||||
SET XML OPTION DOCUMENT;
|
||||
EXECUTE foo ('<bar/>');
|
||||
xmlconcat
|
||||
--------------
|
||||
<foo/><bar/>
|
||||
(1 row)
|
||||
|
||||
EXECUTE foo ('bad');
|
||||
ERROR: invalid XML document
|
||||
DETAIL: Entity: line 1: parser error : Start tag expected, '<' not found
|
||||
bad
|
||||
^
|
||||
SET XML OPTION CONTENT;
|
||||
EXECUTE foo ('<bar/>');
|
||||
xmlconcat
|
||||
--------------
|
||||
<foo/><bar/>
|
||||
(1 row)
|
||||
|
||||
EXECUTE foo ('good');
|
||||
xmlconcat
|
||||
------------
|
||||
<foo/>good
|
||||
(1 row)
|
||||
|
||||
|
@ -30,11 +30,13 @@ ERROR: no XML support in this installation
|
||||
SELECT xmlconcat('hello', 'you');
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlconcat(1, 2);
|
||||
ERROR: argument of XMLCONCAT must be type xml, not type integer
|
||||
ERROR: argument of XMLCONCAT must be type "xml", not type integer
|
||||
SELECT xmlconcat('bad', '<syntax');
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlelement(name element,
|
||||
xmlattributes (1 as one, 'deuce' as two),
|
||||
'content');
|
||||
@ -92,8 +94,18 @@ SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot(xml '<foo/>', version '2.0');
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot(xml '<foo/>', version no value, standalone yes);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot(xml '<?xml version="1.1"?><foo/>', version no value, standalone yes);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot(xmlroot(xml '<foo/>', version '1.0'), version '1.1', standalone no);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no value);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value);
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlroot (
|
||||
xmlelement (
|
||||
name gazonk,
|
||||
@ -144,3 +156,15 @@ SELECT xmlpi(name ":::_xml_abc135.%-&_");
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xmlpi(name "123");
|
||||
ERROR: no XML support in this installation
|
||||
PREPARE foo (xml) AS SELECT xmlconcat('<foo/>', $1);
|
||||
ERROR: no XML support in this installation
|
||||
SET XML OPTION DOCUMENT;
|
||||
EXECUTE foo ('<bar/>');
|
||||
ERROR: prepared statement "foo" does not exist
|
||||
EXECUTE foo ('bad');
|
||||
ERROR: prepared statement "foo" does not exist
|
||||
SET XML OPTION CONTENT;
|
||||
EXECUTE foo ('<bar/>');
|
||||
ERROR: prepared statement "foo" does not exist
|
||||
EXECUTE foo ('good');
|
||||
ERROR: prepared statement "foo" does not exist
|
||||
|
@ -25,6 +25,7 @@ SELECT xmlconcat('hello', 'you');
|
||||
SELECT xmlconcat(1, 2);
|
||||
SELECT xmlconcat('bad', '<syntax');
|
||||
SELECT xmlconcat('<foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
|
||||
SELECT xmlconcat('<?xml version="1.1"?><foo/>', NULL, '<?xml version="1.1" standalone="no"?><bar/>');
|
||||
|
||||
|
||||
SELECT xmlelement(name element,
|
||||
@ -69,7 +70,13 @@ SELECT xmlpi(name foo, ' bar');
|
||||
|
||||
SELECT xmlroot(xml '<foo/>', version no value, standalone no value);
|
||||
SELECT xmlroot(xml '<foo/>', version '2.0');
|
||||
SELECT xmlroot(xml '<foo/>', version no value, standalone yes);
|
||||
SELECT xmlroot(xml '<?xml version="1.1"?><foo/>', version no value, standalone yes);
|
||||
SELECT xmlroot(xmlroot(xml '<foo/>', version '1.0'), version '1.1', standalone no);
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no);
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value, standalone no value);
|
||||
SELECT xmlroot('<?xml version="1.1" standalone="yes"?><foo/>', version no value);
|
||||
|
||||
|
||||
SELECT xmlroot (
|
||||
xmlelement (
|
||||
@ -107,3 +114,14 @@ SELECT xmlelement(name employees, xmlagg(xmlelement(name name, name))) FROM emp;
|
||||
|
||||
SELECT xmlpi(name ":::_xml_abc135.%-&_");
|
||||
SELECT xmlpi(name "123");
|
||||
|
||||
|
||||
PREPARE foo (xml) AS SELECT xmlconcat('<foo/>', $1);
|
||||
|
||||
SET XML OPTION DOCUMENT;
|
||||
EXECUTE foo ('<bar/>');
|
||||
EXECUTE foo ('bad');
|
||||
|
||||
SET XML OPTION CONTENT;
|
||||
EXECUTE foo ('<bar/>');
|
||||
EXECUTE foo ('good');
|
||||
|
Loading…
x
Reference in New Issue
Block a user