mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
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:
parent
f9f5dfbf10
commit
e1a8b0f2ce
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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)
|
bool *argIsDone)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
bool argIsNull,
|
bool *nullVect;
|
||||||
*nullVect;
|
|
||||||
List *arg;
|
List *arg;
|
||||||
|
|
||||||
nullVect = fcache->nullVect;
|
nullVect = fcache->nullVect;
|
||||||
@ -631,23 +630,17 @@ ExecEvalFuncArgs(FunctionCachePtr fcache,
|
|||||||
* as arguments but we make an exception in the case of nested dot
|
* as arguments but we make an exception in the case of nested dot
|
||||||
* expressions. We have to watch out for this case here.
|
* expressions. We have to watch out for this case here.
|
||||||
*/
|
*/
|
||||||
argV[i] = (Datum)
|
argV[i] = ExecEvalExpr((Node *) lfirst(arg),
|
||||||
ExecEvalExpr((Node *) lfirst(arg),
|
|
||||||
econtext,
|
econtext,
|
||||||
&argIsNull,
|
& nullVect[i],
|
||||||
argIsDone);
|
argIsDone);
|
||||||
|
|
||||||
|
|
||||||
if (!(*argIsDone))
|
if (!(*argIsDone))
|
||||||
{
|
{
|
||||||
Assert(i == 0);
|
Assert(i == 0);
|
||||||
fcache->setArg = (char *) argV[0];
|
fcache->setArg = (char *) argV[0];
|
||||||
fcache->hasSetArg = true;
|
fcache->hasSetArg = true;
|
||||||
}
|
}
|
||||||
if (argIsNull)
|
|
||||||
nullVect[i] = true;
|
|
||||||
else
|
|
||||||
nullVect[i] = false;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1108,7 +1101,7 @@ ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull)
|
|||||||
* ExecEvalCase
|
* ExecEvalCase
|
||||||
*
|
*
|
||||||
* Evaluate a CASE clause. Will have boolean expressions
|
* 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.
|
* for results.
|
||||||
* - thomas 1998-11-09
|
* - thomas 1998-11-09
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
@ -1118,7 +1111,6 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, bool *isNull)
|
|||||||
{
|
{
|
||||||
List *clauses;
|
List *clauses;
|
||||||
List *clause;
|
List *clause;
|
||||||
CaseWhen *wclause;
|
|
||||||
Datum const_value = 0;
|
Datum const_value = 0;
|
||||||
bool isDone;
|
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
|
* 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
|
* 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)
|
foreach(clause, clauses)
|
||||||
{
|
{
|
||||||
|
CaseWhen *wclause = lfirst(clause);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't iterate over sets in the quals, so pass in an isDone
|
* We don't iterate over sets in the quals, so pass in an isDone
|
||||||
* flag, but ignore it.
|
* flag, but ignore it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
wclause = lfirst(clause);
|
|
||||||
const_value = ExecEvalExpr((Node *) wclause->expr,
|
const_value = ExecEvalExpr((Node *) wclause->expr,
|
||||||
econtext,
|
econtext,
|
||||||
isNull,
|
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
|
* 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,
|
const_value = ExecEvalExpr((Node *) wclause->result,
|
||||||
econtext,
|
econtext,
|
||||||
isNull,
|
isNull,
|
||||||
&isDone);
|
&isDone);
|
||||||
return (Datum) const_value;
|
return (Datum) const_value;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1318,7 +1309,7 @@ ExecQualClause(Node *clause, ExprContext *econtext)
|
|||||||
bool isNull;
|
bool isNull;
|
||||||
bool isDone;
|
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)
|
if (clause == NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1326,20 +1317,14 @@ ExecQualClause(Node *clause, ExprContext *econtext)
|
|||||||
* pass isDone, but ignore it. We don't iterate over multiple returns
|
* pass isDone, but ignore it. We don't iterate over multiple returns
|
||||||
* in the qualifications.
|
* in the qualifications.
|
||||||
*/
|
*/
|
||||||
expr_value = (Datum)
|
expr_value = ExecEvalExpr(clause, econtext, &isNull, &isDone);
|
||||||
ExecEvalExpr(clause, econtext, &isNull, &isDone);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this is interesting behaviour here. When a clause evaluates to
|
* remember, we return true when the qualification fails;
|
||||||
* null, then we consider this as passing the qualification. it seems
|
* NULL is considered failure.
|
||||||
* kind of like, if the qual is NULL, then there's no qual..
|
|
||||||
*/
|
*/
|
||||||
if (isNull)
|
if (isNull)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
|
||||||
* remember, we return true when the qualification fails..
|
|
||||||
*/
|
|
||||||
if (DatumGetInt32(expr_value) == 0)
|
if (DatumGetInt32(expr_value) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user