|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * IDENTIFICATION
|
12 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.15 2007/05/12 19:22:35 tgl Exp $ |
| 12 | + * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.16 2007/07/24 17:22:07 tgl Exp $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -84,6 +84,7 @@ static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause);
|
84 | 84 | static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause);
|
85 | 85 | static bool is_null_contradicts(NullTest *ntest, Node *clause);
|
86 | 86 | static Node *extract_not_arg(Node *clause);
|
| 87 | +static bool list_member_strip(List *list, Expr *datum); |
87 | 88 | static bool btree_predicate_proof(Expr *predicate, Node *clause,
|
88 | 89 | bool refute_it);
|
89 | 90 |
|
@@ -961,11 +962,11 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
|
961 | 962 | if (!type_is_rowtype(exprType((Node *) nonnullarg)))
|
962 | 963 | {
|
963 | 964 | if (is_opclause(clause) &&
|
964 |
| - list_member(((OpExpr *) clause)->args, nonnullarg) && |
| 965 | + list_member_strip(((OpExpr *) clause)->args, nonnullarg) && |
965 | 966 | op_strict(((OpExpr *) clause)->opno))
|
966 | 967 | return true;
|
967 | 968 | if (is_funcclause(clause) &&
|
968 |
| - list_member(((FuncExpr *) clause)->args, nonnullarg) && |
| 969 | + list_member_strip(((FuncExpr *) clause)->args, nonnullarg) && |
969 | 970 | func_strict(((FuncExpr *) clause)->funcid))
|
970 | 971 | return true;
|
971 | 972 | }
|
@@ -1044,11 +1045,11 @@ is_null_contradicts(NullTest *ntest, Node *clause)
|
1044 | 1045 |
|
1045 | 1046 | /* foo IS NULL contradicts any strict op/func on foo */
|
1046 | 1047 | if (is_opclause(clause) &&
|
1047 |
| - list_member(((OpExpr *) clause)->args, isnullarg) && |
| 1048 | + list_member_strip(((OpExpr *) clause)->args, isnullarg) && |
1048 | 1049 | op_strict(((OpExpr *) clause)->opno))
|
1049 | 1050 | return true;
|
1050 | 1051 | if (is_funcclause(clause) &&
|
1051 |
| - list_member(((FuncExpr *) clause)->args, isnullarg) && |
| 1052 | + list_member_strip(((FuncExpr *) clause)->args, isnullarg) && |
1052 | 1053 | func_strict(((FuncExpr *) clause)->funcid))
|
1053 | 1054 | return true;
|
1054 | 1055 |
|
@@ -1091,6 +1092,36 @@ extract_not_arg(Node *clause)
|
1091 | 1092 | }
|
1092 | 1093 |
|
1093 | 1094 |
|
| 1095 | +/* |
| 1096 | + * Check whether an Expr is equal() to any member of a list, ignoring |
| 1097 | + * any top-level RelabelType nodes. This is legitimate for the purposes |
| 1098 | + * we use it for (matching IS [NOT] NULL arguments to arguments of strict |
| 1099 | + * functions) because RelabelType doesn't change null-ness. It's helpful |
| 1100 | + * for cases such as a varchar argument of a strict function on text. |
| 1101 | + */ |
| 1102 | +static bool |
| 1103 | +list_member_strip(List *list, Expr *datum) |
| 1104 | +{ |
| 1105 | + ListCell *cell; |
| 1106 | + |
| 1107 | + if (datum && IsA(datum, RelabelType)) |
| 1108 | + datum = ((RelabelType *) datum)->arg; |
| 1109 | + |
| 1110 | + foreach(cell, list) |
| 1111 | + { |
| 1112 | + Expr *elem = (Expr *) lfirst(cell); |
| 1113 | + |
| 1114 | + if (elem && IsA(elem, RelabelType)) |
| 1115 | + elem = ((RelabelType *) elem)->arg; |
| 1116 | + |
| 1117 | + if (equal(elem, datum)) |
| 1118 | + return true; |
| 1119 | + } |
| 1120 | + |
| 1121 | + return false; |
| 1122 | +} |
| 1123 | + |
| 1124 | + |
1094 | 1125 | /*
|
1095 | 1126 | * Define an "operator implication table" for btree operators ("strategies"),
|
1096 | 1127 | * and a similar table for refutation.
|
|
0 commit comments