77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.65 2000/01/10 17:14:34 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.66 2000/01/19 23:54:54 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -1283,12 +1283,33 @@ ExecEvalExpr(Node *expression,
12831283/* ----------------------------------------------------------------
12841284 *ExecQual
12851285 *
1286- *Evaluates a conjunctive boolean expression and returns t
1287- *iff none of the subexpressions are false (or null).
1286+ *Evaluates a conjunctive boolean expression (qual list) and
1287+ *returns true iff none of the subexpressions are false.
1288+ *(We also return true if the list is empty.)
1289+ *
1290+ *If some of the subexpressions yield NULL but none yield FALSE,
1291+ *then the result of the conjunction is NULL (ie, unknown)
1292+ *according to three-valued boolean logic. In this case,
1293+ *we return the value specified by the "resultForNull" parameter.
1294+ *
1295+ *Callers evaluating WHERE clauses should pass resultForNull=FALSE,
1296+ *since SQL specifies that tuples with null WHERE results do not
1297+ *get selected. On the other hand, callers evaluating constraint
1298+ *conditions should pass resultForNull=TRUE, since SQL also specifies
1299+ *that NULL constraint conditions are not failures.
1300+ *
1301+ *NOTE: it would not be correct to use this routine to evaluate an
1302+ *AND subclause of a boolean expression; for that purpose, a NULL
1303+ *result must be returned as NULL so that it can be properly treated
1304+ *in the next higher operator (cf. ExecEvalAnd and ExecEvalOr).
1305+ *This routine is only used in contexts where a complete expression
1306+ *is being evaluated and we know that NULL can be treated the same
1307+ *as one boolean result or the other.
1308+ *
12881309 * ----------------------------------------------------------------
12891310 */
12901311bool
1291- ExecQual (List * qual ,ExprContext * econtext )
1312+ ExecQual (List * qual ,ExprContext * econtext , bool resultForNull )
12921313{
12931314List * qlist ;
12941315
@@ -1302,37 +1323,48 @@ ExecQual(List *qual, ExprContext *econtext)
13021323IncrProcessed ();
13031324
13041325/*
1305- * a "qual" is a list of clauses. To evaluate the qual, we evaluate
1306- * each of the clauses in the list. (For an empty list, we'll return
1307- * TRUE.)
1326+ * Evaluate the qual conditions one at a time. If we find a FALSE
1327+ * result, we can stop evaluating and return FALSE --- the AND result
1328+ * must be FALSE. Also, if we find a NULL result when resultForNull
1329+ * is FALSE, we can stop and return FALSE --- the AND result must be
1330+ * FALSE or NULL in that case, and the caller doesn't care which.
13081331 *
1309- * If any of the clauses return NULL, we treat this as FALSE. This
1310- * is correct per the SQL spec: if any ANDed conditions are NULL, then
1311- * the AND result is either FALSE or NULL, and in either case the
1312- * WHERE condition fails. NOTE: it would NOT be correct to use this
1313- * simplified logic in a sub-clause; ExecEvalAnd must do the full
1314- * three-state condition evaluation. We can get away with simpler
1315- * logic here because we know how the result will be used.
1332+ * If we get to the end of the list, we can return TRUE. This will
1333+ * happen when the AND result is indeed TRUE, or when the AND result
1334+ * is NULL (one or more NULL subresult, with all the rest TRUE) and
1335+ * the caller has specified resultForNull = TRUE.
13161336 */
1337+
13171338foreach (qlist ,qual )
13181339{
13191340Node * clause = (Node * )lfirst (qlist );
13201341Datum expr_value ;
13211342bool isNull ;
13221343bool isDone ;
13231344
1324- /* if there is a null clause, consider the qualification to fail */
1345+ /*
1346+ * If there is a null clause, consider the qualification to fail.
1347+ * XXX is this still correct for constraints? It probably shouldn't
1348+ * happen at all ...
1349+ */
13251350if (clause == NULL )
13261351return false;
13271352/*
13281353 * pass isDone, but ignore it.We don't iterate over multiple returns
13291354 * in the qualifications.
13301355 */
13311356expr_value = ExecEvalExpr (clause ,econtext ,& isNull ,& isDone );
1357+
13321358if (isNull )
1333- return false;/* treat NULL as FALSE */
1334- if (DatumGetInt32 (expr_value )== 0 )
1335- return false;
1359+ {
1360+ if (resultForNull == false)
1361+ return false;/* treat NULL as FALSE */
1362+ }
1363+ else
1364+ {
1365+ if (DatumGetInt32 (expr_value )== 0 )
1366+ return false;/* definitely FALSE */
1367+ }
13361368}
13371369
13381370return true;