Commit c957c0ba authored by Tom Lane's avatar Tom Lane

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.
parent 64974613
<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.20 2006/06/16 23:29:26 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.21 2006/12/24 00:29:17 tgl Exp $ -->
<appendix id="errcodes-appendix">
<title><productname>PostgreSQL</productname> Error Codes</title>
......@@ -541,6 +541,29 @@
<entry>untranslatable_character</entry>
</row>
<row>
<entry><literal>2200M</literal></entry>
<entry>INVALID XML DOCUMENT</entry>
<entry>invalid_xml_document</entry>
</row>
<row>
<entry><literal>2200N</literal></entry>
<entry>INVALID XML CONTENT</entry>
<entry>invalid_xml_content</entry>
</row>
<row>
<entry><literal>2200S</literal></entry>
<entry>INVALID XML COMMENT</entry>
<entry>invalid_xml_comment</entry>
</row>
<row>
<entry><literal>2200T</literal></entry>
<entry>INVALID XML PROCESSING INSTRUCTION</entry>
<entry>invalid_xml_processing_instruction</entry>
</row>
<row>
<entry spanname="span13"><emphasis role="bold">Class 23 &mdash; Integrity Constraint Violation</></entry>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.269 2006/12/21 16:05:13 petere Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.270 2006/12/24 00:29:17 tgl Exp $ -->
<chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]>
......@@ -909,7 +909,7 @@ su - postgres
<term><option>--with-libxml</option></term>
<listitem>
<para>
Build with libxml, required for SQL/XML support.
Build with libxml (enables SQL/XML support).
</para>
</listitem>
</varlistentry>
......
This diff is collapsed.
......@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.356 2006/12/23 00:43:09 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.357 2006/12/24 00:29:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1093,6 +1093,23 @@ _copyMinMaxExpr(MinMaxExpr *from)
return newnode;
}
/*
* _copyXmlExpr
*/
static XmlExpr *
_copyXmlExpr(XmlExpr *from)
{
XmlExpr *newnode = makeNode(XmlExpr);
COPY_SCALAR_FIELD(op);
COPY_STRING_FIELD(name);
COPY_NODE_FIELD(named_args);
COPY_NODE_FIELD(arg_names);
COPY_NODE_FIELD(args);
return newnode;
}
/*
* _copyNullIfExpr (same as OpExpr)
*/
......@@ -1138,22 +1155,6 @@ _copyBooleanTest(BooleanTest *from)
return newnode;
}
/*
* _copyXmlExpr
*/
static XmlExpr *
_copyXmlExpr(XmlExpr *from)
{
XmlExpr *newnode = makeNode(XmlExpr);
COPY_SCALAR_FIELD(op);
COPY_STRING_FIELD(name);
COPY_NODE_FIELD(named_args);
COPY_NODE_FIELD(args);
return newnode;
}
/*
* _copyCoerceToDomain
*/
......@@ -2977,6 +2978,9 @@ copyObject(void *from)
case T_MinMaxExpr:
retval = _copyMinMaxExpr(from);
break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;
case T_NullIfExpr:
retval = _copyNullIfExpr(from);
break;
......@@ -2986,9 +2990,6 @@ copyObject(void *from)
case T_BooleanTest:
retval = _copyBooleanTest(from);
break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;
case T_CoerceToDomain:
retval = _copyCoerceToDomain(from);
break;
......
......@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.290 2006/12/23 00:43:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.291 2006/12/24 00:29:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -454,6 +454,18 @@ _equalMinMaxExpr(MinMaxExpr *a, MinMaxExpr *b)
return true;
}
static bool
_equalXmlExpr(XmlExpr *a, XmlExpr *b)
{
COMPARE_SCALAR_FIELD(op);
COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(named_args);
COMPARE_NODE_FIELD(arg_names);
COMPARE_NODE_FIELD(args);
return true;
}
static bool
_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
{
......@@ -495,17 +507,6 @@ _equalBooleanTest(BooleanTest *a, BooleanTest *b)
return true;
}
static bool
_equalXmlExpr(XmlExpr *a, XmlExpr *b)
{
COMPARE_SCALAR_FIELD(op);
COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(named_args);
COMPARE_NODE_FIELD(args);
return true;
}
static bool
_equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b)
{
......@@ -1971,6 +1972,9 @@ equal(void *a, void *b)
case T_MinMaxExpr:
retval = _equalMinMaxExpr(a, b);
break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;
case T_NullIfExpr:
retval = _equalNullIfExpr(a, b);
break;
......@@ -1980,9 +1984,6 @@ equal(void *a, void *b)
case T_BooleanTest:
retval = _equalBooleanTest(a, b);
break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;
case T_CoerceToDomain:
retval = _equalCoerceToDomain(a, b);
break;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.288 2006/12/23 00:43:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.289 2006/12/24 00:29:18 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
......@@ -892,6 +892,18 @@ _outMinMaxExpr(StringInfo str, MinMaxExpr *node)
WRITE_NODE_FIELD(args);
}
static void
_outXmlExpr(StringInfo str, XmlExpr *node)
{
WRITE_NODE_TYPE("XMLEXPR");
WRITE_ENUM_FIELD(op, XmlExprOp);
WRITE_STRING_FIELD(name);
WRITE_NODE_FIELD(named_args);
WRITE_NODE_FIELD(arg_names);
WRITE_NODE_FIELD(args);
}
static void
_outNullIfExpr(StringInfo str, NullIfExpr *node)
{
......@@ -922,17 +934,6 @@ _outBooleanTest(StringInfo str, BooleanTest *node)
WRITE_ENUM_FIELD(booltesttype, BoolTestType);
}
static void
_outXmlExpr(StringInfo str, XmlExpr *node)
{
WRITE_NODE_TYPE("XMLEXPR");
WRITE_ENUM_FIELD(op, XmlExprOp);
WRITE_STRING_FIELD(name);
WRITE_NODE_FIELD(named_args);
WRITE_NODE_FIELD(args);
}
static void
_outCoerceToDomain(StringInfo str, CoerceToDomain *node)
{
......@@ -2026,6 +2027,9 @@ _outNode(StringInfo str, void *obj)
case T_MinMaxExpr:
_outMinMaxExpr(str, obj);
break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;
case T_NullIfExpr:
_outNullIfExpr(str, obj);
break;
......@@ -2035,9 +2039,6 @@ _outNode(StringInfo str, void *obj)
case T_BooleanTest:
_outBooleanTest(str, obj);
break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;
case T_CoerceToDomain:
_outCoerceToDomain(str, obj);
break;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.198 2006/12/23 00:43:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.199 2006/12/24 00:29:18 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
......@@ -708,6 +708,23 @@ _readMinMaxExpr(void)
READ_DONE();
}
/*
* _readXmlExpr
*/
static XmlExpr *
_readXmlExpr(void)
{
READ_LOCALS(XmlExpr);
READ_ENUM_FIELD(op, XmlExprOp);
READ_STRING_FIELD(name);
READ_NODE_FIELD(named_args);
READ_NODE_FIELD(arg_names);
READ_NODE_FIELD(args);
READ_DONE();
}
/*
* _readNullIfExpr
*/
......@@ -764,22 +781,6 @@ _readBooleanTest(void)
READ_DONE();
}
/*
* _readXmlExpr
*/
static XmlExpr *
_readXmlExpr(void)
{
READ_LOCALS(XmlExpr);
READ_ENUM_FIELD(op, XmlExprOp);
READ_STRING_FIELD(name);
READ_NODE_FIELD(named_args);
READ_NODE_FIELD(args);
READ_DONE();
}
/*
* _readCoerceToDomain
*/
......@@ -1024,14 +1025,14 @@ parseNodeString(void)
return_value = _readCoalesceExpr();
else if (MATCH("MINMAX", 6))
return_value = _readMinMaxExpr();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("NULLIFEXPR", 10))
return_value = _readNullIfExpr();
else if (MATCH("NULLTEST", 8))
return_value = _readNullTest();
else if (MATCH("BOOLEANTEST", 11))
return_value = _readBooleanTest();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("COERCETODOMAIN", 14))
return_value = _readCoerceToDomain();
else if (MATCH("COERCETODOMAINVALUE", 19))
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.225 2006/12/23 00:43:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.226 2006/12/24 00:29:18 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
......@@ -557,10 +557,10 @@ expression_returns_set_walker(Node *node, void *context)
return false;
if (IsA(node, MinMaxExpr))
return false;
if (IsA(node, NullIfExpr))
return false;
if (IsA(node, XmlExpr))
return false;
if (IsA(node, NullIfExpr))
return false;
return expression_tree_walker(node, expression_returns_set_walker,
context);
......@@ -872,14 +872,14 @@ contain_nonstrict_functions_walker(Node *node, void *context)
return true;
if (IsA(node, MinMaxExpr))
return true;
if (IsA(node, XmlExpr))
return true;
if (IsA(node, NullIfExpr))
return true;
if (IsA(node, NullTest))
return true;
if (IsA(node, BooleanTest))
return true;
if (IsA(node, XmlExpr))
return true;
return expression_tree_walker(node, contain_nonstrict_functions_walker,
context);
}
......@@ -3328,22 +3328,23 @@ expression_tree_walker(Node *node,
return walker(((CoalesceExpr *) node)->args, context);
case T_MinMaxExpr:
return walker(((MinMaxExpr *) node)->args, context);
case T_NullIfExpr:
return walker(((NullIfExpr *) node)->args, context);
case T_NullTest:
return walker(((NullTest *) node)->arg, context);
case T_BooleanTest:
return walker(((BooleanTest *) node)->arg, context);
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
if (walker(xexpr->named_args, context))
return true;
/* we assume walker doesn't care about arg_names */
if (walker(xexpr->args, context))
return true;
}
break;
case T_NullIfExpr:
return walker(((NullIfExpr *) node)->args, context);
case T_NullTest:
return walker(((NullTest *) node)->arg, context);
case T_BooleanTest:
return walker(((BooleanTest *) node)->arg, context);
case T_CoerceToDomain:
return walker(((CoerceToDomain *) node)->arg, context);
case T_TargetEntry:
......@@ -3874,6 +3875,7 @@ expression_tree_mutator(Node *node,
FLATCOPY(newnode, xexpr, XmlExpr);
MUTATE(newnode->named_args, xexpr->named_args, List *);
/* assume mutator does not care about arg_names */
MUTATE(newnode->args, xexpr->args, List *);
return (Node *) newnode;
}
......
This diff is collapsed.
......@@ -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)
{
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))
......
......@@ -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:
......
......@@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text
*
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.237 2006/12/23 00:43:11 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.238 2006/12/24 00:29:19 tgl Exp $
**********************************************************************/
#include "postgres.h"
......@@ -2988,8 +2988,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RowExpr:
case T_CoalesceExpr:
case T_MinMaxExpr:
case T_NullIfExpr:
case T_XmlExpr:
case T_NullIfExpr:
case T_Aggref:
case T_FuncExpr:
/* function-like: name(..) or name[..] */
......@@ -3097,8 +3097,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RowExpr: /* other separators */
case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_XmlExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */
return true;
......@@ -3146,8 +3146,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RowExpr: /* other separators */
case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_XmlExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */
return true;
......@@ -3779,6 +3779,140 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
bool needcomma = false;
ListCell *arg;
ListCell *narg;
Const *con;
switch (xexpr->op)
{
case IS_XMLCONCAT:
appendStringInfoString(buf, "XMLCONCAT(");
break;
case IS_XMLELEMENT:
appendStringInfoString(buf, "XMLELEMENT(");
break;
case IS_XMLFOREST:
appendStringInfoString(buf, "XMLFOREST(");
break;
case IS_XMLPARSE:
appendStringInfoString(buf, "XMLPARSE(");
break;
case IS_XMLPI:
appendStringInfoString(buf, "XMLPI(");
break;
case IS_XMLROOT:
appendStringInfoString(buf, "XMLROOT(");
break;
}
if (xexpr->name)
{
/*
* XXX need to de-escape the name
*/
appendStringInfo(buf, "NAME %s",
quote_identifier(xexpr->name));
needcomma = true;
}
if (xexpr->named_args)
{
if (xexpr->op != IS_XMLFOREST)
{
if (needcomma)
appendStringInfoString(buf, ", ");
appendStringInfoString(buf, "XMLATTRIBUTES(");
needcomma = false;
}
forboth(arg, xexpr->named_args, narg, xexpr->arg_names)
{
Node *e = (Node *) lfirst(arg);
char *argname = strVal(lfirst(narg));
if (needcomma)
appendStringInfoString(buf, ", ");
get_rule_expr((Node *) e, context, true);
/*
* XXX need to de-escape the name
*/
appendStringInfo(buf, " AS %s",
quote_identifier(argname));
needcomma = true;
}
if (xexpr->op != IS_XMLFOREST)
appendStringInfoChar(buf, ')');
}
if (xexpr->args)
{
if (needcomma)
appendStringInfoString(buf, ", ");
switch (xexpr->op)
{
case IS_XMLCONCAT:
case IS_XMLELEMENT:
case IS_XMLFOREST:
case IS_XMLPI:
/* no extra decoration needed */
get_rule_expr((Node *) xexpr->args, context, true);
break;
case IS_XMLPARSE:
Assert(list_length(xexpr->args) == 3);
con = (Const *) lsecond(xexpr->args);
Assert(IsA(con, Const));
Assert(!con->constisnull);
if (DatumGetBool(con->constvalue))
appendStringInfoString(buf, "DOCUMENT ");
else
appendStringInfoString(buf, "CONTENT ");
get_rule_expr((Node *) linitial(xexpr->args),
context, true);
con = (Const *) lthird(xexpr->args);
Assert(IsA(con, Const));
Assert(!con->constisnull);
if (DatumGetBool(con->constvalue))
appendStringInfoString(buf,
" PRESERVE WHITESPACE");
else
appendStringInfoString(buf,
" STRIP WHITESPACE");
break;
case IS_XMLROOT:
Assert(list_length(xexpr->args) == 3);
get_rule_expr((Node *) linitial(xexpr->args),
context, true);
appendStringInfoString(buf, ", VERSION ");
con = (Const *) lsecond(xexpr->args);
if (IsA(con, Const) &&
con->constisnull)
appendStringInfoString(buf, "NO VALUE");
else
get_rule_expr((Node *) con, context, false);
con = (Const *) lthird(xexpr->args);
Assert(IsA(con, Const));
if (con->constisnull)
/* suppress STANDALONE NO VALUE */ ;
else if (DatumGetBool(con->constvalue))
appendStringInfoString(buf,
", STANDALONE YES");
else
appendStringInfoString(buf,
", STANDALONE NO");
break;
}
}
appendStringInfoChar(buf, ')');
}
break;
case T_NullIfExpr:
{
NullIfExpr *nullifexpr = (NullIfExpr *) node;
......@@ -3849,28 +3983,6 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
case T_XmlExpr:
{
XmlExpr *xexpr = (XmlExpr *) node;
switch (xexpr->op)
{
case IS_XMLCONCAT:
appendStringInfo(buf, "XMLCONCAT(");
break;
case IS_XMLELEMENT:
appendStringInfo(buf, "XMLELEMENT(");
break;
case IS_XMLFOREST:
appendStringInfo(buf, "XMLFOREST(");
break;
}
get_rule_expr((Node *) xexpr->named_args, context, true);
get_rule_expr((Node *) xexpr->args, context, true);
appendStringInfoChar(buf, ')');
}
break;
case T_CoerceToDomain:
{
CoerceToDomain *ctest = (CoerceToDomain *) node;
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.2 2006/12/23 04:56:50 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.3 2006/12/24 00:29:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -41,15 +41,6 @@
#ifdef USE_LIBXML
/*
* A couple of useful macros (similar to ones from libxml/parse.c)
*/
#define CMP4( s, c1, c2, c3, c4 ) \
( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
#define CMP5( s, c1, c2, c3, c4, c5 ) \
( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
#define PG_XML_DEFAULT_URI "dummy.xml"
#define XML_ERRBUF_SIZE 200
......@@ -177,31 +168,18 @@ xmlcomment(PG_FUNCTION_ARGS)
Datum
xmlparse(PG_FUNCTION_ARGS)
texttoxml(PG_FUNCTION_ARGS)
{
#ifdef USE_LIBXML
text *data;
bool is_document;
bool preserve_whitespace;
data = PG_GETARG_TEXT_P(0);
text *data = PG_GETARG_TEXT_P(0);
if (PG_NARGS() >= 2)
is_document = PG_GETARG_BOOL(1);
else
is_document = false;
PG_RETURN_XML_P(xmlparse(data, false, true));
}
if (PG_NARGS() >= 3)
preserve_whitespace = PG_GETARG_BOOL(2);
else
/*
* Since the XMLPARSE grammar makes STRIP WHITESPACE the
* default, this argument should really default to false. But
* until we have actually implemented whitespace stripping,
* this would be annoying.
*/
preserve_whitespace = true;
xmltype *
xmlparse(text *data, bool is_document, bool preserve_whitespace)
{
#ifdef USE_LIBXML
if (!preserve_whitespace)
ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
......@@ -213,111 +191,93 @@ xmlparse(PG_FUNCTION_ARGS)
* valies defined by internal DTD are applied'. As for external
* DTDs, we try to support them too, (see SQL/XML:10.16.7.e)
*/
xml_parse(data, XML_PARSE_DTDATTR, is_document); /* assume that ERROR occurred if parsing failed */
xml_parse(data, XML_PARSE_DTDATTR, is_document);
PG_RETURN_XML_P(data);
return (xmltype *) data;
#else
NO_XML_SUPPORT();
return 0;
return NULL;
#endif
}
Datum
xmlpi(PG_FUNCTION_ARGS)
xmltype *
xmlpi(char *target, text *arg)
{
#ifdef USE_LIBXML
char *target = NameStr(*PG_GETARG_NAME(0));
xmltype *result;
StringInfoData buf;
if (strlen(target) >= 3
&& (target[0] == 'x' || target[0] == 'X')
&& (target[1] == 'm' || target[1] == 'M')
&& (target[2] == 'l' || target[2] == 'L'))
{
if (pg_strncasecmp(target, "xml", 3) == 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
errmsg("invalid XML processing instruction"),
errdetail("XML processing instruction target name cannot start with \"xml\".")));
}
initStringInfo(&buf);
appendStringInfo(&buf, "<?");
appendStringInfoString(&buf, map_sql_identifier_to_xml_name(target, false));
if (PG_NARGS() > 1)
appendStringInfo(&buf, "<?%s", target);
if (arg != NULL)
{
text *arg = PG_GETARG_TEXT_P(1);
char *string;
string = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(arg)));
if (strstr(string, "?>"))
string = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(arg)));
if (strstr(string, "?>") != NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
errmsg("invalid XML processing instruction"),
errdetail("XML processing instruction cannot contain \"?>\".")));
appendStringInfoString(&buf, " ");
appendStringInfoChar(&buf, ' ');
appendStringInfoString(&buf, string);
pfree(string);
}
appendStringInfoString(&buf, "?>");
PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
result = stringinfo_to_xmltype(&buf);
pfree(buf.data);
return result;
#else
NO_XML_SUPPORT();
return 0;
return NULL;
#endif
}
Datum
xmlroot(PG_FUNCTION_ARGS)
xmltype *
xmlroot(xmltype *data, text *version, int standalone)
{
#ifdef USE_LIBXML
xmltype *data;
text *version;
int standalone;
xmltype *result;
StringInfoData buf;
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
else
data = PG_GETARG_XML_P(0);
if (PG_ARGISNULL(1))
version = NULL;
else
version = PG_GETARG_TEXT_P(1);
if (PG_ARGISNULL(2))
standalone = 0;
else
{
bool tmp = PG_GETARG_BOOL(2);
standalone = (tmp ? 1 : -1);
}
initStringInfo(&buf);
/*
* FIXME: This is probably supposed to be cleverer if there
* already is an XML preamble.
*/
initStringInfo(&buf);
appendStringInfo(&buf,"<?xml");
if (version) {
if (version)
{
appendStringInfo(&buf, " version=\"");
appendStringInfoText(&buf, version);
appendStringInfo(&buf, "\"");
}
if (standalone)
appendStringInfo(&buf, " standalone=\"%s\"", (standalone == 1 ? "yes" : "no"));
appendStringInfo(&buf, " standalone=\"%s\"",
(standalone == 1 ? "yes" : "no"));
appendStringInfo(&buf, "?>");
appendStringInfoText(&buf, (text *) data);
PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
result = stringinfo_to_xmltype(&buf);
pfree(buf.data);
return result;
#else
NO_XML_SUPPORT();
return 0;
return NULL;
#endif
}
......@@ -456,7 +416,7 @@ xml_parse(text *data, int opts, bool is_document)
/* first, we try to parse the string as XML doc, then, as XML chunk */
ereport(DEBUG3, (errmsg("string to parse: %s", string)));
if (len > 4 && CMP5(string, '<', '?', 'x', 'm', 'l'))
if (len >= 5 && strncmp((char *) string, "<?xml", 5) == 0)
{
/* consider it as DOCUMENT */
doc = xmlCtxtReadMemory(ctxt, (char *) string, len,
......@@ -918,10 +878,8 @@ map_sql_identifier_to_xml_name(char *ident, bool fully_escaped)
appendStringInfo(&buf, "_x003A_");
else if (*p == '_' && *(p+1) == 'x')
appendStringInfo(&buf, "_x005F_");
else if (fully_escaped && p == ident
&& ( *p == 'x' || *p == 'X')
&& ( *(p+1) == 'm' || *(p+1) == 'M')
&& ( *(p+2) == 'l' || *(p+2) == 'L'))
else if (fully_escaped && p == ident &&
pg_strncasecmp(p, "xml", 3) == 0)
{
if (*p == 'x')
appendStringInfo(&buf, "_x0078_");
......@@ -932,9 +890,10 @@ map_sql_identifier_to_xml_name(char *ident, bool fully_escaped)
{
pg_wchar u = sqlchar_to_unicode(p);
if (!is_valid_xml_namechar(u)
|| (p == ident && !is_valid_xml_namefirst(u)))
appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
if ((p == ident)
? !is_valid_xml_namefirst(u)
: !is_valid_xml_namechar(u))
appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
else
appendBinaryStringInfo(&buf, p, pg_mblen(p));
}
......
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.365 2006/12/23 00:43:12 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.366 2006/12/24 00:29:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200612221
#define CATALOG_VERSION_NO 200612231
#endif
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.431 2006/12/21 16:05:15 petere Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.432 2006/12/24 00:29:19 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -3983,17 +3983,9 @@ DATA(insert OID = 2894 ( xml_out PGNSP PGUID 12 f f t f i 1 2275 "142" _nul
DESCR("I/O");
DATA(insert OID = 2895 ( xmlcomment PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlcomment - _null_ ));
DESCR("generate an XML comment");
DATA(insert OID = 2896 ( xmlparse PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlparse - _null_ ));
DATA(insert OID = 2896 ( xml PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ texttoxml - _null_ ));
DESCR("perform a non-validating parse of a character string to produce an XML value");
DATA(insert OID = 2897 ( xmlparse PGNSP PGUID 12 f f t f i 3 142 "25 16 16" _null_ _null_ _null_ xmlparse - _null_ ));
DESCR("perform a non-validating parse of a character string to produce an XML value");
DATA(insert OID = 2898 ( xmlpi PGNSP PGUID 12 f f t f i 1 142 "19" _null_ _null_ _null_ xmlpi - _null_ ));
DESCR("generate an XML processing instruction");
DATA(insert OID = 2899 ( xmlpi PGNSP PGUID 12 f f t f i 2 142 "19 25" _null_ _null_ _null_ xmlpi - _null_ ));
DESCR("generate an XML processing instruction");
DATA(insert OID = 2900 ( xmlroot PGNSP PGUID 12 f f f f i 3 142 "142 25 16" _null_ _null_ _null_ xmlroot - _null_ ));
DESCR("create an XML value by modifying the properties of the XML root information item of another XML value");
DATA(insert OID = 2901 ( xmlvalidate PGNSP PGUID 12 f f t f i 2 16 "142 25" _null_ _null_ _null_ xmlvalidate - _null_ ));
DATA(insert OID = 2897 ( xmlvalidate PGNSP PGUID 12 f f t f i 2 16 "142 25" _null_ _null_ _null_ xmlvalidate - _null_ ));
DESCR("validate an XML value");
/*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.163 2006/12/21 16:05:16 petere Exp $
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.164 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -710,6 +710,18 @@ typedef struct MinMaxExprState
FmgrInfo cfunc; /* lookup info for comparison func */
} MinMaxExprState;
/* ----------------
* XmlExprState node
* ----------------
*/
typedef struct XmlExprState
{
ExprState xprstate;
List *named_args; /* ExprStates for named arguments */
FmgrInfo *named_outfuncs; /* array of output fns for named arguments */
List *args; /* ExprStates for other arguments */
} XmlExprState;
/* ----------------
* NullTestState node
* ----------------
......@@ -723,22 +735,6 @@ typedef struct NullTestState
TupleDesc argdesc; /* tupdesc for most recent input */
} NullTestState;
/* ----------------
* XmlExprState node
* ----------------
*/
typedef struct XmlExprState
{
ExprState xprstate;
XmlExprOp op;
char *name;
List *named_args;
List *args;
Oid *named_args_tcache;
char **named_args_ncache;
Oid arg_typeout;
} XmlExprState;
/* ----------------
* CoerceToDomainState node
* ----------------
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.189 2006/12/21 16:05:16 petere Exp $
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.190 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -130,6 +130,7 @@ typedef enum NodeTag
T_RowCompareExpr,
T_CoalesceExpr,
T_MinMaxExpr,
T_XmlExpr,
T_NullIfExpr,
T_NullTest,
T_BooleanTest,
......@@ -140,7 +141,6 @@ typedef enum NodeTag
T_RangeTblRef,
T_JoinExpr,
T_FromExpr,
T_XmlExpr,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
......@@ -166,10 +166,10 @@ typedef enum NodeTag
T_RowCompareExprState,
T_CoalesceExprState,
T_MinMaxExprState,
T_XmlExprState,
T_NullTestState,
T_CoerceToDomainState,
T_DomainConstraintState,
T_XmlExprState,
/*
* TAGS FOR PLANNER NODES (relation.h)
......
......@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.120 2006/12/23 00:43:13 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.121 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -711,6 +711,33 @@ typedef struct MinMaxExpr
List *args; /* the arguments */
} MinMaxExpr;
/*
* XmlExpr - various SQL/XML functions requiring special grammar productions
*
* 'name' carries the "NAME foo" argument (already XML-escaped).
* 'named_args' and 'arg_names' represent an xml_attribute list.
* 'args' carries all other arguments.
*/
typedef enum XmlExprOp
{
IS_XMLCONCAT, /* XMLCONCAT(args) */
IS_XMLELEMENT, /* XMLELEMENT(name, xml_attributes, args) */
IS_XMLFOREST, /* XMLFOREST(xml_attributes) */
IS_XMLPARSE, /* XMLPARSE(text, is_doc, preserve_ws) */
IS_XMLPI, /* XMLPI(name [, args]) */
IS_XMLROOT /* XMLROOT(xml, version, standalone) */
} XmlExprOp;
typedef struct XmlExpr
{
Expr xpr;
XmlExprOp op; /* xml function ID */
char *name; /* name in xml(NAME foo ...) syntaxes */
List *named_args; /* non-XML expressions for xml_attributes */
List *arg_names; /* parallel list of Value strings */
List *args; /* list of expressions */
} XmlExpr;
/*
* NullIfExpr - a NULLIF expression
*
......@@ -765,26 +792,6 @@ typedef struct BooleanTest
BoolTestType booltesttype; /* test type */
} BooleanTest;
/*
* XmlExpr - holder for SQL/XML functions XMLCONCAT,
* XMLELEMENT, XMLFOREST
*/
typedef enum XmlExprOp
{
IS_XMLCONCAT,
IS_XMLELEMENT,
IS_XMLFOREST,
} XmlExprOp;
typedef struct XmlExpr
{
Expr xpr;
XmlExprOp op; /* xml expression type */
char *name; /* element name */
List *named_args;
List *args;
} XmlExpr;
/*
* CoerceToDomain
*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.67 2006/12/21 16:05:16 petere Exp $
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.68 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -55,12 +55,9 @@ extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod,
extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
const char *constructName);
extern Node *coerce_to_integer(ParseState *pstate, Node *node,
const char *constructName);
extern Node *coerce_to_bigint(ParseState *pstate, Node *node,
const char *constructName);
extern Node *coerce_to_xml(ParseState *pstate, Node *node,
const char *constructName);
extern Node *coerce_to_specific_type(ParseState *pstate, Node *node,
Oid targetTypeId,
const char *constructName);
extern Oid select_common_type(List *typeids, const char *context);
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.2 2006/12/23 04:56:50 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/xml.h,v 1.3 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -27,11 +27,13 @@ typedef struct varlena xmltype;
extern Datum xml_in(PG_FUNCTION_ARGS);
extern Datum xml_out(PG_FUNCTION_ARGS);
extern Datum xmlcomment(PG_FUNCTION_ARGS);
extern Datum xmlparse(PG_FUNCTION_ARGS);
extern Datum xmlpi(PG_FUNCTION_ARGS);
extern Datum xmlroot(PG_FUNCTION_ARGS);
extern Datum texttoxml(PG_FUNCTION_ARGS);
extern Datum xmlvalidate(PG_FUNCTION_ARGS);
extern xmltype *xmlparse(text *data, bool is_doc, bool preserve_whitespace);
extern xmltype *xmlpi(char *target, text *arg);
extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
#endif /* XML_H */
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.180 2006/10/04 00:30:13 momjian Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.181 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -4493,6 +4493,18 @@ exec_simple_check_node(Node *node)
return TRUE;
}
case T_XmlExpr:
{
XmlExpr *expr = (XmlExpr *) node;
if (!exec_simple_check_node((Node *) expr->named_args))
return FALSE;
if (!exec_simple_check_node((Node *) expr->args))
return FALSE;
return TRUE;
}
case T_NullIfExpr:
{
NullIfExpr *expr = (NullIfExpr *) node;
......
......@@ -9,7 +9,7 @@
*
* Copyright (c) 2003-2006, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.9 2006/06/16 23:29:27 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plerrcodes.h,v 1.10 2006/12/24 00:29:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -243,6 +243,22 @@
"untranslatable_character", ERRCODE_UNTRANSLATABLE_CHARACTER
},
{
"invalid_xml_document", ERRCODE_INVALID_XML_DOCUMENT
},
{
"invalid_xml_content", ERRCODE_INVALID_XML_CONTENT
},
{
"invalid_xml_comment", ERRCODE_INVALID_XML_COMMENT
},
{
"invalid_xml_processing_instruction", ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION
},
{
"integrity_constraint_violation", ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION
},
......
......@@ -74,7 +74,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND
p1.prosrc = p2.prosrc AND p1.prosrc NOT IN ('xmlparse', 'xmlpi') AND
p1.prosrc = p2.prosrc AND
p1.prolang = 12 AND p2.prolang = 12 AND
(p1.proisagg = false OR p2.proisagg = false) AND
(p1.prolang != p2.prolang OR
......
......@@ -77,7 +77,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND
p1.prosrc = p2.prosrc AND p1.prosrc NOT IN ('xmlparse', 'xmlpi') AND
p1.prosrc = p2.prosrc AND
p1.prolang = 12 AND p2.prolang = 12 AND
(p1.proisagg = false OR p2.proisagg = false) AND
(p1.prolang != p2.prolang OR
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment