88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.233 2007/02/02 00:02:55 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.234 2007/02/16 23:32:08 tgl Exp $
1212 *
1313 * HISTORY
1414 * AUTHOR DATE MAJOR EVENT
@@ -974,12 +974,13 @@ contain_nonstrict_functions_walker(Node *node, void *context)
974974 * the expression to have been AND/OR flattened and converted to implicit-AND
975975 * format.
976976 *
977- * We don't use expression_tree_walker here because we don't want to
978- * descend through very many kinds of nodes; only the ones we can be sure
979- * are strict. We can descend through the top level of implicit AND'ing,
980- * but not through any explicit ANDs (or ORs) below that, since those are not
981- * strict constructs. The List case handles the top-level implicit AND list
982- * as well as lists of arguments to strict operators/functions.
977+ * top_level is TRUE while scanning top-level AND/OR structure; here, showing
978+ * the result is either FALSE or NULL is good enough. top_level is FALSE when
979+ * we have descended below a NOT or a strict function: now we must be able to
980+ * prove that the subexpression goes to NULL.
981+ *
982+ * We don't use expression_tree_walker here because we don't want to descend
983+ * through very many kinds of nodes; only the ones we can be sure are strict.
983984 */
984985Relids
985986find_nonnullable_rels (Node * clause )
@@ -991,6 +992,7 @@ static Relids
991992find_nonnullable_rels_walker (Node * node , bool top_level )
992993{
993994 Relids result = NULL ;
995+ ListCell * l ;
994996
995997 if (node == NULL )
996998 return NULL ;
@@ -1003,8 +1005,15 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
10031005 }
10041006 else if (IsA (node , List ))
10051007 {
1006- ListCell * l ;
1007-
1008+ /*
1009+ * At top level, we are examining an implicit-AND list: if any of
1010+ * the arms produces FALSE-or-NULL then the result is FALSE-or-NULL.
1011+ * If not at top level, we are examining the arguments of a strict
1012+ * function: if any of them produce NULL then the result of the
1013+ * function must be NULL. So in both cases, the set of nonnullable
1014+ * rels is the union of those found in the arms, and we pass down
1015+ * the top_level flag unmodified.
1016+ */
10081017 foreach (l , (List * ) node )
10091018 {
10101019 result = bms_join (result ,
@@ -1037,9 +1046,57 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
10371046 {
10381047 BoolExpr * expr = (BoolExpr * ) node ;
10391048
1040- /* NOT is strict, others are not */
1041- if (expr -> boolop == NOT_EXPR )
1042- result = find_nonnullable_rels_walker ((Node * ) expr -> args , false);
1049+ switch (expr -> boolop )
1050+ {
1051+ case AND_EXPR :
1052+ /* At top level we can just recurse (to the List case) */
1053+ if (top_level )
1054+ {
1055+ result = find_nonnullable_rels_walker ((Node * ) expr -> args ,
1056+ top_level );
1057+ break ;
1058+ }
1059+ /*
1060+ * Below top level, even if one arm produces NULL, the result
1061+ * could be FALSE (hence not NULL). However, if *all* the
1062+ * arms produce NULL then the result is NULL, so we can
1063+ * take the intersection of the sets of nonnullable rels,
1064+ * just as for OR. Fall through to share code.
1065+ */
1066+ /* FALL THRU */
1067+ case OR_EXPR :
1068+ /*
1069+ * OR is strict if all of its arms are, so we can take the
1070+ * intersection of the sets of nonnullable rels for each arm.
1071+ * This works for both values of top_level.
1072+ */
1073+ foreach (l , expr -> args )
1074+ {
1075+ Relids subresult ;
1076+
1077+ subresult = find_nonnullable_rels_walker (lfirst (l ),
1078+ top_level );
1079+ if (result == NULL ) /* first subresult? */
1080+ result = subresult ;
1081+ else
1082+ result = bms_int_members (result , subresult );
1083+ /*
1084+ * If the intersection is empty, we can stop looking.
1085+ * This also justifies the test for first-subresult above.
1086+ */
1087+ if (bms_is_empty (result ))
1088+ break ;
1089+ }
1090+ break ;
1091+ case NOT_EXPR :
1092+ /* NOT will return null if its arg is null */
1093+ result = find_nonnullable_rels_walker ((Node * ) expr -> args ,
1094+ false);
1095+ break ;
1096+ default :
1097+ elog (ERROR , "unrecognized boolop: %d" , (int ) expr -> boolop );
1098+ break ;
1099+ }
10431100 }
10441101 else if (IsA (node , RelabelType ))
10451102 {
@@ -1056,22 +1113,17 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
10561113 }
10571114 else if (IsA (node , NullTest ))
10581115 {
1116+ /* IS NOT NULL can be considered strict, but only at top level */
10591117 NullTest * expr = (NullTest * ) node ;
10601118
1061- /*
1062- * IS NOT NULL can be considered strict, but only at top level; else
1063- * we might have something like NOT (x IS NOT NULL).
1064- */
10651119 if (top_level && expr -> nulltesttype == IS_NOT_NULL )
10661120 result = find_nonnullable_rels_walker ((Node * ) expr -> arg , false);
10671121 }
10681122 else if (IsA (node , BooleanTest ))
10691123 {
1124+ /* Boolean tests that reject NULL are strict at top level */
10701125 BooleanTest * expr = (BooleanTest * ) node ;
10711126
1072- /*
1073- * Appropriate boolean tests are strict at top level.
1074- */
10751127 if (top_level &&
10761128 (expr -> booltesttype == IS_TRUE ||
10771129 expr -> booltesttype == IS_FALSE ||
0 commit comments