aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r--src/backend/parser/parse_expr.c167
1 files changed, 109 insertions, 58 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 2a48741b3a2..7dbbb9a33a8 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.201 2006/12/23 00:43:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.202 2006/12/24 00:29:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -220,6 +220,10 @@ transformExpr(ParseState *pstate, Node *expr)
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break;
+ case T_XmlExpr:
+ result = transformXmlExpr(pstate, (XmlExpr *) expr);
+ break;
+
case T_NullTest:
{
NullTest *n = (NullTest *) expr;
@@ -234,10 +238,6 @@ transformExpr(ParseState *pstate, Node *expr)
result = transformBooleanTest(pstate, (BooleanTest *) expr);
break;
- case T_XmlExpr:
- result = transformXmlExpr(pstate, (XmlExpr *) expr);
- break;
-
/*********************************************
* Quietly accept node types that may be presented when we are
* called on an already-transformed tree.
@@ -1376,6 +1376,107 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
}
static Node *
+transformXmlExpr(ParseState *pstate, XmlExpr *x)
+{
+ XmlExpr *newx = makeNode(XmlExpr);
+ ListCell *lc;
+ int i;
+
+ newx->op = x->op;
+ if (x->name)
+ newx->name = map_sql_identifier_to_xml_name(x->name, false);
+ else
+ newx->name = NULL;
+
+ /*
+ * gram.y built the named args as a list of ResTarget. Transform each,
+ * and break the names out as a separate list.
+ */
+ newx->named_args = NIL;
+ newx->arg_names = NIL;
+
+ foreach(lc, x->named_args)
+ {
+ ResTarget *r = (ResTarget *) lfirst(lc);
+ Node *expr;
+ char *argname;
+
+ Assert(IsA(r, ResTarget));
+
+ expr = transformExpr(pstate, r->val);
+
+ if (r->name)
+ argname = map_sql_identifier_to_xml_name(r->name, false);
+ else if (IsA(r->val, ColumnRef))
+ argname = map_sql_identifier_to_xml_name(FigureColname(r->val),
+ true);
+ else
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ x->op == IS_XMLELEMENT
+ ? errmsg("unnamed attribute value must be a column reference")
+ : errmsg("unnamed element value must be a column reference")));
+ argname = NULL; /* keep compiler quiet */
+ }
+
+ newx->named_args = lappend(newx->named_args, expr);
+ newx->arg_names = lappend(newx->arg_names, makeString(argname));
+ }
+
+ /* The other arguments are of varying types depending on the function */
+ newx->args = NIL;
+ i = 0;
+ foreach(lc, x->args)
+ {
+ Node *e = (Node *) lfirst(lc);
+ Node *newe;
+
+ newe = transformExpr(pstate, e);
+ switch (x->op)
+ {
+ case IS_XMLCONCAT:
+ newe = coerce_to_specific_type(pstate, newe, XMLOID,
+ "XMLCONCAT");
+ break;
+ case IS_XMLELEMENT:
+ newe = coerce_to_specific_type(pstate, newe, XMLOID,
+ "XMLELEMENT");
+ break;
+ case IS_XMLFOREST:
+ newe = coerce_to_specific_type(pstate, newe, XMLOID,
+ "XMLFOREST");
+ break;
+ case IS_XMLPARSE:
+ if (i == 0)
+ newe = coerce_to_specific_type(pstate, newe, TEXTOID,
+ "XMLPARSE");
+ else
+ newe = coerce_to_boolean(pstate, newe, "XMLPARSE");
+ break;
+ case IS_XMLPI:
+ newe = coerce_to_specific_type(pstate, newe, TEXTOID,
+ "XMLPI");
+ break;
+ case IS_XMLROOT:
+ if (i == 0)
+ newe = coerce_to_specific_type(pstate, newe, XMLOID,
+ "XMLROOT");
+ else if (i == 1)
+ newe = coerce_to_specific_type(pstate, newe, TEXTOID,
+ "XMLROOT");
+ else
+ newe = coerce_to_boolean(pstate, newe, "XMLROOT");
+ break;
+ }
+ newx->args = lappend(newx->args, newe);
+ i++;
+ }
+
+ return (Node *) newx;
+}
+
+static Node *
transformBooleanTest(ParseState *pstate, BooleanTest *b)
{
const char *clausename;
@@ -1415,56 +1516,6 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
return (Node *) b;
}
-static Node *
-transformXmlExpr(ParseState *pstate, XmlExpr *x)
-{
- ListCell *lc;
- XmlExpr *newx = makeNode(XmlExpr);
-
- newx->op = x->op;
- if (x->name)
- newx->name = map_sql_identifier_to_xml_name(x->name, false);
- else
- newx->name = NULL;
-
- foreach(lc, x->named_args)
- {
- ResTarget *r = (ResTarget *) lfirst(lc);
- Node *expr = transformExpr(pstate, r->val);
- char *argname = NULL;
-
- if (r->name)
- argname = map_sql_identifier_to_xml_name(r->name, false);
- else if (IsA(r->val, ColumnRef))
- argname = map_sql_identifier_to_xml_name(FigureColname(r->val), true);
- else
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- x->op == IS_XMLELEMENT
- ? errmsg("unnamed attribute value must be a column reference")
- : errmsg("unnamed element value must be a column reference")));
-
- newx->named_args = lappend(newx->named_args,
- makeTargetEntry((Expr *) expr, 0, argname, false));
- }
-
- foreach(lc, x->args)
- {
- Node *e = (Node *) lfirst(lc);
- Node *newe;
-
- newe = coerce_to_xml(pstate, transformExpr(pstate, e),
- (x->op == IS_XMLCONCAT
- ? "XMLCONCAT"
- : (x->op == IS_XMLELEMENT
- ? "XMLELEMENT"
- : "XMLFOREST")));
- newx->args = lappend(newx->args, newe);
- }
-
- return (Node *) newx;
-}
-
/*
* Construct a whole-row reference to represent the notation "relation.*".
*
@@ -1715,6 +1766,9 @@ exprType(Node *expr)
case T_MinMaxExpr:
type = ((MinMaxExpr *) expr)->minmaxtype;
break;
+ case T_XmlExpr:
+ type = XMLOID;
+ break;
case T_NullIfExpr:
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
break;
@@ -1724,9 +1778,6 @@ exprType(Node *expr)
case T_BooleanTest:
type = BOOLOID;
break;
- case T_XmlExpr:
- type = XMLOID;
- break;
case T_CoerceToDomain:
type = ((CoerceToDomain *) expr)->resulttype;
break;