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.
This commit is contained in:
Tom Lane 1999-09-18 23:26:37 +00:00
parent f9f5dfbf10
commit e1a8b0f2ce
1 changed files with 16 additions and 31 deletions

View File

@ -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;