1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-01 01:04:50 +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:
Tom Lane 2006-12-24 00:29:20 +00:00
parent 64974613c9
commit c957c0bac7
27 changed files with 883 additions and 686 deletions

View File

@ -1,4 +1,4 @@
<!-- $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"> <appendix id="errcodes-appendix">
<title><productname>PostgreSQL</productname> Error Codes</title> <title><productname>PostgreSQL</productname> Error Codes</title>
@ -541,6 +541,29 @@
<entry>untranslatable_character</entry> <entry>untranslatable_character</entry>
</row> </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> <row>
<entry spanname="span13"><emphasis role="bold">Class 23 &mdash; Integrity Constraint Violation</></entry> <entry spanname="span13"><emphasis role="bold">Class 23 &mdash; Integrity Constraint Violation</></entry>

View File

@ -1,4 +1,4 @@
<!-- $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"> <chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]> <title><![%standalone-include[<productname>PostgreSQL</>]]>
@ -909,7 +909,7 @@ su - postgres
<term><option>--with-libxml</option></term> <term><option>--with-libxml</option></term>
<listitem> <listitem>
<para> <para>
Build with libxml, required for SQL/XML support. Build with libxml (enables SQL/XML support).
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.201 2006/12/23 00:43:09 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.202 2006/12/24 00:29:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -117,11 +117,11 @@ static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr, static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr, static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(NullTestState *nstate, static Datum ExecEvalNullTest(NullTestState *nstate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
@ -2638,6 +2638,237 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
return result; return result;
} }
/* ----------------------------------------------------------------
* ExecEvalXml
* ----------------------------------------------------------------
*/
static Datum
ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
XmlExpr *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
text *result;
StringInfoData buf;
Datum value;
bool isnull;
char *str;
ListCell *arg;
ListCell *narg;
bool found_arg;
int i;
if (isDone)
*isDone = ExprSingleResult;
*isNull = true; /* until we get a result */
switch (xexpr->op)
{
case IS_XMLCONCAT:
initStringInfo(&buf);
foreach(arg, xmlExpr->args)
{
ExprState *e = (ExprState *) lfirst(arg);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (!isnull)
{
/* we know the value is XML type */
str = DatumGetCString(DirectFunctionCall1(xml_out,
value));
appendStringInfoString(&buf, str);
pfree(str);
*isNull = false;
}
}
break;
case IS_XMLELEMENT:
initStringInfo(&buf);
*isNull = false;
appendStringInfo(&buf, "<%s", xexpr->name);
i = 0;
forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
{
ExprState *e = (ExprState *) lfirst(arg);
char *argname = strVal(lfirst(narg));
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (!isnull)
{
str = OutputFunctionCall(&xmlExpr->named_outfuncs[i],
value);
appendStringInfo(&buf, " %s=\"%s\"", argname, str);
pfree(str);
}
i++;
}
found_arg = false;
foreach(arg, xmlExpr->args)
{
ExprState *e = (ExprState *) lfirst(arg);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (!isnull)
{
if (!found_arg)
{
appendStringInfoChar(&buf, '>');
found_arg = true;
}
/* we know the value is XML type */
str = DatumGetCString(DirectFunctionCall1(xml_out,
value));
appendStringInfoString(&buf, str);
pfree(str);
}
}
if (!found_arg)
appendStringInfo(&buf, "/>");
else
appendStringInfo(&buf, "</%s>", xexpr->name);
break;
case IS_XMLFOREST:
initStringInfo(&buf);
i = 0;
forboth(arg, xmlExpr->named_args, narg, xexpr->arg_names)
{
ExprState *e = (ExprState *) lfirst(arg);
char *argname = strVal(lfirst(narg));
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (!isnull)
{
str = OutputFunctionCall(&xmlExpr->named_outfuncs[i],
value);
appendStringInfo(&buf, "<%s>%s</%s>",
argname, str, argname);
pfree(str);
*isNull = false;
}
i++;
}
break;
/* The remaining cases don't need to set up buf */
case IS_XMLPARSE:
{
ExprState *e;
text *data;
bool is_document;
bool preserve_whitespace;
/* arguments are known to be text, bool, bool */
Assert(list_length(xmlExpr->args) == 3);
e = (ExprState *) linitial(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull)
return (Datum) 0;
data = DatumGetTextP(value);
e = (ExprState *) lsecond(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull) /* probably can't happen */
return (Datum) 0;
is_document = DatumGetBool(value);
e = (ExprState *) lthird(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull) /* probably can't happen */
return (Datum) 0;
preserve_whitespace = DatumGetBool(value);
*isNull = false;
return PointerGetDatum(xmlparse(data,
is_document,
preserve_whitespace));
}
break;
case IS_XMLPI:
{
ExprState *e;
text *arg;
/* optional argument is known to be text */
Assert(list_length(xmlExpr->args) <= 1);
if (xmlExpr->args)
{
e = (ExprState *) linitial(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull)
return (Datum) 0;
arg = DatumGetTextP(value);
}
else
arg = NULL;
*isNull = false;
return PointerGetDatum(xmlpi(xexpr->name, arg));
}
break;
case IS_XMLROOT:
{
ExprState *e;
xmltype *data;
text *version;
int standalone;
/* arguments are known to be xml, text, bool */
Assert(list_length(xmlExpr->args) == 3);
e = (ExprState *) linitial(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull)
return (Datum) 0;
data = DatumGetXmlP(value);
e = (ExprState *) lsecond(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull)
version = NULL;
else
version = DatumGetTextP(value);
e = (ExprState *) lthird(xmlExpr->args);
value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (isnull)
standalone = 0;
else
standalone = (DatumGetBool(value) ? 1 : -1);
*isNull = false;
return PointerGetDatum(xmlroot(data,
version,
standalone));
}
break;
}
if (*isNull)
result = NULL;
else
{
int len = buf.len + VARHDRSZ;
result = palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), buf.data, buf.len);
}
pfree(buf.data);
return PointerGetDatum(result);
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecEvalNullIf * ExecEvalNullIf
* *
@ -2881,120 +3112,6 @@ ExecEvalBooleanTest(GenericExprState *bstate,
} }
} }
/* ----------------------------------------------------------------
* ExecEvalXml
* ----------------------------------------------------------------
*/
static Datum
ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
StringInfoData buf;
bool isnull;
ListCell *arg;
text *result = NULL;
int len;
initStringInfo(&buf);
*isNull = false;
if (isDone)
*isDone = ExprSingleResult;
switch (xmlExpr->op)
{
case IS_XMLCONCAT:
*isNull = true;
foreach(arg, xmlExpr->args)
{
ExprState *e = (ExprState *) lfirst(arg);
Datum value = ExecEvalExpr(e, econtext, &isnull, NULL);
if (!isnull)
{
appendStringInfoString(&buf, DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeout, value)));
*isNull = false;
}
}
break;
case IS_XMLELEMENT:
{
int state = 0, i = 0;
appendStringInfo(&buf, "<%s", xmlExpr->name);
foreach(arg, xmlExpr->named_args)
{
GenericExprState *gstate = (GenericExprState *) lfirst(arg);
Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
if (!isnull)
{
char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->named_args_tcache[i], value));
appendStringInfo(&buf, " %s=\"%s\"", xmlExpr->named_args_ncache[i], outstr);
pfree(outstr);
}
i++;
}
if (xmlExpr->args)
{
ExprState *expr = linitial(xmlExpr->args);
Datum value = ExecEvalExpr(expr, econtext, &isnull, NULL);
if (!isnull)
{
char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->arg_typeout, value));
if (state == 0)
{
appendStringInfoChar(&buf, '>');
state = 1;
}
appendStringInfo(&buf, "%s", outstr);
pfree(outstr);
}
}
if (state == 0)
appendStringInfo(&buf, "/>");
else if (state == 1)
appendStringInfo(&buf, "</%s>", xmlExpr->name);
}
break;
case IS_XMLFOREST:
{
/* only if all argumets are null returns null */
int i = 0;
*isNull = true;
foreach(arg, xmlExpr->named_args)
{
GenericExprState *gstate = (GenericExprState *) lfirst(arg);
Datum value = ExecEvalExpr(gstate->arg, econtext, &isnull, NULL);
if (!isnull)
{
char *outstr = DatumGetCString(OidFunctionCall1(xmlExpr->named_args_tcache[i], value));
appendStringInfo(&buf, "<%s>%s</%s>", xmlExpr->named_args_ncache[i], outstr, xmlExpr->named_args_ncache[i]);
pfree(outstr);
*isNull = false;
}
i += 1;
}
}
break;
default:
break;
}
len = buf.len + VARHDRSZ;
result = palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), buf.data, buf.len);
pfree(buf.data);
PG_RETURN_TEXT_P(result);
}
/* /*
* ExecEvalCoerceToDomain * ExecEvalCoerceToDomain
* *
@ -3794,59 +3911,45 @@ ExecInitExpr(Expr *node, PlanState *parent)
break; break;
case T_XmlExpr: case T_XmlExpr:
{ {
List *outlist;
ListCell *arg;
XmlExpr *xexpr = (XmlExpr *) node; XmlExpr *xexpr = (XmlExpr *) node;
XmlExprState *xstate = makeNode(XmlExprState); XmlExprState *xstate = makeNode(XmlExprState);
int i = 0; List *outlist;
Oid typeout; ListCell *arg;
int i;
xstate->name = xexpr->name;
xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml; xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml;
xstate->op = xexpr->op; xstate->named_outfuncs = (FmgrInfo *)
palloc0(list_length(xexpr->named_args) * sizeof(FmgrInfo));
outlist = NIL; outlist = NIL;
if (xexpr->named_args) i = 0;
foreach(arg, xexpr->named_args)
{ {
xstate->named_args_tcache = (Oid *) palloc(list_length(xexpr->named_args) * sizeof(int)); Expr *e = (Expr *) lfirst(arg);
xstate->named_args_ncache = (char **) palloc(list_length(xexpr->named_args) * sizeof(char *)); ExprState *estate;
Oid typOutFunc;
i = 0; bool typIsVarlena;
foreach(arg, xexpr->named_args)
{ estate = ExecInitExpr(e, parent);
bool tpisvarlena; outlist = lappend(outlist, estate);
Expr *e = (Expr *) lfirst(arg);
ExprState *estate = ExecInitExpr(e, parent); getTypeOutputInfo(exprType((Node *) e),
TargetEntry *tle; &typOutFunc, &typIsVarlena);
outlist = lappend(outlist, estate); fmgr_info(typOutFunc, &xstate->named_outfuncs[i]);
tle = (TargetEntry *) ((GenericExprState *) estate)->xprstate.expr; i++;
getTypeOutputInfo(exprType((Node *)tle->expr), &typeout, &tpisvarlena);
xstate->named_args_ncache[i] = tle->resname;
xstate->named_args_tcache[i] = typeout;
i++;
}
}
else
{
xstate->named_args_tcache = NULL;
xstate->named_args_ncache = NULL;
} }
xstate->named_args = outlist; xstate->named_args = outlist;
outlist = NIL; outlist = NIL;
foreach(arg, xexpr->args) foreach(arg, xexpr->args)
{ {
bool tpisvarlena; Expr *e = (Expr *) lfirst(arg);
ExprState *estate; ExprState *estate;
Expr *e = (Expr *) lfirst(arg);
getTypeOutputInfo(exprType((Node *)e), &typeout, &tpisvarlena);
estate = ExecInitExpr(e, parent); estate = ExecInitExpr(e, parent);
outlist = lappend(outlist, estate); outlist = lappend(outlist, estate);
} }
xstate->arg_typeout = typeout;
xstate->args = outlist; xstate->args = outlist;
state = (ExprState *) xstate; state = (ExprState *) xstate;
} }
break; break;

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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; 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) * _copyNullIfExpr (same as OpExpr)
*/ */
@ -1138,22 +1155,6 @@ _copyBooleanTest(BooleanTest *from)
return newnode; 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 * _copyCoerceToDomain
*/ */
@ -2977,6 +2978,9 @@ copyObject(void *from)
case T_MinMaxExpr: case T_MinMaxExpr:
retval = _copyMinMaxExpr(from); retval = _copyMinMaxExpr(from);
break; break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;
case T_NullIfExpr: case T_NullIfExpr:
retval = _copyNullIfExpr(from); retval = _copyNullIfExpr(from);
break; break;
@ -2986,9 +2990,6 @@ copyObject(void *from)
case T_BooleanTest: case T_BooleanTest:
retval = _copyBooleanTest(from); retval = _copyBooleanTest(from);
break; break;
case T_XmlExpr:
retval = _copyXmlExpr(from);
break;
case T_CoerceToDomain: case T_CoerceToDomain:
retval = _copyCoerceToDomain(from); retval = _copyCoerceToDomain(from);
break; break;

