aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 94a5c110d41..fc16cccdda9 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.155 2004/03/17 01:02:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.156 2004/03/17 20:48:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -81,6 +81,9 @@ static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalArray(ArrayExprState *astate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
@@ -1809,11 +1812,30 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
{
List *clauses = caseExpr->args;
List *clause;
+ Datum save_datum;
+ bool save_isNull;
if (isDone)
*isDone = ExprSingleResult;
/*
+ * If there's a test expression, we have to evaluate it and save
+ * the value where the CaseTestExpr placeholders can find it.
+ * We must save and restore prior setting of econtext's caseValue fields,
+ * in case this node is itself within a larger CASE.
+ */
+ save_datum = econtext->caseValue_datum;
+ save_isNull = econtext->caseValue_isNull;
+
+ if (caseExpr->arg)
+ {
+ econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg,
+ econtext,
+ &econtext->caseValue_isNull,
+ NULL);
+ }
+
+ /*
* we evaluate each of the WHEN clauses in turn, as soon as one is
* true we return the corresponding result. If none are true then we
* return the value of the default clause, or NULL if there is none.
@@ -1835,6 +1857,8 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
*/
if (DatumGetBool(clause_value) && !*isNull)
{
+ econtext->caseValue_datum = save_datum;
+ econtext->caseValue_isNull = save_isNull;
return ExecEvalExpr(wclause->result,
econtext,
isNull,
@@ -1842,6 +1866,9 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
}
}
+ econtext->caseValue_datum = save_datum;
+ econtext->caseValue_isNull = save_isNull;
+
if (caseExpr->defresult)
{
return ExecEvalExpr(caseExpr->defresult,
@@ -1854,6 +1881,22 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
return (Datum) 0;
}
+/*
+ * ExecEvalCaseTestExpr
+ *
+ * Return the value stored by CASE.
+ */
+static Datum
+ExecEvalCaseTestExpr(ExprState *exprstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone)
+{
+ if (isDone)
+ *isDone = ExprSingleResult;
+ *isNull = econtext->caseValue_isNull;
+ return econtext->caseValue_datum;
+}
+
/* ----------------------------------------------------------------
* ExecEvalArray - ARRAY[] expressions
*
@@ -2478,6 +2521,10 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) makeNode(ExprState);
state->evalfunc = ExecEvalCoerceToDomainValue;
break;
+ case T_CaseTestExpr:
+ state = (ExprState *) makeNode(ExprState);
+ state->evalfunc = ExecEvalCaseTestExpr;
+ break;
case T_Aggref:
{
Aggref *aggref = (Aggref *) node;
@@ -2666,6 +2713,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
List *inlist;
cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCase;
+ cstate->arg = ExecInitExpr(caseexpr->arg, parent);
FastListInit(&outlist);
foreach(inlist, caseexpr->args)
{
@@ -2680,8 +2728,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
FastAppend(&outlist, wstate);
}
cstate->args = FastListValue(&outlist);
- /* caseexpr->arg should be null by now */
- Assert(caseexpr->arg == NULL);
cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
state = (ExprState *) cstate;
}