1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Implement XMLSERIALIZE for real. Analogously, make the xml to text cast

observe the xmloption.

Reorganize the representation of the XML option in the parse tree and the
API to make it easier to manage and understand.

Add regression tests for parsing back XML expressions.
This commit is contained in:
Peter Eisentraut
2007-02-03 14:06:56 +00:00
parent 25dc46334b
commit ec020e1ceb
23 changed files with 344 additions and 99 deletions

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.247 2007/01/30 02:39:27 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.248 2007/02/03 14:06:54 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3856,9 +3856,19 @@ get_rule_expr(Node *node, deparse_context *context,
case IS_XMLROOT:
appendStringInfoString(buf, "XMLROOT(");
break;
case IS_XMLSERIALIZE:
appendStringInfoString(buf, "XMLSERIALIZE(");
break;
case IS_DOCUMENT:
break;
}
if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE)
{
if (xexpr->xmloption == XMLOPTION_DOCUMENT)
appendStringInfoString(buf, "DOCUMENT ");
else
appendStringInfoString(buf, "CONTENT ");
}
if (xexpr->name)
{
appendStringInfo(buf, "NAME %s",
@@ -3899,24 +3909,17 @@ get_rule_expr(Node *node, deparse_context *context,
case IS_XMLELEMENT:
case IS_XMLFOREST:
case IS_XMLPI:
case IS_XMLSERIALIZE:
/* no extra decoration needed */
get_rule_expr((Node *) xexpr->args, context, true);
break;
case IS_XMLPARSE:
Assert(list_length(xexpr->args) == 3);
con = (Const *) lsecond(xexpr->args);
Assert(IsA(con, Const));
Assert(!con->constisnull);
if (DatumGetBool(con->constvalue))
appendStringInfoString(buf, "DOCUMENT ");
else
appendStringInfoString(buf, "CONTENT ");
Assert(list_length(xexpr->args) == 2);
get_rule_expr((Node *) linitial(xexpr->args),
context, true);
con = (Const *) lthird(xexpr->args);
con = (Const *) lsecond(xexpr->args);
Assert(IsA(con, Const));
Assert(!con->constisnull);
if (DatumGetBool(con->constvalue))
@@ -3944,12 +3947,26 @@ get_rule_expr(Node *node, deparse_context *context,
Assert(IsA(con, Const));
if (con->constisnull)
/* suppress STANDALONE NO VALUE */ ;
else if (DatumGetBool(con->constvalue))
appendStringInfoString(buf,
", STANDALONE YES");
else
appendStringInfoString(buf,
", STANDALONE NO");
{
switch (DatumGetInt32(con->constvalue))
{
case XML_STANDALONE_YES:
appendStringInfoString(buf,
", STANDALONE YES");
break;
case XML_STANDALONE_NO:
appendStringInfoString(buf,
", STANDALONE NO");
break;
case XML_STANDALONE_NO_VALUE:
appendStringInfoString(buf,
", STANDALONE NO VALUE");
break;
default:
break;
}
}
break;
case IS_DOCUMENT:
get_rule_expr_paren((Node *) xexpr->args, context, false, node);
@@ -3957,6 +3974,9 @@ get_rule_expr(Node *node, deparse_context *context,
}
}
if (xexpr->op == IS_XMLSERIALIZE)
appendStringInfo(buf, " AS %s", format_type_with_typemod(xexpr->type,
xexpr->typmod));
if (xexpr->op == IS_DOCUMENT)
appendStringInfoString(buf, " IS DOCUMENT");
else

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.24 2007/01/27 14:50:51 petere Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.25 2007/02/03 14:06:55 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -80,7 +80,7 @@ static void xml_ereport_by_code(int level, int sqlcode,
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);
static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xmlChar *encoding);
#endif /* USE_LIBXML */
@@ -112,7 +112,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, (xmloption == XMLOPTION_DOCUMENT), true, NULL);
doc = xml_parse(vardata, xmloption, true, NULL);
xmlFreeDoc(doc);
PG_RETURN_XML_P(vardata);
@@ -211,7 +211,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, (xmloption == XMLOPTION_DOCUMENT), true, encoding);
doc = xml_parse(result, xmloption, true, encoding);
xmlFreeDoc(doc);
newstr = (char *) pg_do_encoding_conversion((unsigned char *) str,
@@ -435,7 +435,29 @@ texttoxml(PG_FUNCTION_ARGS)
{
text *data = PG_GETARG_TEXT_P(0);
PG_RETURN_XML_P(xmlparse(data, (xmloption == XMLOPTION_DOCUMENT), true));
PG_RETURN_XML_P(xmlparse(data, xmloption, true));
}
Datum
xmltotext(PG_FUNCTION_ARGS)
{
xmltype *data = PG_GETARG_XML_P(0);
PG_RETURN_TEXT_P(xmltotext_with_xmloption(data, xmloption));
}
text *
xmltotext_with_xmloption(xmltype *data, XmlOptionType xmloption_arg)
{
if (xmloption_arg == XMLOPTION_DOCUMENT && !xml_is_document(data))
ereport(ERROR,
(errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
errmsg("not an XML document")));
/* It's actually binary compatible, save for the above check. */
return (text *) data;
}
@@ -499,12 +521,12 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
xmltype *
xmlparse(text *data, bool is_document, bool preserve_whitespace)
xmlparse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
{
#ifdef USE_LIBXML
xmlDocPtr doc;
doc = xml_parse(data, is_document, preserve_whitespace, NULL);
doc = xml_parse(data, xmloption_arg, preserve_whitespace, NULL);
xmlFreeDoc(doc);
return (xmltype *) data;
@@ -723,7 +745,7 @@ xml_is_document(xmltype *arg)
PG_TRY();
{
doc = xml_parse((text *) arg, true, true, NULL);
doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true, NULL);
result = true;
}
PG_CATCH();
@@ -996,7 +1018,7 @@ print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int stan
* TODO maybe, libxml2's xmlreader is better? (do not construct DOM, yet do not use SAX - see xml_reader.c)
*/
static xmlDocPtr
xml_parse(text *data, bool is_document, bool preserve_whitespace, xmlChar *encoding)
xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xmlChar *encoding)
{
int32 len;
xmlChar *string;
@@ -1024,7 +1046,7 @@ xml_parse(text *data, bool is_document, bool preserve_whitespace, xmlChar *encod
xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR,
"could not allocate parser context");
if (is_document)
if (xmloption_arg == XMLOPTION_DOCUMENT)
{
/*
* Note, that here we try to apply DTD defaults