From e1a8b0f2ce75e55dedae46286dd2253c322c499a Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Sat, 18 Sep 1999 23:26:37 +0000 Subject: [PATCH] Fix CASE bug identified by Keith Parks: CASE didn't reliably treat a NULL condition result as FALSE. Clean up some bogus comments here and there, too. --- src/backend/executor/execQual.c | 47 +++++++++++---------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index a3eb943ab96..a44030aa406 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.58 1999/07/19 00:26:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.59 1999/09/18 23:26:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -616,8 +616,7 @@ ExecEvalFuncArgs(FunctionCachePtr fcache, bool *argIsDone) { int i; - bool argIsNull, - *nullVect; + bool *nullVect; List *arg; nullVect = fcache->nullVect; @@ -631,12 +630,10 @@ ExecEvalFuncArgs(FunctionCachePtr fcache, * as arguments but we make an exception in the case of nested dot * expressions. We have to watch out for this case here. */ - argV[i] = (Datum) - ExecEvalExpr((Node *) lfirst(arg), - econtext, - &argIsNull, - argIsDone); - + argV[i] = ExecEvalExpr((Node *) lfirst(arg), + econtext, + & nullVect[i], + argIsDone); if (!(*argIsDone)) { @@ -644,10 +641,6 @@ ExecEvalFuncArgs(FunctionCachePtr fcache, fcache->setArg = (char *) argV[0]; fcache->hasSetArg = true; } - if (argIsNull) - nullVect[i] = true; - else - nullVect[i] = false; i++; } } @@ -1108,7 +1101,7 @@ ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull) * ExecEvalCase * * Evaluate a CASE clause. Will have boolean expressions - * inside the WHEN clauses, and will have constants + * inside the WHEN clauses, and will have expressions * for results. * - thomas 1998-11-09 * ---------------------------------------------------------------- @@ -1118,7 +1111,6 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull) { List *clauses; List *clause; - CaseWhen *wclause; Datum const_value = 0; bool isDone; @@ -1127,17 +1119,16 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull) /* * 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. + * return the value of the default clause, or NULL if there is none. */ foreach(clause, clauses) { + CaseWhen *wclause = lfirst(clause); /* * We don't iterate over sets in the quals, so pass in an isDone * flag, but ignore it. */ - - wclause = lfirst(clause); const_value = ExecEvalExpr((Node *) wclause->expr, econtext, isNull, @@ -1145,16 +1136,16 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull) /* * if we have a true test, then we return the result, since the - * case statement is satisfied. + * case statement is satisfied. A NULL result from the test is + * not considered true. */ - if (DatumGetInt32(const_value) != 0) + if (DatumGetInt32(const_value) != 0 && ! *isNull) { const_value = ExecEvalExpr((Node *) wclause->result, econtext, isNull, &isDone); return (Datum) const_value; - } } @@ -1318,7 +1309,7 @@ ExecQualClause(Node *clause, ExprContext *econtext) bool isNull; bool isDone; - /* when there is a null clause, consider the qualification to be true */ + /* when there is a null clause, consider the qualification to fail */ if (clause == NULL) return true; @@ -1326,20 +1317,14 @@ ExecQualClause(Node *clause, ExprContext *econtext) * pass isDone, but ignore it. We don't iterate over multiple returns * in the qualifications. */ - expr_value = (Datum) - ExecEvalExpr(clause, econtext, &isNull, &isDone); + expr_value = ExecEvalExpr(clause, econtext, &isNull, &isDone); /* - * this is interesting behaviour here. When a clause evaluates to - * null, then we consider this as passing the qualification. it seems - * kind of like, if the qual is NULL, then there's no qual.. + * remember, we return true when the qualification fails; + * NULL is considered failure. */ if (isNull) return true; - - /* - * remember, we return true when the qualification fails.. - */ if (DatumGetInt32(expr_value) == 0) return true; -- GitLab