8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
* HISTORY
14
14
* AUTHOR DATE MAJOR EVENT
@@ -974,12 +974,13 @@ contain_nonstrict_functions_walker(Node *node, void *context)
974
974
* the expression to have been AND/OR flattened and converted to implicit-AND
975
975
* format.
976
976
*
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.
983
984
*/
984
985
Relids
985
986
find_nonnullable_rels (Node * clause )
@@ -991,6 +992,7 @@ static Relids
991
992
find_nonnullable_rels_walker (Node * node , bool top_level )
992
993
{
993
994
Relids result = NULL ;
995
+ ListCell * l ;
994
996
995
997
if (node == NULL )
996
998
return NULL ;
@@ -1003,8 +1005,15 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
1003
1005
}
1004
1006
else if (IsA (node , List ))
1005
1007
{
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
+ */
1008
1017
foreach (l , (List * ) node )
1009
1018
{
1010
1019
result = bms_join (result ,
@@ -1037,9 +1046,57 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
1037
1046
{
1038
1047
BoolExpr * expr = (BoolExpr * ) node ;
1039
1048
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
+ }
1043
1100
}
1044
1101
else if (IsA (node , RelabelType ))
1045
1102
{
@@ -1056,22 +1113,17 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
1056
1113
}
1057
1114
else if (IsA (node , NullTest ))
1058
1115
{
1116
+ /* IS NOT NULL can be considered strict, but only at top level */
1059
1117
NullTest * expr = (NullTest * ) node ;
1060
1118
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
- */
1065
1119
if (top_level && expr -> nulltesttype == IS_NOT_NULL )
1066
1120
result = find_nonnullable_rels_walker ((Node * ) expr -> arg , false);
1067
1121
}
1068
1122
else if (IsA (node , BooleanTest ))
1069
1123
{
1124
+ /* Boolean tests that reject NULL are strict at top level */
1070
1125
BooleanTest * expr = (BooleanTest * ) node ;
1071
1126
1072
- /*
1073
- * Appropriate boolean tests are strict at top level.
1074
- */
1075
1127
if (top_level &&
1076
1128
(expr -> booltesttype == IS_TRUE ||
1077
1129
expr -> booltesttype == IS_FALSE ||
0 commit comments