|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * IDENTIFICATION
|
12 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.31 2010/02/14 18:42:15 rhaas Exp $ |
| 12 | + * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.32 2010/02/25 20:59:53 tgl Exp $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -95,6 +95,7 @@ static void arrayexpr_cleanup_fn(PredIterInfo info);
|
95 | 95 | static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause);
|
96 | 96 | static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause);
|
97 | 97 | static Node *extract_not_arg(Node *clause);
|
| 98 | +static Node *extract_strong_not_arg(Node *clause); |
98 | 99 | static bool list_member_strip(List *list, Expr *datum);
|
99 | 100 | static bool btree_predicate_proof(Expr *predicate, Node *clause,
|
100 | 101 | bool refute_it);
|
@@ -468,6 +469,8 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
468 | 469 | * Unfortunately we *cannot* use
|
469 | 470 | * NOT A R=> B if: B => A
|
470 | 471 | * because this type of reasoning fails to prove that B doesn't yield NULL.
|
| 472 | + * We can however make the more limited deduction that |
| 473 | + * NOT A R=> A |
471 | 474 | *
|
472 | 475 | * Other comments are as for predicate_implied_by_recurse().
|
473 | 476 | *----------
|
@@ -651,21 +654,18 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
651 | 654 |
|
652 | 655 | case CLASS_ATOM:
|
653 | 656 |
|
654 |
| -#ifdef NOT_USED |
655 |
| - |
656 | 657 | /*
|
657 |
| - * If A is a NOT-clause, A R=> B if B => A's arg |
| 658 | + * If A is a strong NOT-clause, A R=> B if B equals A's arg |
658 | 659 | *
|
659 |
| - * Unfortunately not: this would only prove that B is not-TRUE, |
660 |
| - * not that it's not NULL either. Keep this code as a comment |
661 |
| - * because it would be useful if we ever had a need for the weak |
662 |
| - * form of refutation. |
| 660 | + * We cannot make the stronger conclusion that B is refuted if |
| 661 | + * B implies A's arg; that would only prove that B is not-TRUE, |
| 662 | + * not that it's not NULL either. Hence use equal() rather than |
| 663 | + * predicate_implied_by_recurse(). We could do the latter if we |
| 664 | + * ever had a need for the weak form of refutation. |
663 | 665 | */
|
664 |
| - not_arg = extract_not_arg(clause); |
665 |
| - if (not_arg && |
666 |
| - predicate_implied_by_recurse(predicate, not_arg)) |
| 666 | + not_arg = extract_strong_not_arg(clause); |
| 667 | + if (not_arg && equal(predicate, not_arg)) |
667 | 668 | return true;
|
668 |
| -#endif |
669 | 669 |
|
670 | 670 | switch (pclass)
|
671 | 671 | {
|
@@ -1178,6 +1178,32 @@ extract_not_arg(Node *clause)
|
1178 | 1178 | return NULL;
|
1179 | 1179 | }
|
1180 | 1180 |
|
| 1181 | +/* |
| 1182 | + * If clause asserts the falsity of a subclause, return that subclause; |
| 1183 | + * otherwise return NULL. |
| 1184 | + */ |
| 1185 | +static Node * |
| 1186 | +extract_strong_not_arg(Node *clause) |
| 1187 | +{ |
| 1188 | + if (clause == NULL) |
| 1189 | + return NULL; |
| 1190 | + if (IsA(clause, BoolExpr)) |
| 1191 | + { |
| 1192 | + BoolExpr *bexpr = (BoolExpr *) clause; |
| 1193 | + |
| 1194 | + if (bexpr->boolop == NOT_EXPR) |
| 1195 | + return (Node *) linitial(bexpr->args); |
| 1196 | + } |
| 1197 | + else if (IsA(clause, BooleanTest)) |
| 1198 | + { |
| 1199 | + BooleanTest *btest = (BooleanTest *) clause; |
| 1200 | + |
| 1201 | + if (btest->booltesttype == IS_FALSE) |
| 1202 | + return (Node *) btest->arg; |
| 1203 | + } |
| 1204 | + return NULL; |
| 1205 | +} |
| 1206 | + |
1181 | 1207 |
|
1182 | 1208 | /*
|
1183 | 1209 | * Check whether an Expr is equal() to any member of a list, ignoring
|
|
0 commit comments