From d9e1c97feb47a6f61707282133c4546fb682a5a8 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 28 Dec 2006 03:17:38 +0000 Subject: [PATCH] Handle content and document options in xmlparse() correctly. --- src/backend/utils/adt/xml.c | 93 +++++++++-------------------- src/test/regress/expected/xml.out | 25 +++++++- src/test/regress/expected/xml_1.out | 8 +++ src/test/regress/sql/xml.sql | 7 +++ 4 files changed, 65 insertions(+), 68 deletions(-) diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 7babc82551c..83704f6c794 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.5 2006/12/24 18:25:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.6 2006/12/28 03:17:38 petere Exp $ * *------------------------------------------------------------------------- */ @@ -58,7 +58,7 @@ static void xml_errorHandler(void *ctxt, const char *msg, ...); static void xml_ereport_by_code(int level, int sqlcode, const char *msg, int errcode); static xmlChar *xml_text2xmlChar(text *in); -static xmlDocPtr xml_parse(text *data, int opts, bool is_document); +static xmlDocPtr xml_parse(text *data, bool is_document, bool preserve_whitespace); #endif /* USE_LIBXML */ @@ -86,7 +86,7 @@ xml_in(PG_FUNCTION_ARGS) * that ERROR occurred if parsing failed. Do we need DTD * validation (if DTD exists)? */ - xml_parse(vardata, XML_PARSE_DTDATTR | XML_PARSE_DTDVALID, false); + xml_parse(vardata, false, true); PG_RETURN_XML_P(vardata); #else @@ -179,18 +179,7 @@ xmltype * xmlparse(text *data, bool is_document, bool preserve_whitespace) { #ifdef USE_LIBXML - if (!preserve_whitespace) - ereport(WARNING, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("XMLPARSE with STRIP WHITESPACE is not implemented"))); - - /* - * Note, that here we try to apply DTD defaults - * (XML_PARSE_DTDATTR) according to SQL/XML:10.16.7.d: 'Default - * valies defined by internal DTD are applied'. As for external - * DTDs, we try to support them too, (see SQL/XML:10.16.7.e) - */ - xml_parse(data, XML_PARSE_DTDATTR, is_document); + xml_parse(data, is_document, preserve_whitespace); return (xmltype *) data; #else @@ -421,27 +410,18 @@ xml_init(void) /* * Convert a C string to XML internal representation - * (same things as for TEXT, but with checking the data for well-formedness - * and, moreover, validation against DTD, if needed). - * NOTICE: We use TEXT type as internal storage type. In the future, - * we plan to create own storage type (maybe several types/strategies) - * TODO predefined DTDs / XSDs and validation - * TODO validation against XML Schema + * * TODO maybe, libxml2's xmlreader is better? (do not construct DOM, yet do not use SAX - see xml_reader.c) * TODO what about internal URI for docs? (see PG_XML_DEFAULT_URI below) */ static xmlDocPtr -xml_parse(text *data, int opts, bool is_document) +xml_parse(text *data, bool is_document, bool preserve_whitespace) { - bool validationFailed = false; int res_code; int32 len; xmlChar *string; xmlParserCtxtPtr ctxt = NULL; xmlDocPtr doc = NULL; -#ifdef XML_DEBUG_DTD_CONST - xmlDtdPtr dtd = NULL; -#endif len = VARSIZE(data) - VARHDRSZ; /* will be useful later */ string = xml_text2xmlChar(data); @@ -456,51 +436,40 @@ xml_parse(text *data, int opts, bool is_document) xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR, "could not allocate parser context", ctxt); - /* first, we try to parse the string as XML doc, then, as XML chunk */ - if (len >= 5 && strncmp((char *) string, "intSubset != NULL) || (doc->extSubset != NULL)) - { - /* assume inline DTD exists - validation should be performed */ - if (ctxt->valid == 0) - { - /* DTD exists, but validator reported 'validation failed' */ - validationFailed = true; - } - } -#endif - - if (validationFailed) - xml_ereport(WARNING, ERRCODE_INVALID_XML_DOCUMENT, - "validation against DTD failed", ctxt); - /* TODO encoding issues * (thoughts: * CASE: @@ -517,10 +486,6 @@ xml_parse(text *data, int opts, bool is_document) * ) */ /* ... */ -#ifdef XML_DEBUG_DTD_CONST - if (dtd) - xmlFreeDtd(dtd); -#endif if (doc) xmlFreeDoc(doc); if (ctxt) @@ -529,10 +494,6 @@ xml_parse(text *data, int opts, bool is_document) } PG_CATCH(); { -#ifdef XML_DEBUG_DTD_CONST - if (dtd) - xmlFreeDtd(dtd); -#endif if (doc) xmlFreeDoc(doc); if (ctxt) diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 20a2d4fa02e..14744656124 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -5,7 +5,7 @@ CREATE TABLE xmltest ( INSERT INTO xmltest VALUES (1, 'one'); INSERT INTO xmltest VALUES (2, 'two'); INSERT INTO xmltest VALUES (3, '' SELECT * FROM xmltest; id | data @@ -53,7 +53,7 @@ SELECT xmlconcat('hello', 'you'); SELECT xmlconcat(1, 2); ERROR: argument of XMLCONCAT must be type xml, not type integer SELECT xmlconcat('bad', '' SELECT xmlelement(name element, xmlattributes (1 as one, 'deuce' as two), @@ -85,6 +85,27 @@ SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp; SELECT xmlelement(name wrong, 37); ERROR: argument of XMLELEMENT must be type xml, not type integer +SELECT xmlparse(content 'abc'); + xmlparse +---------- + abc +(1 row) + +SELECT xmlparse(content 'x'); + xmlparse +-------------- + x +(1 row) + +SELECT xmlparse(document 'abc'); +ERROR: invalid XML document +DETAIL: Start tag expected, '<' not found. +SELECT xmlparse(document 'x'); + xmlparse +-------------- + x +(1 row) + SELECT xmlpi(name foo); xmlpi --------- diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index e756b3830e1..259bccbf4ba 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -46,6 +46,14 @@ SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp; ERROR: no XML support in this installation SELECT xmlelement(name wrong, 37); ERROR: no XML support in this installation +SELECT xmlparse(content 'abc'); +ERROR: no XML support in this installation +SELECT xmlparse(content 'x'); +ERROR: no XML support in this installation +SELECT xmlparse(document 'abc'); +ERROR: no XML support in this installation +SELECT xmlparse(document 'x'); +ERROR: no XML support in this installation SELECT xmlpi(name foo); ERROR: no XML support in this installation SELECT xmlpi(name xmlstuff); diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index 061f6329f9b..11db4905c76 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -40,6 +40,13 @@ SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp; SELECT xmlelement(name wrong, 37); +SELECT xmlparse(content 'abc'); +SELECT xmlparse(content 'x'); + +SELECT xmlparse(document 'abc'); +SELECT xmlparse(document 'x'); + + SELECT xmlpi(name foo); SELECT xmlpi(name xmlstuff); SELECT xmlpi(name foo, 'bar');