Skip to content

Commit 2f8f76b

Browse files
committed
Add support for xmlval IS DOCUMENT expression.
1 parent 62c0618 commit 2f8f76b

File tree

11 files changed

+156
-11
lines changed

11 files changed

+156
-11
lines changed

src/backend/executor/execQual.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.206 2007/01/12 21:47:26 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.207 2007/01/14 13:11:53 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2808,6 +2808,25 @@ ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
28082808
standalone));
28092809
}
28102810
break;
2811+
2812+
case IS_DOCUMENT:
2813+
{
2814+
ExprState *e;
2815+
2816+
/* optional argument is known to be xml */
2817+
Assert(list_length(xmlExpr->args) == 1);
2818+
2819+
e = (ExprState *) linitial(xmlExpr->args);
2820+
value = ExecEvalExpr(e, econtext, &isnull, NULL);
2821+
if (isnull)
2822+
return (Datum) 0;
2823+
else
2824+
{
2825+
*isNull = false;
2826+
return BoolGetDatum(xml_is_document(DatumGetXmlP(value)));
2827+
}
2828+
}
2829+
break;
28112830
}
28122831

28132832
if (*isNull)

src/backend/parser/gram.y

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.573 2007/01/09 02:14:14 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.574 2007/01/14 13:11:53 petere Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -7147,6 +7147,16 @@ a_expr: c_expr { $$ = $1; }
71477147
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
71487148
errmsg("UNIQUE predicate is not yet implemented")));
71497149
}
7150+
| a_expr IS DOCUMENT_P %prec IS
7151+
{
7152+
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1));
7153+
}
7154+
| a_expr IS NOT DOCUMENT_P %prec IS
7155+
{
7156+
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
7157+
makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1)),
7158+
@2);
7159+
}
71507160
;
71517161

71527162
/*
@@ -7207,6 +7217,16 @@ b_expr: c_expr
72077217
{
72087218
$$ = (Node *) makeSimpleA_Expr(AEXPR_OF, "<>", $1, (Node *) $6, @2);
72097219
}
7220+
| b_expr IS DOCUMENT_P %prec IS
7221+
{
7222+
$$ = makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1));
7223+
}
7224+
| b_expr IS NOT DOCUMENT_P %prec IS
7225+
{
7226+
$$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL,
7227+
makeXmlExpr(IS_DOCUMENT, NULL, NIL, list_make1($1)),
7228+
@2);
7229+
}
72107230
;
72117231

72127232
/*

src/backend/parser/parse_expr.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.207 2007/01/12 22:09:49 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.208 2007/01/14 13:11:53 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1483,6 +1483,10 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
14831483
else
14841484
newe = coerce_to_boolean(pstate, newe, "XMLROOT");
14851485
break;
1486+
case IS_DOCUMENT:
1487+
newe = coerce_to_specific_type(pstate, newe, XMLOID,
1488+
"IS DOCUMENT");
1489+
break;
14861490
}
14871491
newx->args = lappend(newx->args, newe);
14881492
i++;
@@ -1782,7 +1786,10 @@ exprType(Node *expr)
17821786
type = ((MinMaxExpr *) expr)->minmaxtype;
17831787
break;
17841788
case T_XmlExpr:
1785-
type = XMLOID;
1789+
if (((XmlExpr *) expr)->op == IS_DOCUMENT)
1790+
type = BOOLOID;
1791+
else
1792+
type = XMLOID;
17861793
break;
17871794
case T_NullIfExpr:
17881795
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));

src/backend/parser/parse_target.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.152 2007/01/05 22:19:34 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.153 2007/01/14 13:11:54 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1337,6 +1337,9 @@ FigureColnameInternal(Node *node, char **name)
13371337
case IS_XMLROOT:
13381338
*name = "xmlroot";
13391339
return 2;
1340+
case IS_DOCUMENT:
1341+
/* nothing */
1342+
break;
13401343
}
13411344
break;
13421345
default:

src/backend/utils/adt/ruleutils.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* ruleutils.c - Functions to convert stored expressions/querytrees
33
* back to source text
44
*
5-
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.241 2007/01/09 02:14:14 tgl Exp $
5+
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.242 2007/01/14 13:11:54 petere Exp $
66
**********************************************************************/
77

88
#include "postgres.h"
@@ -3847,6 +3847,8 @@ get_rule_expr(Node *node, deparse_context *context,
38473847
case IS_XMLROOT:
38483848
appendStringInfoString(buf, "XMLROOT(");
38493849
break;
3850+
case IS_DOCUMENT:
3851+
break;
38503852
}
38513853
if (xexpr->name)
38523854
{
@@ -3888,6 +3890,7 @@ get_rule_expr(Node *node, deparse_context *context,
38883890
case IS_XMLELEMENT:
38893891
case IS_XMLFOREST:
38903892
case IS_XMLPI:
3893+
case IS_DOCUMENT:
38913894
/* no extra decoration needed */
38923895
get_rule_expr((Node *) xexpr->args, context, true);
38933896
break;
@@ -3943,7 +3946,10 @@ get_rule_expr(Node *node, deparse_context *context,
39433946
}
39443947

39453948
}
3946-
appendStringInfoChar(buf, ')');
3949+
if (xexpr->op == IS_DOCUMENT)
3950+
appendStringInfoString(buf, " IS DOCUMENT");
3951+
else
3952+
appendStringInfoChar(buf, ')');
39473953
}
39483954
break;
39493955

