diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 39 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 46 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 8 |
3 files changed, 70 insertions, 23 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 1f1dfdb761d..cf25c5607a6 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.578 2007/02/01 19:10:27 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.579 2007/02/03 14:06:54 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -350,7 +350,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) %type <target> xml_attribute_el %type <list> xml_attribute_list xml_attributes %type <node> xml_root_version opt_xml_root_standalone -%type <boolean> document_or_content xml_whitespace_option +%type <ival> document_or_content +%type <boolean> xml_whitespace_option /* @@ -1117,7 +1118,7 @@ set_rest: var_name TO var_list_or_default { VariableSetStmt *n = makeNode(VariableSetStmt); n->name = "xmloption"; - n->args = list_make1(makeStringConst($3 ? "DOCUMENT" : "CONTENT", NULL)); + n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", NULL)); $$ = n; } ; @@ -7903,10 +7904,11 @@ func_expr: func_name '(' ')' } | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')' { - $$ = makeXmlExpr(IS_XMLPARSE, NULL, NIL, - list_make3($4, - makeBoolAConst($3), - makeBoolAConst($5))); + XmlExpr *x = (XmlExpr *) makeXmlExpr(IS_XMLPARSE, NULL, NIL, + list_make2($4, + makeBoolAConst($5))); + x->xmloption = $3; + $$ = (Node *)x; } | XMLPI '(' NAME_P ColLabel ')' { @@ -7921,14 +7923,13 @@ func_expr: func_name '(' ')' $$ = makeXmlExpr(IS_XMLROOT, NULL, NIL, list_make3($3, $5, $6)); } - | XMLSERIALIZE '(' document_or_content a_expr AS Typename ')' + | XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')' { - /* - * FIXME: This should be made distinguishable from - * CAST (for reverse compilation at least). Also, - * what about the document/content option?? - */ - $$ = makeTypeCast($4, $6); + XmlSerialize *n = makeNode(XmlSerialize); + n->xmloption = $3; + n->expr = $4; + n->typename = $6; + $$ = (Node *)n; } ; @@ -7980,17 +7981,13 @@ xml_attribute_el: a_expr AS ColLabel } ; -document_or_content: DOCUMENT_P { $$ = TRUE; } - | CONTENT_P { $$ = FALSE; } +document_or_content: DOCUMENT_P { $$ = XMLOPTION_DOCUMENT; } + | CONTENT_P { $$ = XMLOPTION_CONTENT; } ; -/* - * XXX per SQL spec, the default should be STRIP WHITESPACE, but since we - * haven't implemented that yet, temporarily default to PRESERVE. - */ xml_whitespace_option: PRESERVE WHITESPACE_P { $$ = TRUE; } | STRIP_P WHITESPACE_P { $$ = FALSE; } - | /*EMPTY*/ { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } ; /* diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index a807ef12de4..e7a37a2cfa6 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.209 2007/01/25 11:53:51 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.210 2007/02/03 14:06:54 petere Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,7 @@ static Node *transformRowExpr(ParseState *pstate, RowExpr *r); static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c); static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m); static Node *transformXmlExpr(ParseState *pstate, XmlExpr *x); +static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformWholeRowRef(ParseState *pstate, char *schemaname, @@ -224,6 +225,10 @@ transformExpr(ParseState *pstate, Node *expr) result = transformXmlExpr(pstate, (XmlExpr *) expr); break; + case T_XmlSerialize: + result = transformXmlSerialize(pstate, (XmlSerialize *) expr); + break; + case T_NullTest: { NullTest *n = (NullTest *) expr; @@ -1424,6 +1429,8 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x) newx->arg_names = lappend(newx->arg_names, makeString(argname)); } + newx->xmloption = x->xmloption; + if (x->op == IS_XMLELEMENT) { foreach(lc, newx->arg_names) @@ -1484,6 +1491,9 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x) newe = coerce_to_specific_type(pstate, newe, INT4OID, "XMLROOT"); break; + case IS_XMLSERIALIZE: + /* not handled here */ + break; case IS_DOCUMENT: newe = coerce_to_specific_type(pstate, newe, XMLOID, "IS DOCUMENT"); @@ -1497,6 +1507,38 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x) } static Node * +transformXmlSerialize(ParseState *pstate, XmlSerialize *xs) +{ + Oid targetType; + int32 targetTypmod; + XmlExpr *xexpr; + + xexpr = makeNode(XmlExpr); + xexpr->op = IS_XMLSERIALIZE; + xexpr->args = list_make1(coerce_to_specific_type(pstate, + transformExpr(pstate, xs->expr), + XMLOID, + "XMLSERIALIZE")); + + targetType = typenameTypeId(pstate, xs->typename); + targetTypmod = typenameTypeMod(pstate, xs->typename, targetType); + + xexpr->xmloption = xs->xmloption; + /* We actually only need these to be able to parse back the expression. */ + xexpr->type = targetType; + xexpr->typmod = targetTypmod; + + /* + * The actual target type is determined this way. SQL allows char + * and varchar as target types. We allow anything that can be + * cast implicitly from text. This way, user-defined text-like + * data types automatically fit in. + */ + return (Node *) coerce_to_target_type(pstate, (Node *) xexpr, TEXTOID, targetType, targetTypmod, + COERCION_IMPLICIT, COERCE_IMPLICIT_CAST); +} + +static Node * transformBooleanTest(ParseState *pstate, BooleanTest *b) { const char *clausename; @@ -1789,6 +1831,8 @@ exprType(Node *expr) case T_XmlExpr: if (((XmlExpr *) expr)->op == IS_DOCUMENT) type = BOOLOID; + else if (((XmlExpr *) expr)->op == IS_XMLSERIALIZE) + type = TEXTOID; else type = XMLOID; break; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index dea29d1d8aa..cc4bc091d24 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.153 2007/01/14 13:11:54 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.154 2007/02/03 14:06:54 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1337,11 +1337,17 @@ FigureColnameInternal(Node *node, char **name) case IS_XMLROOT: *name = "xmlroot"; return 2; + case IS_XMLSERIALIZE: + *name = "xmlserialize"; + return 2; case IS_DOCUMENT: /* nothing */ break; } break; + case T_XmlSerialize: + *name = "xmlserialize"; + return 2; default: break; } |