*** pgsql/src/backend/optimizer/util/predtest.c 2009/05/11 17:56:22 1.10.2.5 --- pgsql/src/backend/optimizer/util/predtest.c 2010/02/25 21:00:15 1.10.2.6 *************** *** 9,15 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.10.2.4 2008/11/12 23:08:50 tgl Exp $ * *------------------------------------------------------------------------- */ --- 9,15 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.10.2.5 2009/05/11 17:56:22 tgl Exp $ * *------------------------------------------------------------------------- */ *************** static void arrayexpr_cleanup_fn(PredIte *** 93,98 **** --- 93,99 ---- static bool predicate_implied_by_simple_clause(Expr *predicate, Node *clause); static bool predicate_refuted_by_simple_clause(Expr *predicate, Node *clause); static Node *extract_not_arg(Node *clause); + static Node *extract_strong_not_arg(Node *clause); static bool list_member_strip(List *list, Expr *datum); static bool btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it); *************** predicate_implied_by_recurse(Node *claus *** 430,435 **** --- 431,438 ---- * Unfortunately we *cannot* use * NOT A R=> B if: B => A * because this type of reasoning fails to prove that B doesn't yield NULL. + * We can however make the more limited deduction that + * NOT A R=> A * * Other comments are as for predicate_implied_by_recurse(). *---------- *************** predicate_refuted_by_recurse(Node *claus *** 613,632 **** case CLASS_ATOM: - #ifdef NOT_USED /* ! * If A is a NOT-clause, A R=> B if B => A's arg * ! * Unfortunately not: this would only prove that B is not-TRUE, ! * not that it's not NULL either. Keep this code as a comment ! * because it would be useful if we ever had a need for the ! * weak form of refutation. */ ! not_arg = extract_not_arg(clause); ! if (not_arg && ! predicate_implied_by_recurse(predicate, not_arg)) return true; - #endif switch (pclass) { --- 616,633 ---- case CLASS_ATOM: /* ! * If A is a strong NOT-clause, A R=> B if B equals A's arg * ! * We cannot make the stronger conclusion that B is refuted if ! * B implies A's arg; that would only prove that B is not-TRUE, ! * not that it's not NULL either. Hence use equal() rather than ! * predicate_implied_by_recurse(). We could do the latter if we ! * ever had a need for the weak form of refutation. */ ! not_arg = extract_strong_not_arg(clause); ! if (not_arg && equal(predicate, not_arg)) return true; switch (pclass) { *************** extract_not_arg(Node *clause) *** 1134,1139 **** --- 1135,1166 ---- return (Node *) btest->arg; } return NULL; + } + + /* + * If clause asserts the falsity of a subclause, return that subclause; + * otherwise return NULL. + */ + static Node * + extract_strong_not_arg(Node *clause) + { + if (clause == NULL) + return NULL; + if (IsA(clause, BoolExpr)) + { + BoolExpr *bexpr = (BoolExpr *) clause; + + if (bexpr->boolop == NOT_EXPR) + return (Node *) linitial(bexpr->args); + } + else if (IsA(clause, BooleanTest)) + { + BooleanTest *btest = (BooleanTest *) clause; + + if (btest->booltesttype == IS_FALSE) + return (Node *) btest->arg; + } + return NULL; }