diff options
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r-- | src/backend/executor/execQual.c | 177 |
1 files changed, 176 insertions, 1 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 1dbef5f15c9..10b02b4a3ec 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.199 2006/11/17 16:46:27 petere Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.200 2006/12/21 16:05:13 petere Exp $ * *------------------------------------------------------------------------- */ @@ -52,6 +52,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/typcache.h" +#include "utils/xml.h" /* static function decls */ @@ -119,6 +120,8 @@ static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr, static Datum ExecEvalNullIf(FuncExprState *nullIfExpr, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); +static Datum ExecEvalXml(XmlExprState *xmlExpr, ExprContext *econtext, + bool *isNull, ExprDoneCond *isDone); static Datum ExecEvalNullTest(NullTestState *nstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); @@ -2878,6 +2881,120 @@ 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 * @@ -3668,6 +3785,64 @@ ExecInitExpr(Expr *node, PlanState *parent) state = (ExprState *) mstate; } break; + case T_XmlExpr: + { + List *outlist; + ListCell *arg; + XmlExpr *xexpr = (XmlExpr *) node; + XmlExprState *xstate = makeNode(XmlExprState); + int i = 0; + Oid typeout; + + xstate->name = xexpr->name; + + xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml; + xstate->op = xexpr->op; + + outlist = NIL; + if (xexpr->named_args) + { + xstate->named_args_tcache = (Oid *) palloc(list_length(xexpr->named_args) * sizeof(int)); + xstate->named_args_ncache = (char **) palloc(list_length(xexpr->named_args) * sizeof(char *)); + + i = 0; + foreach(arg, xexpr->named_args) + { + bool tpisvarlena; + Expr *e = (Expr *) lfirst(arg); + ExprState *estate = ExecInitExpr(e, parent); + TargetEntry *tle; + outlist = lappend(outlist, estate); + tle = (TargetEntry *) ((GenericExprState *) estate)->xprstate.expr; + 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; + + outlist = NIL; + foreach(arg, xexpr->args) + { + bool tpisvarlena; + ExprState *estate; + Expr *e = (Expr *) lfirst(arg); + getTypeOutputInfo(exprType((Node *)e), &typeout, &tpisvarlena); + estate = ExecInitExpr(e, parent); + outlist = lappend(outlist, estate); + } + xstate->arg_typeout = typeout; + xstate->args = outlist; + + state = (ExprState *) xstate; + } + break; case T_NullIfExpr: { NullIfExpr *nullifexpr = (NullIfExpr *) node; |