diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 94fc8fd79a..2a95d8fae7 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ - + Server Configuration @@ -3558,6 +3558,38 @@ SELECT * FROM parent WHERE key = 2400; + + xmloption (string) + + xmloption configuration parameter + + + SET XML OPTION + + + XML option + + + + Sets whether DOCUMENT or + CONTENT is implicit when converting between + XML and character string values. See for a description of this. Valid + values are DOCUMENT and + CONTENT. The default is + CONTENT. + + + + According to the SQL standard, the command to set this option is + +SET XML OPTION { DOCUMENT | CONTENT }; + + This syntax is also available in PostgreSQL. + + + + diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 47c2e5c74a..f0ba6c32c7 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,4 +1,4 @@ - + Data Types @@ -3474,6 +3474,24 @@ XMLSERIALIZE ( { DOCUMENT | CONTENT } value AS + + When character string values are cast to or from type + xml without going through XMLPARSE or + XMLSERIALIZE, respectively, the choice of + DOCUMENT versus CONTENT is + determined by the XML option session configuration + parameter, which can be set using the standard command + +SET XML OPTION { DOCUMENT | CONTENT }; + + or the more PostgreSQL-like syntax + +SET xmloption TO { DOCUMENT | CONTENT }; + + The default is CONTENT, so all forms of XML + data are allowed. + + Care must be taken when dealing with multiple character encodings on the client, server, and in the XML data passed through them. diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 60f9d35f1f..75a9e42a24 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -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; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 217b1a0465..c256d73ead 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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 diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index b8607c7c00..368f3e0694 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -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}, diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 394a507f2e..a807ef12de 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -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, diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 3b283d247f..d9a9ce5bc3 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -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 '' - * resulting in '', 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, ""); - } - 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, ""); + 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 '' resulting in + * '', 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, ""); + + return true; + } + else + return false; +} + + /* * Convert a C string to XML internal representation * diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 9f2cdc43f7..dad2898333 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * 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) { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 3b9730c75b..b3c24fb2c5 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -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 - diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h index b580fffd82..f5b33512cf 100644 --- a/src/include/utils/xml.h +++ b/src/include/utils/xml.h @@ -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 */ diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index d91d765303..0c08667706 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -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', '', NULL, ''); + xmlconcat +-------------- + +(1 row) + +SELECT xmlconcat('', NULL, ''); xmlconcat ----------------------------------- @@ -205,23 +211,48 @@ SELECT xmlroot(xml '', version no value, standalone no value); xmlroot --------- - (1 row) SELECT xmlroot(xml '', version '2.0'); - xmlroot ------------------------ - - - + xmlroot +----------------------------- + +(1 row) + +SELECT xmlroot(xml '', version no value, standalone yes); + xmlroot +---------------------------------------------- + +(1 row) + +SELECT xmlroot(xml '', version no value, standalone yes); + xmlroot +---------------------------------------------- + (1 row) SELECT xmlroot(xmlroot(xml '', version '1.0'), version '1.1', standalone no); - xmlroot ---------------------------------------- - + xmlroot +--------------------------------------------- + +(1 row) + +SELECT xmlroot('', version no value, standalone no); + xmlroot +--------------------------------------------- + +(1 row) + +SELECT xmlroot('', version no value, standalone no value); + xmlroot +--------- - +(1 row) + +SELECT xmlroot('', version no value); + xmlroot +---------------------------------------------- + (1 row) SELECT xmlroot ( @@ -239,11 +270,9 @@ SELECT xmlroot ( version '1.0', standalone yes ); - xmlroot ----------------------------------------------------- - - foo - + xmlroot +------------------------------------------------------------------------------------------ + foo (1 row) SELECT xmlserialize(content data as character varying) FROM xmltest; @@ -313,3 +342,29 @@ SELECT xmlpi(name "123"); (1 row) +PREPARE foo (xml) AS SELECT xmlconcat('', $1); +SET XML OPTION DOCUMENT; +EXECUTE foo (''); + xmlconcat +-------------- + +(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 (''); + xmlconcat +-------------- + +(1 row) + +EXECUTE foo ('good'); + xmlconcat +------------ + good +(1 row) + diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index dd35f1bf4e..89124ebb98 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -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', '', NULL, ''); ERROR: no XML support in this installation +SELECT xmlconcat('', NULL, ''); +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 '', version no value, standalone no value); ERROR: no XML support in this installation SELECT xmlroot(xml '', version '2.0'); ERROR: no XML support in this installation +SELECT xmlroot(xml '', version no value, standalone yes); +ERROR: no XML support in this installation +SELECT xmlroot(xml '', version no value, standalone yes); +ERROR: no XML support in this installation SELECT xmlroot(xmlroot(xml '', version '1.0'), version '1.1', standalone no); ERROR: no XML support in this installation +SELECT xmlroot('', version no value, standalone no); +ERROR: no XML support in this installation +SELECT xmlroot('', version no value, standalone no value); +ERROR: no XML support in this installation +SELECT xmlroot('', 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('', $1); +ERROR: no XML support in this installation +SET XML OPTION DOCUMENT; +EXECUTE foo (''); +ERROR: prepared statement "foo" does not exist +EXECUTE foo ('bad'); +ERROR: prepared statement "foo" does not exist +SET XML OPTION CONTENT; +EXECUTE foo (''); +ERROR: prepared statement "foo" does not exist +EXECUTE foo ('good'); +ERROR: prepared statement "foo" does not exist diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index 8e32183159..b3117c2424 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -25,6 +25,7 @@ SELECT xmlconcat('hello', 'you'); SELECT xmlconcat(1, 2); SELECT xmlconcat('bad', '', NULL, ''); +SELECT xmlconcat('', NULL, ''); SELECT xmlelement(name element, @@ -69,7 +70,13 @@ SELECT xmlpi(name foo, ' bar'); SELECT xmlroot(xml '', version no value, standalone no value); SELECT xmlroot(xml '', version '2.0'); +SELECT xmlroot(xml '', version no value, standalone yes); +SELECT xmlroot(xml '', version no value, standalone yes); SELECT xmlroot(xmlroot(xml '', version '1.0'), version '1.1', standalone no); +SELECT xmlroot('', version no value, standalone no); +SELECT xmlroot('', version no value, standalone no value); +SELECT xmlroot('', 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('', $1); + +SET XML OPTION DOCUMENT; +EXECUTE foo (''); +EXECUTE foo ('bad'); + +SET XML OPTION CONTENT; +EXECUTE foo (''); +EXECUTE foo ('good');