99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.7 2006/07/14 14:52:21 momjian Exp $
12+ * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.8 2006/08/05 00:21:14 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -81,6 +81,7 @@ static Node *arrayexpr_next_fn(PredIterInfo info);
8181static void arrayexpr_cleanup_fn (PredIterInfo info );
8282static bool predicate_implied_by_simple_clause (Expr * predicate , Node * clause );
8383static bool predicate_refuted_by_simple_clause (Expr * predicate , Node * clause );
84+ static Node * extract_not_arg (Node * clause );
8485static bool btree_predicate_proof (Expr * predicate , Node * clause ,
8586 bool refute_it );
8687
@@ -393,6 +394,13 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
393394 * OR-expr A R=> AND-expr B iff: each of A's components R=> any of B's
394395 * OR-expr A R=> OR-expr B iff: A R=> each of B's components
395396 *
397+ * In addition, if the predicate is a NOT-clause then we can use
398+ * A R=> NOT B if: A => B
399+ * while if the restriction clause is a NOT-clause then we can use
400+ * NOT A R=> B if: B => A
401+ * This works for several different SQL constructs that assert the non-truth
402+ * of their argument, ie NOT, IS FALSE, IS NOT TRUE, IS UNKNOWN.
403+ *
396404 * Other comments are as for predicate_implied_by_recurse().
397405 *----------
398406 */
@@ -402,6 +410,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
402410 PredIterInfoData clause_info ;
403411 PredIterInfoData pred_info ;
404412 PredClass pclass ;
413+ Node * not_arg ;
405414 bool result ;
406415
407416 /* skip through RestrictInfo */
@@ -467,6 +476,13 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
467476 return result ;
468477
469478 case CLASS_ATOM :
479+ /*
480+ * If B is a NOT-clause, A R=> B if A => B's arg
481+ */
482+ not_arg = extract_not_arg (predicate );
483+ if (not_arg &&
484+ predicate_implied_by_recurse (clause , not_arg ))
485+ return true;
470486 /*
471487 * AND-clause R=> atom if any of A's items refutes B
472488 */
@@ -532,6 +548,13 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
532548 return result ;
533549
534550 case CLASS_ATOM :
551+ /*
552+ * If B is a NOT-clause, A R=> B if A => B's arg
553+ */
554+ not_arg = extract_not_arg (predicate );
555+ if (not_arg &&
556+ predicate_implied_by_recurse (clause , not_arg ))
557+ return true;
535558 /*
536559 * OR-clause R=> atom if each of A's items refutes B
537560 */
@@ -550,6 +573,13 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
550573 break ;
551574
552575 case CLASS_ATOM :
576+ /*
577+ * If A is a NOT-clause, A R=> B if B => A's arg
578+ */
579+ not_arg = extract_not_arg (clause );
580+ if (not_arg &&
581+ predicate_implied_by_recurse (predicate , not_arg ))
582+ return true;
553583 switch (pclass )
554584 {
555585 case CLASS_AND :
@@ -585,6 +615,13 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
585615 return result ;
586616
587617 case CLASS_ATOM :
618+ /*
619+ * If B is a NOT-clause, A R=> B if A => B's arg
620+ */
621+ not_arg = extract_not_arg (predicate );
622+ if (not_arg &&
623+ predicate_implied_by_recurse (clause , not_arg ))
624+ return true;
588625 /*
589626 * atom R=> atom is the base case
590627 */
@@ -917,8 +954,7 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
917954 * We return TRUE if able to prove the refutation, FALSE if not.
918955 *
919956 * Unlike the implication case, checking for equal() clauses isn't
920- * helpful. (XXX is it worth looking at "x vs NOT x" cases? Probably
921- * not seeing that canonicalization tries to get rid of NOTs.)
957+ * helpful.
922958 *
923959 * When the predicate is of the form "foo IS NULL", we can conclude that
924960 * the predicate is refuted if the clause is a strict operator or function
@@ -931,7 +967,12 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
931967static bool
932968predicate_refuted_by_simple_clause (Expr * predicate , Node * clause )
933969{
934- /* First try the IS NULL case */
970+ /* A simple clause can't refute itself */
971+ /* Worth checking because of relation_excluded_by_constraints() */
972+ if ((Node * ) predicate == clause )
973+ return false;
974+
975+ /* Try the IS NULL case */
935976 if (predicate && IsA (predicate , NullTest ) &&
936977 ((NullTest * ) predicate )-> nulltesttype == IS_NULL )
937978 {
@@ -953,6 +994,35 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
953994}
954995
955996
997+ /*
998+ * If clause asserts the non-truth of a subclause, return that subclause;
999+ * otherwise return NULL.
1000+ */
1001+ static Node *
1002+ extract_not_arg (Node * clause )
1003+ {
1004+ if (clause == NULL )
1005+ return NULL ;
1006+ if (IsA (clause , BoolExpr ))
1007+ {
1008+ BoolExpr * bexpr = (BoolExpr * ) clause ;
1009+
1010+ if (bexpr -> boolop == NOT_EXPR )
1011+ return (Node * ) linitial (bexpr -> args );
1012+ }
1013+ else if (IsA (clause , BooleanTest ))
1014+ {
1015+ BooleanTest * btest = (BooleanTest * ) clause ;
1016+
1017+ if (btest -> booltesttype == IS_NOT_TRUE ||
1018+ btest -> booltesttype == IS_FALSE ||
1019+ btest -> booltesttype == IS_UNKNOWN )
1020+ return (Node * ) btest -> arg ;
1021+ }
1022+ return NULL ;
1023+ }
1024+
1025+
9561026/*
9571027 * Define an "operator implication table" for btree operators ("strategies"),
9581028 * and a similar table for refutation.
0 commit comments