7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -1283,12 +1283,33 @@ ExecEvalExpr(Node *expression,
1283
1283
/* ----------------------------------------------------------------
1284
1284
*ExecQual
1285
1285
*
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
+ *
1288
1309
* ----------------------------------------------------------------
1289
1310
*/
1290
1311
bool
1291
- ExecQual (List * qual ,ExprContext * econtext )
1312
+ ExecQual (List * qual ,ExprContext * econtext , bool resultForNull )
1292
1313
{
1293
1314
List * qlist ;
1294
1315
@@ -1302,37 +1323,48 @@ ExecQual(List *qual, ExprContext *econtext)
1302
1323
IncrProcessed ();
1303
1324
1304
1325
/*
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.
1308
1331
*
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.
1316
1336
*/
1337
+
1317
1338
foreach (qlist ,qual )
1318
1339
{
1319
1340
Node * clause = (Node * )lfirst (qlist );
1320
1341
Datum expr_value ;
1321
1342
bool isNull ;
1322
1343
bool isDone ;
1323
1344
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
+ */
1325
1350
if (clause == NULL )
1326
1351
return false;
1327
1352
/*
1328
1353
* pass isDone, but ignore it.We don't iterate over multiple returns
1329
1354
* in the qualifications.
1330
1355
*/
1331
1356
expr_value = ExecEvalExpr (clause ,econtext ,& isNull ,& isDone );
1357
+
1332
1358
if (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
+ }
1336
1368
}
1337
1369
1338
1370
return true;