diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 191 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 20 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_coerce.c | 101 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 167 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 11 |
6 files changed, 233 insertions, 261 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index cc400407363..a1511870f28 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.569 2006/12/21 16:05:14 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.570 2006/12/24 00:29:18 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -348,8 +348,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 -%type <ival> opt_xml_root_standalone document_or_content xml_whitespace_option +%type <node> xml_root_version opt_xml_root_standalone +%type <boolean> document_or_content xml_whitespace_option /* @@ -371,13 +371,13 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS - CONTENT CONVERSION_P CONVERT COPY CREATE CREATEDB + CONTENT_P CONVERSION_P CONVERT COPY CREATE CREATEDB CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS - DESC DISABLE_P DISTINCT DO DOCUMENT DOMAIN_P DOUBLE_P DROP + DESC DISABLE_P DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT @@ -404,7 +404,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE - NAME NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB + NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC @@ -423,9 +423,9 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE - SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE START STATEMENT - STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP SUBSTRING SUPERUSER_P SYMMETRIC - SYSID SYSTEM_P + SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT + STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P + SYMMETRIC SYSID SYSTEM_P TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P @@ -434,15 +434,15 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USER USING - VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING - VERBOSE VERSION VIEW VOLATILE + VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARYING + VERBOSE VERSION_P VIEW VOLATILE - WHEN WHERE WHITESPACE WITH WITHOUT WORK WRITE + WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRITE XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE XMLPI XMLROOT XMLSERIALIZE - YEAR_P YES + YEAR_P YES_P ZONE @@ -493,7 +493,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) * left-associativity among the JOIN rules themselves. */ %left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL -%right PRESERVE STRIP +/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */ +%right PRESERVE STRIP_P %% /* @@ -7880,95 +7881,54 @@ func_expr: func_name '(' ')' } | XMLCONCAT '(' expr_list ')' { - $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NULL, $3); + $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3); } - | XMLELEMENT '(' NAME ColLabel ')' + | XMLELEMENT '(' NAME_P ColLabel ')' { - $$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, NULL); + $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, NIL); } - | XMLELEMENT '(' NAME ColLabel ',' xml_attributes ')' + | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')' { - $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NULL); + $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NIL); } - | XMLELEMENT '(' NAME ColLabel ',' expr_list ')' + | XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')' { - $$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, $6); + $$ = makeXmlExpr(IS_XMLELEMENT, $4, NIL, $6); } - | XMLELEMENT '(' NAME ColLabel ',' xml_attributes ',' expr_list ')' + | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')' { $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8); } | XMLFOREST '(' xml_attribute_list ')' { - $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NULL); + $$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NIL); } | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')' { - FuncCall *n = makeNode(FuncCall); - n->funcname = SystemFuncName("xmlparse"); - n->args = list_make3(makeBoolAConst($3 == DOCUMENT), $4, makeBoolAConst($5 == PRESERVE)); - n->agg_star = FALSE; - n->agg_distinct = FALSE; - n->location = @1; - $$ = (Node *)n; + $$ = makeXmlExpr(IS_XMLPARSE, NULL, NIL, + list_make3($4, + makeBoolAConst($3), + makeBoolAConst($5))); } - | XMLPI '(' NAME ColLabel ')' + | XMLPI '(' NAME_P ColLabel ')' { - FuncCall *n = makeNode(FuncCall); - n->funcname = SystemFuncName("xmlpi"); - n->args = list_make1(makeStringConst($4, NULL)); - n->agg_star = FALSE; - n->agg_distinct = FALSE; - n->location = @1; - $$ = (Node *)n; + $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL); } - | XMLPI '(' NAME ColLabel ',' a_expr ')' + | XMLPI '(' NAME_P ColLabel ',' a_expr ')' { - FuncCall *n = makeNode(FuncCall); - n->funcname = SystemFuncName("xmlpi"); - n->args = list_make2(makeStringConst($4, NULL), $6); - n->agg_star = FALSE; - n->agg_distinct = FALSE; - n->location = @1; - $$ = (Node *)n; + $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6)); } | XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')' { - FuncCall *n = makeNode(FuncCall); - Node *ver; - A_Const *sa; - - if ($5) - ver = $5; - else - { - A_Const *val; - - val = makeNode(A_Const); - val->val.type = T_Null; - ver = (Node *) val; - } - - if ($6) - sa = makeBoolAConst($6 == 1); - else - { - sa = makeNode(A_Const); - sa->val.type = T_Null; - } - - n->funcname = SystemFuncName("xmlroot"); - n->args = list_make3($3, ver, sa); - n->agg_star = FALSE; - n->agg_distinct = FALSE; - n->location = @1; - $$ = (Node *)n; + $$ = makeXmlExpr(IS_XMLROOT, NULL, NIL, + list_make3($3, $5, $6)); } | XMLSERIALIZE '(' document_or_content a_expr AS Typename ')' { /* * FIXME: This should be made distinguishable from - * CAST (for reverse compilation at least). + * CAST (for reverse compilation at least). Also, + * what about the document/content option?? */ $$ = makeTypeCast($4, $6); } @@ -7977,17 +7937,35 @@ func_expr: func_name '(' ')' /* * SQL/XML support */ -xml_root_version: VERSION a_expr { $$ = $2; } - | VERSION NO VALUE { $$ = NULL; } +xml_root_version: VERSION_P a_expr + { $$ = $2; } + | VERSION_P NO VALUE_P + { + A_Const *val = makeNode(A_Const); + val->val.type = T_Null; + $$ = (Node *) val; + } ; -opt_xml_root_standalone: ',' STANDALONE YES { $$ = 1; } - | ',' STANDALONE NO { $$ = -1; } - | ',' STANDALONE NO VALUE { $$ = 0; } - | /*EMPTY*/ { $$ = 0; } +opt_xml_root_standalone: ',' STANDALONE_P YES_P + { $$ = (Node *) makeBoolAConst(true); } + | ',' STANDALONE_P NO + { $$ = (Node *) makeBoolAConst(false); } + | ',' STANDALONE_P NO VALUE_P + { + A_Const *val = makeNode(A_Const); + val->val.type = T_Null; + $$ = (Node *) val; + } + | /*EMPTY*/ + { + A_Const *val = makeNode(A_Const); + val->val.type = T_Null; + $$ = (Node *) val; + } ; -xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; } +xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; } ; xml_attribute_list: xml_attribute_el { $$ = list_make1($1); } @@ -8000,7 +7978,7 @@ xml_attribute_el: a_expr AS ColLabel $$->name = $3; $$->indirection = NULL; $$->val = (Node *) $1; - + $$->location = @1; } | a_expr { @@ -8008,16 +7986,21 @@ xml_attribute_el: a_expr AS ColLabel $$->name = NULL; $$->indirection = NULL; $$->val = (Node *) $1; + $$->location = @1; } ; -document_or_content: DOCUMENT { $$ = DOCUMENT; } - | CONTENT { $$ = CONTENT; } +document_or_content: DOCUMENT_P { $$ = TRUE; } + | CONTENT_P { $$ = FALSE; } ; -xml_whitespace_option: PRESERVE WHITESPACE { $$ = PRESERVE; } - | STRIP WHITESPACE { $$ = STRIP; } - | /*EMPTY*/ { $$ = STRIP; } +/* + * 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; } ; /* @@ -8712,7 +8695,7 @@ unreserved_keyword: | CONCURRENTLY | CONNECTION | CONSTRAINTS - | CONTENT + | CONTENT_P | CONVERSION_P | COPY | CREATEDB @@ -8732,7 +8715,7 @@ unreserved_keyword: | DELIMITER | DELIMITERS | DISABLE_P - | DOCUMENT + | DOCUMENT_P | DOMAIN_P | DOUBLE_P | DROP @@ -8792,7 +8775,7 @@ unreserved_keyword: | MODE | MONTH_P | MOVE - | NAME + | NAME_P | NAMES | NEXT | NO @@ -8853,18 +8836,18 @@ unreserved_keyword: | SHOW | SIMPLE | STABLE - | STANDALONE + | STANDALONE_P | START | STATEMENT | STATISTICS | STDIN | STDOUT | STORAGE - | STRIP + | STRICT_P + | STRIP_P | SUPERUSER_P | SYSID | SYSTEM_P - | STRICT_P | TABLESPACE | TEMP | TEMPLATE @@ -8883,18 +8866,18 @@ unreserved_keyword: | VACUUM | VALID | VALIDATOR + | VALUE_P | VARYING - | VERSION + | VERSION_P | VIEW - | VALUE | VOLATILE - | WHITESPACE + | WHITESPACE_P | WITH | WITHOUT | WORK | WRITE | YEAR_P - | YES + | YES_P | ZONE ; @@ -8948,8 +8931,8 @@ col_name_keyword: | VALUES | VARCHAR | XMLATTRIBUTES - | XMLELEMENT | XMLCONCAT + | XMLELEMENT | XMLFOREST | XMLPARSE | XMLPI @@ -9492,10 +9475,16 @@ doNegateFloat(Value *v) static Node * makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) { - XmlExpr *x = makeNode(XmlExpr); + XmlExpr *x = makeNode(XmlExpr); + x->op = op; x->name = name; + /* + * named_args is a list of ResTarget; it'll be split apart into separate + * expression and name lists in transformXmlExpr(). + */ x->named_args = named_args; + x->arg_names = NIL; x->args = args; return (Node *) x; } diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index b5e49e955fc..4865d360b3e 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.178 2006/12/21 16:05:14 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.179 2006/12/24 00:29:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -89,7 +89,7 @@ static const ScanKeyword ScanKeywords[] = { {"connection", CONNECTION}, {"constraint", CONSTRAINT}, {"constraints", CONSTRAINTS}, - {"content", CONTENT}, + {"content", CONTENT_P}, {"conversion", CONVERSION_P}, {"convert", CONVERT}, {"copy", COPY}, @@ -124,7 +124,7 @@ static const ScanKeyword ScanKeywords[] = { {"disable", DISABLE_P}, {"distinct", DISTINCT}, {"do", DO}, - {"document", DOCUMENT}, + {"document", DOCUMENT_P}, {"domain", DOMAIN_P}, {"double", DOUBLE_P}, {"drop", DROP}, @@ -220,7 +220,7 @@ static const ScanKeyword ScanKeywords[] = { {"mode", MODE}, {"month", MONTH_P}, {"move", MOVE}, - {"name", NAME}, + {"name", NAME_P}, {"names", NAMES}, {"national", NATIONAL}, {"natural", NATURAL}, @@ -317,7 +317,7 @@ static const ScanKeyword ScanKeywords[] = { {"smallint", SMALLINT}, {"some", SOME}, {"stable", STABLE}, - {"standalone", STANDALONE}, + {"standalone", STANDALONE_P}, {"start", START}, {"statement", STATEMENT}, {"statistics", STATISTICS}, @@ -325,7 +325,7 @@ static const ScanKeyword ScanKeywords[] = { {"stdout", STDOUT}, {"storage", STORAGE}, {"strict", STRICT_P}, - {"strip", STRIP}, + {"strip", STRIP_P}, {"substring", SUBSTRING}, {"superuser", SUPERUSER_P}, {"symmetric", SYMMETRIC}, @@ -362,17 +362,17 @@ static const ScanKeyword ScanKeywords[] = { {"vacuum", VACUUM}, {"valid", VALID}, {"validator", VALIDATOR}, - {"value", VALUE}, + {"value", VALUE_P}, {"values", VALUES}, {"varchar", VARCHAR}, {"varying", VARYING}, {"verbose", VERBOSE}, - {"version", VERSION}, + {"version", VERSION_P}, {"view", VIEW}, {"volatile", VOLATILE}, {"when", WHEN}, {"where", WHERE}, - {"whitespace", WHITESPACE}, + {"whitespace", WHITESPACE_P}, {"with", WITH}, {"without", WITHOUT}, {"work", WORK}, @@ -386,7 +386,7 @@ static const ScanKeyword ScanKeywords[] = { {"xmlroot", XMLROOT}, {"xmlserialize", XMLSERIALIZE}, {"year", YEAR_P}, - {"yes", YES}, + {"yes", YES_P}, {"zone", ZONE}, }; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 996c724d1ce..145caab101a 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.159 2006/11/28 12:54:41 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.160 2006/12/24 00:29:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1094,7 +1094,7 @@ transformLimitClause(ParseState *pstate, Node *clause, qual = transformExpr(pstate, clause); - qual = coerce_to_bigint(pstate, qual, constructName); + qual = coerce_to_specific_type(pstate, qual, INT8OID, constructName); /* * LIMIT can't refer to any vars or aggregates of the current query; we diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 5670ed4fe74..45c8e97be1d 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.148 2006/12/21 16:05:14 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.149 2006/12/24 00:29:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -840,8 +840,8 @@ coerce_to_boolean(ParseState *pstate, Node *node, } /* - * coerce_to_integer() - * Coerce an argument of a construct that requires integer input. + * coerce_to_specific_type() + * Coerce an argument of a construct that requires a specific data type. * Also check that input is not a set. * * Returns the possibly-transformed node tree. @@ -850,103 +850,26 @@ coerce_to_boolean(ParseState *pstate, Node *node, * processing is wanted. */ Node * -coerce_to_integer(ParseState *pstate, Node *node, - const char *constructName) -{ - Oid inputTypeId = exprType(node); - - if (inputTypeId != INT4OID) - { - node = coerce_to_target_type(pstate, node, inputTypeId, - INT4OID, -1, - COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST); - if (node == NULL) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - /* translator: first %s is name of a SQL construct, eg LIMIT */ - errmsg("argument of %s must be type integer, not type %s", - constructName, format_type_be(inputTypeId)))); - } - - if (expression_returns_set(node)) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - /* translator: %s is name of a SQL construct, eg LIMIT */ - errmsg("argument of %s must not return a set", - constructName))); - - return node; -} - -/* - * coerce_to_bigint() - * Coerce an argument of a construct that requires int8 input. - * Also check that input is not a set. - * - * Returns the possibly-transformed node tree. - * - * As with coerce_type, pstate may be NULL if no special unknown-Param - * processing is wanted. - */ -Node * -coerce_to_bigint(ParseState *pstate, Node *node, - const char *constructName) -{ - Oid inputTypeId = exprType(node); - - if (inputTypeId != INT8OID) - { - node = coerce_to_target_type(pstate, node, inputTypeId, - INT8OID, -1, - COERCION_ASSIGNMENT, - COERCE_IMPLICIT_CAST); - if (node == NULL) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - /* translator: first %s is name of a SQL construct, eg LIMIT */ - errmsg("argument of %s must be type bigint, not type %s", - constructName, format_type_be(inputTypeId)))); - } - - if (expression_returns_set(node)) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - /* translator: %s is name of a SQL construct, eg LIMIT */ - errmsg("argument of %s must not return a set", - constructName))); - - return node; -} - -/* - * coerce_to_xml() - * Coerce an argument of a construct that requires xml input. - * Also check that input is not a set. - * - * Returns the possibly-transformed node tree. - * - * As with coerce_type, pstate may be NULL if no special unknown-Param - * processing is wanted. - */ -Node * -coerce_to_xml(ParseState *pstate, Node *node, - const char *constructName) +coerce_to_specific_type(ParseState *pstate, Node *node, + Oid targetTypeId, + const char *constructName) { Oid inputTypeId = exprType(node); - if (inputTypeId != XMLOID) + if (inputTypeId != targetTypeId) { node = coerce_to_target_type(pstate, node, inputTypeId, - XMLOID, -1, + targetTypeId, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST); if (node == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), /* translator: first %s is name of a SQL construct, eg LIMIT */ - errmsg("argument of %s must be type xml, not type %s", - constructName, format_type_be(inputTypeId)))); + errmsg("argument of %s must be type %s, not type %s", + constructName, + format_type_be(targetTypeId), + format_type_be(inputTypeId)))); } if (expression_returns_set(node)) 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; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 906d96e45c6..ef4b9083ac6 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.150 2006/12/21 16:05:14 petere Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.151 2006/12/24 00:29:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1328,6 +1328,15 @@ FigureColnameInternal(Node *node, char **name) case IS_XMLFOREST: *name = "xmlforest"; return 2; + case IS_XMLPARSE: + *name = "xmlparse"; + return 2; + case IS_XMLPI: + *name = "xmlpi"; + return 2; + case IS_XMLROOT: + *name = "xmlroot"; + return 2; } break; default: |