mirror of https://github.com/postgres/postgres
Add support for xmlval IS DOCUMENT expression.
This commit is contained in:
parent
62c06186f5
commit
2f8f76bcd5
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.206 2007/01/12 21:47:26 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.207 2007/01/14 13:11:53 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -2808,6 +2808,25 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
|
|||
standalone));
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_DOCUMENT:
|
||||
{
|
||||
ExprState *e;
|
||||
|
||||
/* optional argument is known to be xml */
|
||||
Assert(list_length(xmlExpr->args) == 1);
|
||||
|
||||
e = (ExprState *) linitial(xmlExpr->args);
|
||||
value = ExecEvalExpr(e, econtext, &isnull, NULL);
|
||||
if (isnull)
|
||||
return (Datum) 0;
|
||||
else
|
||||
{
|
||||
*isNull = false;
|
||||
return BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (*isNull)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.573 2007/01/09 02:14:14 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.574 2007/01/14 13:11:53 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
|
@ -7147,6 +7147,16 @@ a_expr: c_expr { $$ = $1; }
|
|||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("UNIQUE predicate is not yet implemented")));
|
||||
}
|
||||
| a_expr IS DOCUMENT_P %prec IS
|
||||
{
|
||||
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1));
|
||||
}
|
||||
| a_expr IS NOT DOCUMENT_P %prec IS
|
||||
{
|
||||
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
|
||||
makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1)),
|
||||
@2);
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
|
@ -7207,6 +7217,16 @@ b_expr: c_expr
|
|||
{
|
||||
$$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2);
|
||||
}
|
||||
| b_expr IS DOCUMENT_P %prec IS
|
||||
{
|
||||
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1));
|
||||
}
|
||||
| b_expr IS NOT DOCUMENT_P %prec IS
|
||||
{
|
||||
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
|
||||
makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1)),
|
||||
@2);
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.207 2007/01/12 22:09:49 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.208 2007/01/14 13:11:53 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -1483,6 +1483,10 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
|
|||
else
|
||||
newe = coerce_to_boolean(pstate, newe, "XMLROOT");
|
||||
break;
|
||||
case IS_DOCUMENT:
|
||||
newe = coerce_to_specific_type(pstate, newe, XMLOID,
|
||||
"IS DOCUMENT");
|
||||
break;
|
||||
}
|
||||
newx->args = lappend(newx->args, newe);
|
||||
i++;
|
||||
|
@ -1782,7 +1786,10 @@ exprType(Node *expr)
|
|||
type = ((MinMaxExpr *) expr)->minmaxtype;
|
||||
break;
|
||||
case T_XmlExpr:
|
||||
type = XMLOID;
|
||||
if (((XmlExpr *) expr)->op == IS_DOCUMENT)
|
||||
type = BOOLOID;
|
||||
else
|
||||
type = XMLOID;
|
||||
break;
|
||||
case T_NullIfExpr:
|
||||
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.152 2007/01/05 22:19:34 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.153 2007/01/14 13:11:54 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -1337,6 +1337,9 @@ FigureColnameInternal(Node *node, char **name)
|
|||
case IS_XMLROOT:
|
||||
*name = "xmlroot";
|
||||
return 2;
|
||||
case IS_DOCUMENT:
|
||||
/* nothing */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* ruleutils.c - Functions to convert stored expressions/querytrees
|
||||
* back to source text
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.241 2007/01/09 02:14:14 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.242 2007/01/14 13:11:54 petere Exp $
|
||||
**********************************************************************/
|
||||
|
||||
#include "postgres.h"
|
||||
|
@ -3847,6 +3847,8 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||
case IS_XMLROOT:
|
||||
appendStringInfoString(buf, "XMLROOT(");
|
||||
break;
|
||||
case IS_DOCUMENT:
|
||||
break;
|
||||
}
|
||||
if (xexpr->name)
|
||||
{
|
||||
|
@ -3888,6 +3890,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||
case IS_XMLELEMENT:
|
||||
case IS_XMLFOREST:
|
||||
case IS_XMLPI:
|
||||
case IS_DOCUMENT:
|
||||
/* no extra decoration needed */
|
||||
get_rule_expr((Node *) xexpr->args, context, true);
|
||||
break;
|
||||
|
@ -3943,7 +3946,10 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||
}
|
||||
|
||||
}
|
||||
appendStringInfoChar(buf, ')');
|
||||
if (xexpr->op == IS_DOCUMENT)
|
||||
appendStringInfoString(buf, " IS DOCUMENT");
|
||||
else
|
||||
appendStringInfoChar(buf, ')');
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -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.16 2007/01/12 21:47:26 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.17 2007/01/14 13:11:54 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -515,6 +515,50 @@ xmlvalidate(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
xml_is_document(xmltype *arg)
|
||||
{
|
||||
#ifdef USE_LIBXML
|
||||
bool result;
|
||||
xmlDocPtr doc = NULL;
|
||||
MemoryContext ccxt = CurrentMemoryContext;
|
||||
|
||||
PG_TRY();
|
||||
{
|
||||
doc = xml_parse((text *) arg, true, true);
|
||||
result = true;
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
ErrorData *errdata;
|
||||
MemoryContext ecxt;
|
||||
|
||||
ecxt = MemoryContextSwitchTo(ccxt);
|
||||
errdata = CopyErrorData();
|
||||
if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
|
||||
{
|
||||
FlushErrorState();
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryContextSwitchTo(ecxt);
|
||||
PG_RE_THROW();
|
||||
}
|
||||
}
|
||||
PG_END_TRY();
|
||||
|
||||
if (doc)
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
return result;
|
||||
#else /* not USE_LIBXML */
|
||||
NO_XML_SUPPORT();
|
||||
return false;
|
||||
#endif /* not USE_LIBXML */
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_LIBXML
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.122 2007/01/05 22:19:56 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.123 2007/01/14 13:11:54 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -725,7 +725,8 @@ typedef enum XmlExprOp
|
|||
IS_XMLFOREST, /* XMLFOREST(xml_attributes) */
|
||||
IS_XMLPARSE, /* XMLPARSE(text, is_doc, preserve_ws) */
|
||||
IS_XMLPI, /* XMLPI(name [, args]) */
|
||||
IS_XMLROOT /* XMLROOT(xml, version, standalone) */
|
||||
IS_XMLROOT, /* XMLROOT(xml, version, standalone) */
|
||||
IS_DOCUMENT /* xmlval IS DOCUMENT */
|
||||
} XmlExprOp;
|
||||
|
||||
typedef struct XmlExpr
|
||||
|
|
|
@ -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.9 2007/01/12 21:47:27 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.10 2007/01/14 13:11:54 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -37,6 +37,7 @@ extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
|
|||
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
|
||||
extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
|
||||
extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
|
||||
extern bool xml_is_document(xmltype *arg);
|
||||
|
||||
extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
|
||||
extern char *map_xml_name_to_sql_identifier(char *name);
|
||||
|
|
|
@ -228,6 +228,33 @@ SELECT xmlserialize(content data as character varying) FROM xmltest;
|
|||
<value>two</value>
|
||||
(2 rows)
|
||||
|
||||
SELECT xml '<foo>bar</foo>' IS DOCUMENT;
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT xml '<abc/>' IS NOT DOCUMENT;
|
||||
?column?
|
||||
----------
|
||||
f
|
||||
(1 row)
|
||||
|
||||
SELECT xml 'abc' IS NOT DOCUMENT;
|
||||
?column?
|
||||
----------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
SELECT '<>' IS NOT DOCUMENT;
|
||||
ERROR: invalid XML content
|
||||
DETAIL: Element name not found
|
||||
-- Check mapping SQL identifier to XML name
|
||||
SELECT xmlpi(name ":::_xml_abc135.%-&_");
|
||||
xmlpi
|
||||
|
|
|
@ -107,6 +107,16 @@ SELECT xmlserialize(content data as character varying) FROM xmltest;
|
|||
------
|
||||
(0 rows)
|
||||
|
||||
SELECT xml '<foo>bar</foo>' IS DOCUMENT;
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xml '<abc/>' IS NOT DOCUMENT;
|
||||
ERROR: no XML support in this installation
|
||||
SELECT xml 'abc' IS NOT DOCUMENT;
|
||||
ERROR: no XML support in this installation
|
||||
SELECT '<>' IS NOT DOCUMENT;
|
||||
ERROR: no XML support in this installation
|
||||
-- Check mapping SQL identifier to XML name
|
||||
SELECT xmlpi(name ":::_xml_abc135.%-&_");
|
||||
ERROR: no XML support in this installation
|
||||
|
|
|
@ -86,6 +86,13 @@ SELECT xmlroot (
|
|||
SELECT xmlserialize(content data as character varying) FROM xmltest;
|
||||
|
||||
|
||||
SELECT xml '<foo>bar</foo>' IS DOCUMENT;
|
||||
SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
|
||||
SELECT xml '<abc/>' IS NOT DOCUMENT;
|
||||
SELECT xml 'abc' IS NOT DOCUMENT;
|
||||
SELECT '<>' IS NOT DOCUMENT;
|
||||
|
||||
|
||||
-- Check mapping SQL identifier to XML name
|
||||
|
||||
SELECT xmlpi(name ":::_xml_abc135.%-&_");
|
||||
|
|
Loading…
Reference in New Issue