mirror of
https://github.com/postgres/postgres.git
synced 2025-07-17 06:41:09 +03:00
Initial SQL/XML support: xml data type and initial set of functions.
This commit is contained in:
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.568 2006/11/05 22:42:09 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.569 2006/12/21 16:05:14 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -106,6 +106,7 @@ static void insertSelectOptions(SelectStmt *stmt,
|
||||
static Node *makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg);
|
||||
static Node *doNegate(Node *n, int location);
|
||||
static void doNegateFloat(Value *v);
|
||||
static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args);
|
||||
|
||||
%}
|
||||
|
||||
@ -345,6 +346,11 @@ static void doNegateFloat(Value *v);
|
||||
%type <str> OptTableSpace OptConsTableSpace OptTableSpaceOwner
|
||||
%type <list> opt_check_option
|
||||
|
||||
%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
|
||||
|
||||
|
||||
/*
|
||||
* If you make any token changes, update the keyword table in
|
||||
@ -365,13 +371,13 @@ static void doNegateFloat(Value *v);
|
||||
CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
|
||||
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
|
||||
COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS
|
||||
CONVERSION_P CONVERT COPY CREATE CREATEDB
|
||||
CONTENT 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 DOMAIN_P DOUBLE_P DROP
|
||||
DESC DISABLE_P DISTINCT DO DOCUMENT DOMAIN_P DOUBLE_P DROP
|
||||
|
||||
EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING
|
||||
EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
|
||||
@ -398,7 +404,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
|
||||
|
||||
NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
|
||||
NAME NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
|
||||
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
|
||||
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
|
||||
|
||||
@ -417,8 +423,8 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
|
||||
SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
|
||||
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
|
||||
STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
|
||||
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE START STATEMENT
|
||||
STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP SUBSTRING SUPERUSER_P SYMMETRIC
|
||||
SYSID SYSTEM_P
|
||||
|
||||
TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
|
||||
@ -428,12 +434,15 @@ static void doNegateFloat(Value *v);
|
||||
UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
|
||||
UPDATE USER USING
|
||||
|
||||
VACUUM VALID VALIDATOR VALUES VARCHAR VARYING
|
||||
VERBOSE VIEW VOLATILE
|
||||
VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING
|
||||
VERBOSE VERSION VIEW VOLATILE
|
||||
|
||||
WHEN WHERE WITH WITHOUT WORK WRITE
|
||||
WHEN WHERE WHITESPACE WITH WITHOUT WORK WRITE
|
||||
|
||||
YEAR_P
|
||||
XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
|
||||
XMLPI XMLROOT XMLSERIALIZE
|
||||
|
||||
YEAR_P YES
|
||||
|
||||
ZONE
|
||||
|
||||
@ -484,6 +493,7 @@ static void doNegateFloat(Value *v);
|
||||
* left-associativity among the JOIN rules themselves.
|
||||
*/
|
||||
%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
|
||||
%right PRESERVE STRIP
|
||||
%%
|
||||
|
||||
/*
|
||||
@ -7868,6 +7878,146 @@ func_expr: func_name '(' ')'
|
||||
v->op = IS_LEAST;
|
||||
$$ = (Node *)v;
|
||||
}
|
||||
| XMLCONCAT '(' expr_list ')'
|
||||
{
|
||||
$$ = makeXmlExpr(IS_XMLCONCAT, NULL, NULL, $3);
|
||||
}
|
||||
| XMLELEMENT '(' NAME ColLabel ')'
|
||||
{
|
||||
$$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, NULL);
|
||||
}
|
||||
| XMLELEMENT '(' NAME ColLabel ',' xml_attributes ')'
|
||||
{
|
||||
$$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, NULL);
|
||||
}
|
||||
| XMLELEMENT '(' NAME ColLabel ',' expr_list ')'
|
||||
{
|
||||
$$ = makeXmlExpr(IS_XMLELEMENT, $4, NULL, $6);
|
||||
}
|
||||
| XMLELEMENT '(' NAME ColLabel ',' xml_attributes ',' expr_list ')'
|
||||
{
|
||||
$$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8);
|
||||
}
|
||||
| XMLFOREST '(' xml_attribute_list ')'
|
||||
{
|
||||
$$ = makeXmlExpr(IS_XMLFOREST, NULL, $3, NULL);
|
||||
}
|
||||
| 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;
|
||||
}
|
||||
| XMLPI '(' NAME 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;
|
||||
}
|
||||
| XMLPI '(' NAME 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;
|
||||
}
|
||||
| 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;
|
||||
}
|
||||
| XMLSERIALIZE '(' document_or_content a_expr AS Typename ')'
|
||||
{
|
||||
/*
|
||||
* FIXME: This should be made distinguishable from
|
||||
* CAST (for reverse compilation at least).
|
||||
*/
|
||||
$$ = makeTypeCast($4, $6);
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
* SQL/XML support
|
||||
*/
|
||||
xml_root_version: VERSION a_expr { $$ = $2; }
|
||||
| VERSION NO VALUE { $$ = NULL; }
|
||||
;
|
||||
|
||||
opt_xml_root_standalone: ',' STANDALONE YES { $$ = 1; }
|
||||
| ',' STANDALONE NO { $$ = -1; }
|
||||
| ',' STANDALONE NO VALUE { $$ = 0; }
|
||||
| /*EMPTY*/ { $$ = 0; }
|
||||
;
|
||||
|
||||
xml_attributes: XMLATTRIBUTES '(' xml_attribute_list ')' { $$ = $3; }
|
||||
;
|
||||
|
||||
xml_attribute_list: xml_attribute_el { $$ = list_make1($1); }
|
||||
| xml_attribute_list ',' xml_attribute_el { $$ = lappend($1, $3); }
|
||||
;
|
||||
|
||||
xml_attribute_el: a_expr AS ColLabel
|
||||
{
|
||||
$$ = makeNode(ResTarget);
|
||||
$$->name = $3;
|
||||
$$->indirection = NULL;
|
||||
$$->val = (Node *) $1;
|
||||
|
||||
}
|
||||
| a_expr
|
||||
{
|
||||
$$ = makeNode(ResTarget);
|
||||
$$->name = NULL;
|
||||
$$->indirection = NULL;
|
||||
$$->val = (Node *) $1;
|
||||
}
|
||||
;
|
||||
|
||||
document_or_content: DOCUMENT { $$ = DOCUMENT; }
|
||||
| CONTENT { $$ = CONTENT; }
|
||||
;
|
||||
|
||||
xml_whitespace_option: PRESERVE WHITESPACE { $$ = PRESERVE; }
|
||||
| STRIP WHITESPACE { $$ = STRIP; }
|
||||
| /*EMPTY*/ { $$ = STRIP; }
|
||||
;
|
||||
|
||||
/*
|
||||
@ -8562,6 +8712,7 @@ unreserved_keyword:
|
||||
| CONCURRENTLY
|
||||
| CONNECTION
|
||||
| CONSTRAINTS
|
||||
| CONTENT
|
||||
| CONVERSION_P
|
||||
| COPY
|
||||
| CREATEDB
|
||||
@ -8581,6 +8732,7 @@ unreserved_keyword:
|
||||
| DELIMITER
|
||||
| DELIMITERS
|
||||
| DISABLE_P
|
||||
| DOCUMENT
|
||||
| DOMAIN_P
|
||||
| DOUBLE_P
|
||||
| DROP
|
||||
@ -8640,6 +8792,7 @@ unreserved_keyword:
|
||||
| MODE
|
||||
| MONTH_P
|
||||
| MOVE
|
||||
| NAME
|
||||
| NAMES
|
||||
| NEXT
|
||||
| NO
|
||||
@ -8700,12 +8853,14 @@ unreserved_keyword:
|
||||
| SHOW
|
||||
| SIMPLE
|
||||
| STABLE
|
||||
| STANDALONE
|
||||
| START
|
||||
| STATEMENT
|
||||
| STATISTICS
|
||||
| STDIN
|
||||
| STDOUT
|
||||
| STORAGE
|
||||
| STRIP
|
||||
| SUPERUSER_P
|
||||
| SYSID
|
||||
| SYSTEM_P
|
||||
@ -8729,13 +8884,17 @@ unreserved_keyword:
|
||||
| VALID
|
||||
| VALIDATOR
|
||||
| VARYING
|
||||
| VERSION
|
||||
| VIEW
|
||||
| VALUE
|
||||
| VOLATILE
|
||||
| WHITESPACE
|
||||
| WITH
|
||||
| WITHOUT
|
||||
| WORK
|
||||
| WRITE
|
||||
| YEAR_P
|
||||
| YES
|
||||
| ZONE
|
||||
;
|
||||
|
||||
@ -8788,6 +8947,14 @@ col_name_keyword:
|
||||
| TRIM
|
||||
| VALUES
|
||||
| VARCHAR
|
||||
| XMLATTRIBUTES
|
||||
| XMLELEMENT
|
||||
| XMLCONCAT
|
||||
| XMLFOREST
|
||||
| XMLPARSE
|
||||
| XMLPI
|
||||
| XMLROOT
|
||||
| XMLSERIALIZE
|
||||
;
|
||||
|
||||
/* Function identifier --- keywords that can be function names.
|
||||
@ -9322,6 +9489,17 @@ doNegateFloat(Value *v)
|
||||
}
|
||||
}
|
||||
|
||||
static Node *
|
||||
makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
|
||||
{
|
||||
XmlExpr *x = makeNode(XmlExpr);
|
||||
x->op = op;
|
||||
x->name = name;
|
||||
x->named_args = named_args;
|
||||
x->args = args;
|
||||
return (Node *) x;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must undefine base_yylex before including scan.c, since we want it
|
||||
* to create the function base_yylex not filtered_base_yylex.
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.177 2006/10/07 21:51:02 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.178 2006/12/21 16:05:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -89,6 +89,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"connection", CONNECTION},
|
||||
{"constraint", CONSTRAINT},
|
||||
{"constraints", CONSTRAINTS},
|
||||
{"content", CONTENT},
|
||||
{"conversion", CONVERSION_P},
|
||||
{"convert", CONVERT},
|
||||
{"copy", COPY},
|
||||
@ -123,6 +124,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"disable", DISABLE_P},
|
||||
{"distinct", DISTINCT},
|
||||
{"do", DO},
|
||||
{"document", DOCUMENT},
|
||||
{"domain", DOMAIN_P},
|
||||
{"double", DOUBLE_P},
|
||||
{"drop", DROP},
|
||||
@ -218,6 +220,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"mode", MODE},
|
||||
{"month", MONTH_P},
|
||||
{"move", MOVE},
|
||||
{"name", NAME},
|
||||
{"names", NAMES},
|
||||
{"national", NATIONAL},
|
||||
{"natural", NATURAL},
|
||||
@ -314,6 +317,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"smallint", SMALLINT},
|
||||
{"some", SOME},
|
||||
{"stable", STABLE},
|
||||
{"standalone", STANDALONE},
|
||||
{"start", START},
|
||||
{"statement", STATEMENT},
|
||||
{"statistics", STATISTICS},
|
||||
@ -321,6 +325,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"stdout", STDOUT},
|
||||
{"storage", STORAGE},
|
||||
{"strict", STRICT_P},
|
||||
{"strip", STRIP},
|
||||
{"substring", SUBSTRING},
|
||||
{"superuser", SUPERUSER_P},
|
||||
{"symmetric", SYMMETRIC},
|
||||
@ -357,19 +362,31 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"vacuum", VACUUM},
|
||||
{"valid", VALID},
|
||||
{"validator", VALIDATOR},
|
||||
{"value", VALUE},
|
||||
{"values", VALUES},
|
||||
{"varchar", VARCHAR},
|
||||
{"varying", VARYING},
|
||||
{"verbose", VERBOSE},
|
||||
{"version", VERSION},
|
||||
{"view", VIEW},
|
||||
{"volatile", VOLATILE},
|
||||
{"when", WHEN},
|
||||
{"where", WHERE},
|
||||
{"whitespace", WHITESPACE},
|
||||
{"with", WITH},
|
||||
{"without", WITHOUT},
|
||||
{"work", WORK},
|
||||
{"write", WRITE},
|
||||
{"xmlattributes", XMLATTRIBUTES},
|
||||
{"xmlconcat", XMLCONCAT},
|
||||
{"xmlelement", XMLELEMENT},
|
||||
{"xmlforest", XMLFOREST},
|
||||
{"xmlparse", XMLPARSE},
|
||||
{"xmlpi", XMLPI},
|
||||
{"xmlroot", XMLROOT},
|
||||
{"xmlserialize", XMLSERIALIZE},
|
||||
{"year", YEAR_P},
|
||||
{"yes", YES},
|
||||
{"zone", ZONE},
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.147 2006/12/10 22:13:26 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.148 2006/12/21 16:05:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -919,6 +919,46 @@ coerce_to_bigint(ParseState *pstate, Node *node,
|
||||
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))));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* select_common_type()
|
||||
* Determine the common supertype of a list of input expression types.
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.199 2006/12/10 22:13:26 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.200 2006/12/21 16:05:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -33,6 +33,7 @@
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/xml.h"
|
||||
|
||||
|
||||
bool Transform_null_equals = false;
|
||||
@ -55,6 +56,7 @@ static Node *transformArrayExpr(ParseState *pstate, ArrayExpr *a);
|
||||
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 *transformBooleanTest(ParseState *pstate, BooleanTest *b);
|
||||
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
|
||||
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
|
||||
@ -232,6 +234,10 @@ 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.
|
||||
@ -1409,6 +1415,56 @@ 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.*".
|
||||
*
|
||||
@ -1668,6 +1724,9 @@ 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.149 2006/10/04 00:29:56 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.150 2006/12/21 16:05:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1315,6 +1315,21 @@ FigureColnameInternal(Node *node, char **name)
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case T_XmlExpr:
|
||||
/* make SQL/XML functions act like a regular function */
|
||||
switch (((XmlExpr*) node)->op)
|
||||
{
|
||||
case IS_XMLCONCAT:
|
||||
*name = "xmlconcat";
|
||||
return 2;
|
||||
case IS_XMLELEMENT:
|
||||
*name = "xmlelement";
|
||||
return 2;
|
||||
case IS_XMLFOREST:
|
||||
*name = "xmlforest";
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user