mirror of
https://github.com/postgres/postgres.git
synced 2025-07-17 06:41:09 +03:00
Code review for XML patch. Instill a bit of sanity in the location of
the XmlExpr code in various lists, use a representation that has some hope of reverse-listing correctly (though it's still a de-escaping function shy of correctness), generally try to make it look more like Postgres coding conventions.
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
@ -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},
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
coerce_to_specific_type(ParseState *pstate, Node *node,
|
||||
Oid targetTypeId,
|
||||
const char *constructName)
|
||||
{
|
||||
Oid inputTypeId = exprType(node);
|
||||
|
||||
if (inputTypeId != INT4OID)
|
||||
if (inputTypeId != targetTypeId)
|
||||
{
|
||||
node = coerce_to_target_type(pstate, node, inputTypeId,
|
||||
INT4OID, -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 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)
|
||||
{
|
||||
Oid inputTypeId = exprType(node);
|
||||
|
||||
if (inputTypeId != XMLOID)
|
||||
{
|
||||
node = coerce_to_target_type(pstate, node, inputTypeId,
|
||||
XMLOID, -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))
|
||||
|
@ -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.
|
||||
@ -1375,6 +1375,107 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
|
||||
return (Node *) newm;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user