src/backend/utils/adt/xml.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.16 2007/01/12 21:47:26 petere Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.17 2007/01/14 13:11:54 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -515,6 +515,50 @@ xmlvalidate(PG_FUNCTION_ARGS)
515515
}
516516

517517

518+
bool
519+
xml_is_document(xmltype *arg)
520+
{
521+
#ifdef USE_LIBXML
522+
bool result;
523+
xmlDocPtr doc = NULL;
524+
MemoryContext ccxt = CurrentMemoryContext;
525+
526+
PG_TRY();
527+
{
528+
doc = xml_parse((text *) arg, true, true);
529+
result = true;
530+
}
531+
PG_CATCH();
532+
{
533+
ErrorData *errdata;
534+
MemoryContext ecxt;
535+
536+
ecxt = MemoryContextSwitchTo(ccxt);
537+
errdata = CopyErrorData();
538+
if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
539+
{
540+
FlushErrorState();
541+
result = false;
542+
}
543+
else
544+
{
545+
MemoryContextSwitchTo(ecxt);
546+
PG_RE_THROW();
547+
}
548+
}
549+
PG_END_TRY();
550+
551+
if (doc)
552+
xmlFreeDoc(doc);
553+
554+
return result;
555+
#else /* not USE_LIBXML */
556+
NO_XML_SUPPORT();
557+
return false;
558+
#endif /* not USE_LIBXML */
559+
}
560+
561+
518562
#ifdef USE_LIBXML
519563

520564
/*

src/include/nodes/primnodes.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
13-
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.122 2007/01/05 22:19:56 momjian Exp $
13+
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.123 2007/01/14 13:11:54 petere Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -725,7 +725,8 @@ typedef enum XmlExprOp
725725
IS_XMLFOREST, /* XMLFOREST(xml_attributes) */
726726
IS_XMLPARSE, /* XMLPARSE(text, is_doc, preserve_ws) */
727727
IS_XMLPI, /* XMLPI(name [, args]) */
728-
IS_XMLROOT /* XMLROOT(xml, version, standalone) */
728+
IS_XMLROOT, /* XMLROOT(xml, version, standalone) */
729+
IS_DOCUMENT /* xmlval IS DOCUMENT */
729730
} XmlExprOp;
730731

731732
typedef struct XmlExpr

src/include/utils/xml.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.9 2007/01/12 21:47:27 petere Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.10 2007/01/14 13:11:54 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -37,6 +37,7 @@ extern xmltype *xmlelement(XmlExprState *xmlExpr, ExprContext *econtext);
3737
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
3838
extern xmltype *xmlpi(char *target, text *arg, bool arg_is_null, bool *result_is_null);
3939
extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
40+
extern bool xml_is_document(xmltype *arg);
4041

4142
extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
4243
extern char *map_xml_name_to_sql_identifier(char *name);

src/test/regress/expected/xml.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,33 @@ SELECT xmlserialize(content data as character varying) FROM xmltest;
228228
<value>two</value>
229229
(2 rows)
230230

231+
SELECT xml '<foo>bar</foo>' IS DOCUMENT;
232+
?column?
233+
----------
234+
t
235+
(1 row)
236+
237+
SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
238+
?column?
239+
----------
240+
f
241+
(1 row)
242+
243+
SELECT xml '<abc/>' IS NOT DOCUMENT;
244+
?column?
245+
----------
246+
f
247+
(1 row)
248+
249+
SELECT xml 'abc' IS NOT DOCUMENT;
250+
?column?
251+
----------
252+
t
253+
(1 row)
254+
255+
SELECT '<>' IS NOT DOCUMENT;
256+
ERROR: invalid XML content
257+
DETAIL: Element name not found
231258
-- Check mapping SQL identifier to XML name
232259
SELECT xmlpi(name ":::_xml_abc135.%-&_");
233260
xmlpi

src/test/regress/expected/xml_1.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,16 @@ SELECT xmlserialize(content data as character varying) FROM xmltest;
107107
------
108108
(0 rows)
109109

110+
SELECT xml '<foo>bar</foo>' IS DOCUMENT;
111+
ERROR: no XML support in this installation
112+
SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
113+
ERROR: no XML support in this installation
114+
SELECT xml '<abc/>' IS NOT DOCUMENT;
115+
ERROR: no XML support in this installation
116+
SELECT xml 'abc' IS NOT DOCUMENT;
117+
ERROR: no XML support in this installation
118+
SELECT '<>' IS NOT DOCUMENT;
119+
ERROR: no XML support in this installation
110120
-- Check mapping SQL identifier to XML name
111121
SELECT xmlpi(name ":::_xml_abc135.%-&_");
112122
ERROR: no XML support in this installation

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy