aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y39
-rw-r--r--src/backend/parser/parse_expr.c46
-rw-r--r--src/backend/parser/parse_target.c8
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;
}