View File

@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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; 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 static bool
_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b) _equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
{ {
@ -495,17 +507,6 @@ _equalBooleanTest(BooleanTest *a, BooleanTest *b)
return true; 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 static bool
_equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b) _equalCoerceToDomain(CoerceToDomain *a, CoerceToDomain *b)
{ {
@ -1971,6 +1972,9 @@ equal(void *a, void *b)
case T_MinMaxExpr: case T_MinMaxExpr:
retval = _equalMinMaxExpr(a, b); retval = _equalMinMaxExpr(a, b);
break; break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;
case T_NullIfExpr: case T_NullIfExpr:
retval = _equalNullIfExpr(a, b); retval = _equalNullIfExpr(a, b);
break; break;
@ -1980,9 +1984,6 @@ equal(void *a, void *b)
case T_BooleanTest: case T_BooleanTest:
retval = _equalBooleanTest(a, b); retval = _equalBooleanTest(a, b);
break; break;
case T_XmlExpr:
retval = _equalXmlExpr(a, b);
break;
case T_CoerceToDomain: case T_CoerceToDomain:
retval = _equalCoerceToDomain(a, b); retval = _equalCoerceToDomain(a, b);
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
@ -892,6 +892,18 @@ _outMinMaxExpr(StringInfo str, MinMaxExpr *node)
WRITE_NODE_FIELD(args); 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 static void
_outNullIfExpr(StringInfo str, NullIfExpr *node) _outNullIfExpr(StringInfo str, NullIfExpr *node)
{ {
@ -922,17 +934,6 @@ _outBooleanTest(StringInfo str, BooleanTest *node)
WRITE_ENUM_FIELD(booltesttype, BoolTestType); 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 static void
_outCoerceToDomain(StringInfo str, CoerceToDomain *node) _outCoerceToDomain(StringInfo str, CoerceToDomain *node)
{ {
@ -2026,6 +2027,9 @@ _outNode(StringInfo str, void *obj)
case T_MinMaxExpr: case T_MinMaxExpr:
_outMinMaxExpr(str, obj); _outMinMaxExpr(str, obj);
break; break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;
case T_NullIfExpr: case T_NullIfExpr:
_outNullIfExpr(str, obj); _outNullIfExpr(str, obj);
break; break;
@ -2035,9 +2039,6 @@ _outNode(StringInfo str, void *obj)
case T_BooleanTest: case T_BooleanTest:
_outBooleanTest(str, obj); _outBooleanTest(str, obj);
break; break;
case T_XmlExpr:
_outXmlExpr(str, obj);
break;
case T_CoerceToDomain: case T_CoerceToDomain:
_outCoerceToDomain(str, obj); _outCoerceToDomain(str, obj);
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
@ -708,6 +708,23 @@ _readMinMaxExpr(void)
READ_DONE(); 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 * _readNullIfExpr
*/ */
@ -764,22 +781,6 @@ _readBooleanTest(void)
READ_DONE(); 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 * _readCoerceToDomain
*/ */
@ -1024,14 +1025,14 @@ parseNodeString(void)
return_value = _readCoalesceExpr(); return_value = _readCoalesceExpr();
else if (MATCH("MINMAX", 6)) else if (MATCH("MINMAX", 6))
return_value = _readMinMaxExpr(); return_value = _readMinMaxExpr();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("NULLIFEXPR", 10)) else if (MATCH("NULLIFEXPR", 10))
return_value = _readNullIfExpr(); return_value = _readNullIfExpr();
else if (MATCH("NULLTEST", 8)) else if (MATCH("NULLTEST", 8))
return_value = _readNullTest(); return_value = _readNullTest();
else if (MATCH("BOOLEANTEST", 11)) else if (MATCH("BOOLEANTEST", 11))
return_value = _readBooleanTest(); return_value = _readBooleanTest();
else if (MATCH("XMLEXPR", 7))
return_value = _readXmlExpr();
else if (MATCH("COERCETODOMAIN", 14)) else if (MATCH("COERCETODOMAIN", 14))
return_value = _readCoerceToDomain(); return_value = _readCoerceToDomain();
else if (MATCH("COERCETODOMAINVALUE", 19)) else if (MATCH("COERCETODOMAINVALUE", 19))

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -557,10 +557,10 @@ expression_returns_set_walker(Node *node, void *context)
return false; return false;
if (IsA(node, MinMaxExpr)) if (IsA(node, MinMaxExpr))
return false; return false;
if (IsA(node, NullIfExpr))
return false;
if (IsA(node, XmlExpr)) if (IsA(node, XmlExpr))
return false; return false;
if (IsA(node, NullIfExpr))
return false;
return expression_tree_walker(node, expression_returns_set_walker, return expression_tree_walker(node, expression_returns_set_walker,
context); context);
@ -872,14 +872,14 @@ contain_nonstrict_functions_walker(Node *node, void *context)
return true; return true;
if (IsA(node, MinMaxExpr)) if (IsA(node, MinMaxExpr))
return true; return true;
if (IsA(node, XmlExpr))
return true;
if (IsA(node, NullIfExpr)) if (IsA(node, NullIfExpr))
return true; return true;
if (IsA(node, NullTest)) if (IsA(node, NullTest))
return true; return true;
if (IsA(node, BooleanTest)) if (IsA(node, BooleanTest))
return true; return true;
if (IsA(node, XmlExpr))
return true;
return expression_tree_walker(node, contain_nonstrict_functions_walker, return expression_tree_walker(node, contain_nonstrict_functions_walker,
context); context);
} }
@ -3328,22 +3328,23 @@ expression_tree_walker(Node *node,
return walker(((CoalesceExpr *) node)->args, context); return walker(((CoalesceExpr *) node)->args, context);
case T_MinMaxExpr: case T_MinMaxExpr:
return walker(((MinMaxExpr *) node)->args, context); 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: case T_XmlExpr:
{ {
XmlExpr *xexpr = (XmlExpr *) node; XmlExpr *xexpr = (XmlExpr *) node;
if (walker(xexpr->named_args, context)) if (walker(xexpr->named_args, context))
return true; return true;
/* we assume walker doesn't care about arg_names */
if (walker(xexpr->args, context)) if (walker(xexpr->args, context))
return true; return true;
} }
break; 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: case T_CoerceToDomain:
return walker(((CoerceToDomain *) node)->arg, context); return walker(((CoerceToDomain *) node)->arg, context);
case T_TargetEntry: case T_TargetEntry:
@ -3874,6 +3875,7 @@ expression_tree_mutator(Node *node,
FLATCOPY(newnode, xexpr, XmlExpr); FLATCOPY(newnode, xexpr, XmlExpr);
MUTATE(newnode->named_args, xexpr->named_args, List *); MUTATE(newnode->named_args, xexpr->named_args, List *);
/* assume mutator does not care about arg_names */
MUTATE(newnode->args, xexpr->args, List *); MUTATE(newnode->args, xexpr->args, List *);
return (Node *) newnode; return (Node *) newnode;
} }

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * 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 <target> xml_attribute_el
%type <list> xml_attribute_list xml_attributes %type <list> xml_attribute_list xml_attributes
%type <node> xml_root_version %type <node> xml_root_version opt_xml_root_standalone
%type <ival> opt_xml_root_standalone document_or_content xml_whitespace_option %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 CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS 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 CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS 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 EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUDING
EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT 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 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 NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC 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 SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE START STATEMENT SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT
STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP SUBSTRING SUPERUSER_P SYMMETRIC STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P
SYSID SYSTEM_P SYMMETRIC SYSID SYSTEM_P
TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P 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 UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
UPDATE USER USING UPDATE USER USING
VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARYING
VERBOSE VERSION VIEW VOLATILE 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 XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE XMLPI XMLROOT XMLSERIALIZE
YEAR_P YES YEAR_P YES_P
ZONE 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-associativity among the JOIN rules themselves.
*/ */
%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL %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 ')' | 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); $$ = makeXmlExpr(IS_XMLELEMENT, $4, $6, $8);
} }
| XMLFOREST '(' xml_attribute_list ')' | 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 ')' | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
{ {
FuncCall *n = makeNode(FuncCall); $$ = makeXmlExpr(IS_XMLPARSE, NULL, NIL,
n->funcname = SystemFuncName("xmlparse"); list_make3($4,
n->args = list_make3(makeBoolAConst($3 == DOCUMENT), $4, makeBoolAConst($5 == PRESERVE)); makeBoolAConst($3),
n->agg_star = FALSE; makeBoolAConst($5)));
n->agg_distinct = FALSE;
n->location = @1;
$$ = (Node *)n;
} }
| XMLPI '(' NAME ColLabel ')' | XMLPI '(' NAME_P ColLabel ')'
{ {
FuncCall *n = makeNode(FuncCall); $$ = makeXmlExpr(IS_XMLPI, $4, NULL, NIL);
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 ')' | XMLPI '(' NAME_P ColLabel ',' a_expr ')'
{ {
FuncCall *n = makeNode(FuncCall); $$ = makeXmlExpr(IS_XMLPI, $4, NULL, list_make1($6));
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 ')' | XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'
{ {
FuncCall *n = makeNode(FuncCall); $$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
Node *ver; list_make3($3, $5, $6));
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 ')' | XMLSERIALIZE '(' document_or_content a_expr AS Typename ')'
{ {
/* /*
* FIXME: This should be made distinguishable from * 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); $$ = makeTypeCast($4, $6);
} }
@ -7977,17 +7937,35 @@ func_expr: func_name '(' ')'
/* /*
* SQL/XML support * SQL/XML support
*/ */
xml_root_version: VERSION a_expr { $$ = $2; } xml_root_version: VERSION_P a_expr
| VERSION NO VALUE { $$ = NULL; } { $$ = $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; } opt_xml_root_standalone: ',' STANDALONE_P YES_P
| ',' STANDALONE NO { $$ = -1; } { $$ = (Node *) makeBoolAConst(true); }
| ',' STANDALONE NO VALUE { $$ = 0; } | ',' STANDALONE_P NO
| /*EMPTY*/ { $$ = 0; } { $$ = (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); } xml_attribute_list: xml_attribute_el { $$ = list_make1($1); }
@ -8000,7 +7978,7 @@ xml_attribute_el: a_expr AS ColLabel
$$->name = $3; $$->name = $3;
$$->indirection = NULL; $$->indirection = NULL;
$$->val = (Node *) $1; $$->val = (Node *) $1;
$$->location = @1;
} }
| a_expr | a_expr
{ {
@ -8008,16 +7986,21 @@ xml_attribute_el: a_expr AS ColLabel
$$->name = NULL; $$->name = NULL;
$$->indirection = NULL; $$->indirection = NULL;
$$->val = (Node *) $1; $$->val = (Node *) $1;
$$->location = @1;
} }
; ;
document_or_content: DOCUMENT { $$ = DOCUMENT; } document_or_content: DOCUMENT_P { $$ = TRUE; }
| CONTENT { $$ = CONTENT; } | CONTENT_P { $$ = FALSE; }
; ;
xml_whitespace_option: PRESERVE WHITESPACE { $$ = PRESERVE; } /*
| STRIP WHITESPACE { $$ = STRIP; } * XXX per SQL spec, the default should be STRIP WHITESPACE, but since we
| /*EMPTY*/ { $$ = STRIP; } * 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 | CONCURRENTLY
| CONNECTION | CONNECTION
| CONSTRAINTS | CONSTRAINTS
| CONTENT | CONTENT_P
| CONVERSION_P | CONVERSION_P
| COPY | COPY
| CREATEDB | CREATEDB
@ -8732,7 +8715,7 @@ unreserved_keyword:
| DELIMITER | DELIMITER
| DELIMITERS | DELIMITERS
| DISABLE_P | DISABLE_P
| DOCUMENT | DOCUMENT_P
| DOMAIN_P | DOMAIN_P
| DOUBLE_P | DOUBLE_P
| DROP | DROP
@ -8792,7 +8775,7 @@ unreserved_keyword:
| MODE | MODE
| MONTH_P | MONTH_P
| MOVE | MOVE
| NAME | NAME_P
| NAMES | NAMES
| NEXT | NEXT
| NO | NO
@ -8853,18 +8836,18 @@ unreserved_keyword:
| SHOW | SHOW
| SIMPLE | SIMPLE
| STABLE | STABLE
| STANDALONE | STANDALONE_P
| START | START
| STATEMENT | STATEMENT
| STATISTICS | STATISTICS
| STDIN | STDIN
| STDOUT | STDOUT
| STORAGE | STORAGE
| STRIP | STRICT_P
| STRIP_P
| SUPERUSER_P | SUPERUSER_P
| SYSID | SYSID
| SYSTEM_P | SYSTEM_P
| STRICT_P
| TABLESPACE | TABLESPACE
| TEMP | TEMP
| TEMPLATE | TEMPLATE
@ -8883,18 +8866,18 @@ unreserved_keyword:
| VACUUM | VACUUM
| VALID | VALID
| VALIDATOR | VALIDATOR
| VALUE_P
| VARYING | VARYING
| VERSION | VERSION_P
| VIEW | VIEW
| VALUE
| VOLATILE | VOLATILE
| WHITESPACE | WHITESPACE_P
| WITH | WITH
| WITHOUT | WITHOUT
| WORK | WORK
| WRITE | WRITE
| YEAR_P | YEAR_P
| YES | YES_P
| ZONE | ZONE
; ;
@ -8948,8 +8931,8 @@ col_name_keyword:
| VALUES | VALUES
| VARCHAR | VARCHAR
| XMLATTRIBUTES | XMLATTRIBUTES
| XMLELEMENT
| XMLCONCAT | XMLCONCAT
| XMLELEMENT
| XMLFOREST | XMLFOREST
| XMLPARSE | XMLPARSE
| XMLPI | XMLPI
@ -9492,10 +9475,16 @@ doNegateFloat(Value *v)
static Node * static Node *
makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
{ {
XmlExpr *x = makeNode(XmlExpr); XmlExpr *x = makeNode(XmlExpr);
x->op = op; x->op = op;
x->name = name; 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->named_args = named_args;
x->arg_names = NIL;
x->args = args; x->args = args;
return (Node *) x; return (Node *) x;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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}, {"connection", CONNECTION},
{"constraint", CONSTRAINT}, {"constraint", CONSTRAINT},
{"constraints", CONSTRAINTS}, {"constraints", CONSTRAINTS},
{"content", CONTENT}, {"content", CONTENT_P},
{"conversion", CONVERSION_P}, {"conversion", CONVERSION_P},
{"convert", CONVERT}, {"convert", CONVERT},
{"copy", COPY}, {"copy", COPY},
@ -124,7 +124,7 @@ static const ScanKeyword ScanKeywords[] = {
{"disable", DISABLE_P}, {"disable", DISABLE_P},
{"distinct", DISTINCT}, {"distinct", DISTINCT},
{"do", DO}, {"do", DO},
{"document", DOCUMENT}, {"document", DOCUMENT_P},
{"domain", DOMAIN_P}, {"domain", DOMAIN_P},
{"double", DOUBLE_P}, {"double", DOUBLE_P},
{"drop", DROP}, {"drop", DROP},
@ -220,7 +220,7 @@ static const ScanKeyword ScanKeywords[] = {
{"mode", MODE}, {"mode", MODE},
{"month", MONTH_P}, {"month", MONTH_P},
{"move", MOVE}, {"move", MOVE},
{"name", NAME}, {"name", NAME_P},
{"names", NAMES}, {"names", NAMES},
{"national", NATIONAL}, {"national", NATIONAL},
{"natural", NATURAL}, {"natural", NATURAL},
@ -317,7 +317,7 @@ static const ScanKeyword ScanKeywords[] = {
{"smallint", SMALLINT}, {"smallint", SMALLINT},
{"some", SOME}, {"some", SOME},
{"stable", STABLE}, {"stable", STABLE},
{"standalone", STANDALONE}, {"standalone", STANDALONE_P},
{"start", START}, {"start", START},
{"statement", STATEMENT}, {"statement", STATEMENT},
{"statistics", STATISTICS}, {"statistics", STATISTICS},
@ -325,7 +325,7 @@ static const ScanKeyword ScanKeywords[] = {
{"stdout", STDOUT}, {"stdout", STDOUT},
{"storage", STORAGE}, {"storage", STORAGE},
{"strict", STRICT_P}, {"strict", STRICT_P},
{"strip", STRIP}, {"strip", STRIP_P},
{"substring", SUBSTRING}, {"substring", SUBSTRING},
{"superuser", SUPERUSER_P}, {"superuser", SUPERUSER_P},
{"symmetric", SYMMETRIC}, {"symmetric", SYMMETRIC},
@ -362,17 +362,17 @@ static const ScanKeyword ScanKeywords[] = {
{"vacuum", VACUUM}, {"vacuum", VACUUM},
{"valid", VALID}, {"valid", VALID},
{"validator", VALIDATOR}, {"validator", VALIDATOR},
{"value", VALUE}, {"value", VALUE_P},
{"values", VALUES}, {"values", VALUES},
{"varchar", VARCHAR}, {"varchar", VARCHAR},
{"varying", VARYING}, {"varying", VARYING},
{"verbose", VERBOSE}, {"verbose", VERBOSE},
{"version", VERSION}, {"version", VERSION_P},
{"view", VIEW}, {"view", VIEW},
{"volatile", VOLATILE}, {"volatile", VOLATILE},
{"when", WHEN}, {"when", WHEN},
{"where", WHERE}, {"where", WHERE},
{"whitespace", WHITESPACE}, {"whitespace", WHITESPACE_P},
{"with", WITH}, {"with", WITH},
{"without", WITHOUT}, {"without", WITHOUT},
{"work", WORK}, {"work", WORK},
@ -386,7 +386,7 @@ static const ScanKeyword ScanKeywords[] = {
{"xmlroot", XMLROOT}, {"xmlroot", XMLROOT},
{"xmlserialize", XMLSERIALIZE}, {"xmlserialize", XMLSERIALIZE},
{"year", YEAR_P}, {"year", YEAR_P},
{"yes", YES}, {"yes", YES_P},
{"zone", ZONE}, {"zone", ZONE},
}; };

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 = 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 * LIMIT can't refer to any vars or aggregates of the current query; we

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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_to_specific_type()
* Coerce an argument of a construct that requires integer input. * Coerce an argument of a construct that requires a specific data type.
* Also check that input is not a set. * Also check that input is not a set.
* *
* Returns the possibly-transformed node tree. * Returns the possibly-transformed node tree.
@ -850,103 +850,26 @@ coerce_to_boolean(ParseState *pstate, Node *node,
* processing is wanted. * processing is wanted.
*/ */
Node * Node *
coerce_to_integer(ParseState *pstate, Node *node, coerce_to_specific_type(ParseState *pstate, Node *node,
const char *constructName) Oid targetTypeId,
const char *constructName)
{ {
Oid inputTypeId = exprType(node); Oid inputTypeId = exprType(node);
if (inputTypeId != INT4OID) if (inputTypeId != targetTypeId)
{ {
node = coerce_to_target_type(pstate, node, inputTypeId, node = coerce_to_target_type(pstate, node, inputTypeId,
INT4OID, -1, targetTypeId, -1,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
if (node == NULL) if (node == NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
/* translator: first %s is name of a SQL construct, eg LIMIT */ /* translator: first %s is name of a SQL construct, eg LIMIT */
errmsg("argument of %s must be type integer, not type %s", errmsg("argument of %s must be type %s, not type %s",
constructName, format_type_be(inputTypeId)))); constructName,
} format_type_be(targetTypeId),
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))));
} }
if (expression_returns_set(node)) if (expression_returns_set(node))

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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); result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break; break;
case T_XmlExpr:
result = transformXmlExpr(pstate, (XmlExpr *) expr);
break;
case T_NullTest: case T_NullTest:
{ {
NullTest *n = (NullTest *) expr; NullTest *n = (NullTest *) expr;
@ -234,10 +238,6 @@ transformExpr(ParseState *pstate, Node *expr)
result = transformBooleanTest(pstate, (BooleanTest *) expr); result = transformBooleanTest(pstate, (BooleanTest *) expr);
break; break;
case T_XmlExpr:
result = transformXmlExpr(pstate, (XmlExpr *) expr);
break;
/********************************************* /*********************************************
* Quietly accept node types that may be presented when we are * Quietly accept node types that may be presented when we are
* called on an already-transformed tree. * called on an already-transformed tree.
@ -1375,6 +1375,107 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
return (Node *) newm; 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 * static Node *
transformBooleanTest(ParseState *pstate, BooleanTest *b) transformBooleanTest(ParseState *pstate, BooleanTest *b)
{ {
@ -1415,56 +1516,6 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
return (Node *) 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.*". * Construct a whole-row reference to represent the notation "relation.*".
* *
@ -1715,6 +1766,9 @@ exprType(Node *expr)
case T_MinMaxExpr: case T_MinMaxExpr:
type = ((MinMaxExpr *) expr)->minmaxtype; type = ((MinMaxExpr *) expr)->minmaxtype;
break; break;
case T_XmlExpr:
type = XMLOID;
break;
case T_NullIfExpr: case T_NullIfExpr:
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args)); type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
break; break;
@ -1724,9 +1778,6 @@ exprType(Node *expr)
case T_BooleanTest: case T_BooleanTest:
type = BOOLOID; type = BOOLOID;
break; break;
case T_XmlExpr:
type = XMLOID;
break;
case T_CoerceToDomain: case T_CoerceToDomain:
type = ((CoerceToDomain *) expr)->resulttype; type = ((CoerceToDomain *) expr)->resulttype;
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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: case IS_XMLFOREST:
*name = "xmlforest"; *name = "xmlforest";
return 2; return 2;
case IS_XMLPARSE:
*name = "xmlparse";
return 2;
case IS_XMLPI:
*name = "xmlpi";
return 2;
case IS_XMLROOT:
*name = "xmlroot";
return 2;
} }
break; break;
default: default:

View File

@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees * ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text * 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" #include "postgres.h"
@ -2988,8 +2988,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RowExpr: case T_RowExpr:
case T_CoalesceExpr: case T_CoalesceExpr:
case T_MinMaxExpr: case T_MinMaxExpr:
case T_NullIfExpr:
case T_XmlExpr: case T_XmlExpr:
case T_NullIfExpr:
case T_Aggref: case T_Aggref:
case T_FuncExpr: case T_FuncExpr:
/* function-like: name(..) or name[..] */ /* function-like: name(..) or name[..] */
@ -3097,8 +3097,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RowExpr: /* other separators */ case T_RowExpr: /* other separators */
case T_CoalesceExpr: /* own parentheses */ case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */ case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_XmlExpr: /* own parentheses */ case T_XmlExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_Aggref: /* own parentheses */ case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */ case T_CaseExpr: /* other separators */
return true; return true;
@ -3146,8 +3146,8 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RowExpr: /* other separators */ case T_RowExpr: /* other separators */
case T_CoalesceExpr: /* own parentheses */ case T_CoalesceExpr: /* own parentheses */
case T_MinMaxExpr: /* own parentheses */ case T_MinMaxExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_XmlExpr: /* own parentheses */ case T_XmlExpr: /* own parentheses */
case T_NullIfExpr: /* other separators */
case T_Aggref: /* own parentheses */ case T_Aggref: /* own parentheses */
case T_CaseExpr: /* other separators */ case T_CaseExpr: /* other separators */
return true; return true;
@ -3779,6 +3779,140 @@ get_rule_expr(Node *node, deparse_context *context,
} }
break; 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: case T_NullIfExpr:
{ {
NullIfExpr *nullifexpr = (NullIfExpr *) node; NullIfExpr *nullifexpr = (NullIfExpr *) node;
@ -3849,28 +3983,6 @@ get_rule_expr(Node *node, deparse_context *context,
} }
break; 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: case T_CoerceToDomain:
{ {
CoerceToDomain *ctest = (CoerceToDomain *) node; CoerceToDomain *ctest = (CoerceToDomain *) node;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #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 PG_XML_DEFAULT_URI "dummy.xml"
#define XML_ERRBUF_SIZE 200 #define XML_ERRBUF_SIZE 200
@ -177,31 +168,18 @@ xmlcomment(PG_FUNCTION_ARGS)
Datum Datum
xmlparse(PG_FUNCTION_ARGS) texttoxml(PG_FUNCTION_ARGS)
{
text *data = PG_GETARG_TEXT_P(0);
PG_RETURN_XML_P(xmlparse(data, false, true));
}
xmltype *
xmlparse(text *data, bool is_document, bool preserve_whitespace)
{ {
#ifdef USE_LIBXML #ifdef USE_LIBXML
text *data;
bool is_document;
bool preserve_whitespace;
data = PG_GETARG_TEXT_P(0);
if (PG_NARGS() >= 2)
is_document = PG_GETARG_BOOL(1);
else
is_document = false;
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;
if (!preserve_whitespace) if (!preserve_whitespace)
ereport(WARNING, ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@ -213,111 +191,93 @@ xmlparse(PG_FUNCTION_ARGS)
* valies defined by internal DTD are applied'. As for external * valies defined by internal DTD are applied'. As for external
* DTDs, we try to support them too, (see SQL/XML:10.16.7.e) * 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 #else
NO_XML_SUPPORT(); NO_XML_SUPPORT();
return 0; return NULL;
#endif #endif
} }
Datum xmltype *
xmlpi(PG_FUNCTION_ARGS) xmlpi(char *target, text *arg)
{ {
#ifdef USE_LIBXML #ifdef USE_LIBXML
char *target = NameStr(*PG_GETARG_NAME(0)); xmltype *result;
StringInfoData buf; StringInfoData buf;
if (strlen(target) >= 3 if (pg_strncasecmp(target, "xml", 3) == 0)
&& (target[0] == 'x' || target[0] == 'X')
&& (target[1] == 'm' || target[1] == 'M')
&& (target[2] == 'l' || target[2] == 'L'))
{
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
errmsg("invalid XML processing instruction"), errmsg("invalid XML processing instruction"),
errdetail("XML processing instruction target name cannot start with \"xml\"."))); errdetail("XML processing instruction target name cannot start with \"xml\".")));
}
initStringInfo(&buf); initStringInfo(&buf);
appendStringInfo(&buf, "<?"); appendStringInfo(&buf, "<?%s", target);
appendStringInfoString(&buf, map_sql_identifier_to_xml_name(target, false));
if (PG_NARGS() > 1) if (arg != NULL)
{ {
text *arg = PG_GETARG_TEXT_P(1);
char *string; char *string;
string = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(arg))); string = DatumGetCString(DirectFunctionCall1(textout,
if (strstr(string, "?>")) PointerGetDatum(arg)));
if (strstr(string, "?>") != NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION), (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
errmsg("invalid XML processing instruction"), errmsg("invalid XML processing instruction"),
errdetail("XML processing instruction cannot contain \"?>\"."))); errdetail("XML processing instruction cannot contain \"?>\".")));
appendStringInfoString(&buf, " "); appendStringInfoChar(&buf, ' ');
appendStringInfoString(&buf, string); appendStringInfoString(&buf, string);
pfree(string);
} }
appendStringInfoString(&buf, "?>"); appendStringInfoString(&buf, "?>");
PG_RETURN_XML_P(stringinfo_to_xmltype(&buf)); result = stringinfo_to_xmltype(&buf);
pfree(buf.data);
return result;
#else #else
NO_XML_SUPPORT(); NO_XML_SUPPORT();
return 0; return NULL;
#endif #endif
} }
Datum xmltype *
xmlroot(PG_FUNCTION_ARGS) xmlroot(xmltype *data, text *version, int standalone)
{ {
#ifdef USE_LIBXML #ifdef USE_LIBXML
xmltype *data; xmltype *result;
text *version;
int standalone;
StringInfoData buf; StringInfoData buf;
if (PG_ARGISNULL(0)) initStringInfo(&buf);
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);
}
/* /*
* FIXME: This is probably supposed to be cleverer if there * FIXME: This is probably supposed to be cleverer if there
* already is an XML preamble. * already is an XML preamble.
*/ */
initStringInfo(&buf);
appendStringInfo(&buf,"<?xml"); appendStringInfo(&buf,"<?xml");
if (version) { if (version)
{
appendStringInfo(&buf, " version=\""); appendStringInfo(&buf, " version=\"");
appendStringInfoText(&buf, version); appendStringInfoText(&buf, version);
appendStringInfo(&buf, "\""); appendStringInfo(&buf, "\"");
} }
if (standalone) if (standalone)
appendStringInfo(&buf, " standalone=\"%s\"", (standalone == 1 ? "yes" : "no")); appendStringInfo(&buf, " standalone=\"%s\"",
(standalone == 1 ? "yes" : "no"));
appendStringInfo(&buf, "?>"); appendStringInfo(&buf, "?>");
appendStringInfoText(&buf, (text *) data); appendStringInfoText(&buf, (text *) data);
PG_RETURN_XML_P(stringinfo_to_xmltype(&buf)); result = stringinfo_to_xmltype(&buf);
pfree(buf.data);
return result;
#else #else
NO_XML_SUPPORT(); NO_XML_SUPPORT();
return 0; return NULL;
#endif #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 */ /* first, we try to parse the string as XML doc, then, as XML chunk */
ereport(DEBUG3, (errmsg("string to parse: %s", string))); 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 */ /* consider it as DOCUMENT */
doc = xmlCtxtReadMemory(ctxt, (char *) string, len, doc = xmlCtxtReadMemory(ctxt, (char *) string, len,
@ -918,10 +878,8 @@ map_sql_identifier_to_xml_name(char *ident, bool fully_escaped)
appendStringInfo(&buf, "_x003A_"); appendStringInfo(&buf, "_x003A_");
else if (*p == '_' && *(p+1) == 'x') else if (*p == '_' && *(p+1) == 'x')
appendStringInfo(&buf, "_x005F_"); appendStringInfo(&buf, "_x005F_");
else if (fully_escaped && p == ident else if (fully_escaped && p == ident &&
&& ( *p == 'x' || *p == 'X') pg_strncasecmp(p, "xml", 3) == 0)
&& ( *(p+1) == 'm' || *(p+1) == 'M')
&& ( *(p+2) == 'l' || *(p+2) == 'L'))
{ {
if (*p == 'x') if (*p == 'x')
appendStringInfo(&buf, "_x0078_"); 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); pg_wchar u = sqlchar_to_unicode(p);
if (!is_valid_xml_namechar(u) if ((p == ident)
|| (p == ident && !is_valid_xml_namefirst(u))) ? !is_valid_xml_namefirst(u)
appendStringInfo(&buf, "_x%04X_", (unsigned int) u); : !is_valid_xml_namechar(u))
appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
else else
appendBinaryStringInfo(&buf, p, pg_mblen(p)); appendBinaryStringInfo(&buf, p, pg_mblen(p));
} }

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200612221 #define CATALOG_VERSION_NO 200612231
#endif #endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * 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"); DESCR("I/O");
DATA(insert OID = 2895 ( xmlcomment PGNSP PGUID 12 f f t f i 1 142 "25" _null_ _null_ _null_ xmlcomment - _null_ )); 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"); 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"); 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_ )); DATA(insert OID = 2897 ( xmlvalidate PGNSP PGUID 12 f f t f i 2 16 "142 25" _null_ _null_ _null_ xmlvalidate - _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_ ));
DESCR("validate an XML value"); DESCR("validate an XML value");
/* /*

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 */ FmgrInfo cfunc; /* lookup info for comparison func */
} MinMaxExprState; } 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 * NullTestState node
* ---------------- * ----------------
@ -723,22 +735,6 @@ typedef struct NullTestState
TupleDesc argdesc; /* tupdesc for most recent input */ TupleDesc argdesc; /* tupdesc for most recent input */
} NullTestState; } 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 * CoerceToDomainState node
* ---------------- * ----------------

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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_RowCompareExpr,
T_CoalesceExpr, T_CoalesceExpr,
T_MinMaxExpr, T_MinMaxExpr,
T_XmlExpr,
T_NullIfExpr, T_NullIfExpr,
T_NullTest, T_NullTest,
T_BooleanTest, T_BooleanTest,
@ -140,7 +141,6 @@ typedef enum NodeTag
T_RangeTblRef, T_RangeTblRef,
T_JoinExpr, T_JoinExpr,
T_FromExpr, T_FromExpr,
T_XmlExpr,
/* /*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h) * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
@ -166,10 +166,10 @@ typedef enum NodeTag
T_RowCompareExprState, T_RowCompareExprState,
T_CoalesceExprState, T_CoalesceExprState,
T_MinMaxExprState, T_MinMaxExprState,
T_XmlExprState,
T_NullTestState, T_NullTestState,
T_CoerceToDomainState, T_CoerceToDomainState,
T_DomainConstraintState, T_DomainConstraintState,
T_XmlExprState,
/* /*
* TAGS FOR PLANNER NODES (relation.h) * TAGS FOR PLANNER NODES (relation.h)

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 */ List *args; /* the arguments */
} MinMaxExpr; } 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 * NullIfExpr - a NULLIF expression
* *
@ -765,26 +792,6 @@ typedef struct BooleanTest
BoolTestType booltesttype; /* test type */ BoolTestType booltesttype; /* test type */
} BooleanTest; } 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 * CoerceToDomain
* *

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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, extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
const char *constructName); const char *constructName);
extern Node *coerce_to_integer(ParseState *pstate, Node *node, extern Node *coerce_to_specific_type(ParseState *pstate, Node *node,
const char *constructName); Oid targetTypeId,
extern Node *coerce_to_bigint(ParseState *pstate, Node *node, const char *constructName);
const char *constructName);
extern Node *coerce_to_xml(ParseState *pstate, Node *node,
const char *constructName);
extern Oid select_common_type(List *typeids, const char *context); extern Oid select_common_type(List *typeids, const char *context);
extern Node *coerce_to_common_type(ParseState *pstate, Node *node, extern Node *coerce_to_common_type(ParseState *pstate, Node *node,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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_in(PG_FUNCTION_ARGS);
extern Datum xml_out(PG_FUNCTION_ARGS); extern Datum xml_out(PG_FUNCTION_ARGS);
extern Datum xmlcomment(PG_FUNCTION_ARGS); extern Datum xmlcomment(PG_FUNCTION_ARGS);
extern Datum xmlparse(PG_FUNCTION_ARGS); extern Datum texttoxml(PG_FUNCTION_ARGS);
extern Datum xmlpi(PG_FUNCTION_ARGS);
extern Datum xmlroot(PG_FUNCTION_ARGS);
extern Datum xmlvalidate(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); extern char *map_sql_identifier_to_xml_name(char *ident, bool fully_escaped);
#endif /* XML_H */ #endif /* XML_H */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; 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: case T_NullIfExpr:
{ {
NullIfExpr *expr = (NullIfExpr *) node; NullIfExpr *expr = (NullIfExpr *) node;

View File

@ -9,7 +9,7 @@
* *
* Copyright (c) 2003-2006, PostgreSQL Global Development Group * 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 "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 "integrity_constraint_violation", ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION
}, },

View File

@ -74,7 +74,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname, p2.oid, p2.proname SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2 FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND 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.prolang = 12 AND p2.prolang = 12 AND
(p1.proisagg = false OR p2.proisagg = false) AND (p1.proisagg = false OR p2.proisagg = false) AND
(p1.prolang != p2.prolang OR (p1.prolang != p2.prolang OR

View File

@ -77,7 +77,7 @@ WHERE p1.oid != p2.oid AND
SELECT p1.oid, p1.proname, p2.oid, p2.proname SELECT p1.oid, p1.proname, p2.oid, p2.proname
FROM pg_proc AS p1, pg_proc AS p2 FROM pg_proc AS p1, pg_proc AS p2
WHERE p1.oid < p2.oid AND 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.prolang = 12 AND p2.prolang = 12 AND
(p1.proisagg = false OR p2.proisagg = false) AND (p1.proisagg = false OR p2.proisagg = false) AND
(p1.prolang != p2.prolang OR (p1.prolang != p2.prolang OR