/* * predicate_refuted_by * Recursively checks whether the clauses in restrictinfo_list refute * the given predicate (that is, prove it false). * * This is NOT the same as !(predicate_implied_by), though it is similar * in the technique and structure of the code. * * An important fine point is that truth of the clauses must imply that * the predicate returns FALSE, not that it does not return TRUE. This * is normally used to try to refute CHECK constraints, and the only * thing we can assume about a CHECK constraint is that it didn't return * FALSE --- a NULL result isn't a violation per the SQL spec. (Someday * perhaps this code should be extended to support both "strong" and * "weak" refutation, but for now we only need "strong".) * * The top-level List structure of each list corresponds to an AND list. * We assume that eval_const_expressions() has been applied and so there * are no un-flattened ANDs or ORs (e.g., no AND immediately within an AND, * including AND just below the top-level List structure). * If this is not true we might fail to prove an implication that is * valid, but no worse consequences will ensue. * * We assume the predicate has already been checked to contain only * immutable functions and operators. We dare not make deductions based on * non-immutable functions, because they might change answers between the * time we make the plan and the time we execute the plan. */ bool predicate_refuted_by(List *predicate_list, List *restrictinfo_list) { Node *p, *r; if (predicate_list == NIL) return false; /* no predicate: no refutation is possible */ if (restrictinfo_list == NIL) return false; /* no restriction: refutation must fail */ /* * If either input is a single-element list, replace it with its lone * member; this avoids one useless level of AND-recursion. We only need * to worry about this at top level, since eval_const_expressions should * have gotten rid of any trivial ANDs or ORs below that. */ if (list_length(predicate_list) == 1) p = (Node *) linitial(predicate_list); else p = (Node *) predicate_list; if (list_length(restrictinfo_list) == 1) r = (Node *) linitial(restrictinfo_list); else r = (Node *) restrictinfo_list; /* And away we go ... */ return predicate_refuted_by_recurse(r, p); }
/* * predicate_refuted_by * Recursively checks whether the clauses in restrictinfo_list refute * the given predicate (that is, prove it false). * * This is NOT the same as !(predicate_implied_by), though it is similar * in the technique and structure of the code. * * An important fine point is that truth of the clauses must imply that * the predicate returns FALSE, not that it does not return TRUE. This * is normally used to try to refute CHECK constraints, and the only * thing we can assume about a CHECK constraint is that it didn't return * FALSE --- a NULL result isn't a violation per the SQL spec. (Someday * perhaps this code should be extended to support both "strong" and * "weak" refutation, but for now we only need "strong".) * * The top-level List structure of each list corresponds to an AND list. * We assume that eval_const_expressions() has been applied and so there * are no un-flattened ANDs or ORs (e.g., no AND immediately within an AND, * including AND just below the top-level List structure). * If this is not true we might fail to prove an implication that is * valid, but no worse consequences will ensue. * * We assume the predicate has already been checked to contain only * immutable functions and operators. We dare not make deductions based on * non-immutable functions, because they might change answers between the * time we make the plan and the time we execute the plan. */ bool predicate_refuted_by(List *predicate_list, List *restrictinfo_list) { if (predicate_list == NIL) return false; /* no predicate: no refutation is possible */ if (restrictinfo_list == NIL) return false; /* no restriction: refutation must fail */ /* Otherwise, away we go ... */ return predicate_refuted_by_recurse((Node *) restrictinfo_list, (Node *) predicate_list); }