*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.156 2004/01/07 22:02:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.157 2004/03/07 05:43:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
};
-/*
+/*----------
* pred_test_simple_clause
* Does the "predicate inclusion test" for a "simple clause" predicate
* and a "simple clause" restriction.
*
- * We have two strategies for determining whether one simple clause
- * implies another. A simple and general way is to see if they are
- * equal(); this works for any kind of expression. (Actually, there
- * is an implied assumption that the functions in the expression are
- * immutable, ie dependent only on their input arguments --- but this
- * was checked for the predicate by CheckPredicate().)
+ * We have three strategies for determining whether one simple clause
+ * implies another:
+ *
+ * A simple and general way is to see if they are equal(); this works for any
+ * kind of expression. (Actually, there is an implied assumption that the
+ * functions in the expression are immutable, ie dependent only on their input
+ * arguments --- but this was checked for the predicate by CheckPredicate().)
*
- * Our other way works only for (binary boolean) operators that are
- * in some btree operator class. We use the above operator implication
- * table to be able to derive implications between nonidentical clauses.
+ * When the predicate is of the form "foo IS NOT NULL", we can conclude that
+ * the predicate is implied if the clause is a strict operator or function
+ * that has "foo" as an input. In this case the clause must yield NULL when
+ * "foo" is NULL, which we can take as equivalent to FALSE because we know
+ * we are within an AND/OR subtree of a WHERE clause. (Again, "foo" is
+ * already known immutable, so the clause will certainly always fail.)
*
- * Eventually, rtree operators could also be handled by defining an
- * appropriate "RT_implic_table" array.
+ * Our other way works only for binary boolean opclauses of the form
+ * "foo op constant", where "foo" is the same in both clauses. The operators
+ * and constants can be different but the operators must be in the same btree
+ * operator class. We use the above operator implication table to be able to
+ * derive implications between nonidentical clauses. (Note: "foo" is known
+ * immutable, and constants are surely immutable, and we assume that operators
+ * that are in btree opclasses are immutable, so there's no need to do extra
+ * mutability checks in this case either.)
+ *
+ * Eventually, rtree operators could also be handled by defining an
+ * appropriate "RT_implic_table" array.
+ *----------
*/
static bool
pred_test_simple_clause(Expr *predicate, Node *clause)
if (equal((Node *) predicate, clause))
return true;
+ /* Next try the IS NOT NULL case */
+ if (predicate && IsA(predicate, NullTest) &&
+ ((NullTest *) predicate)->nulltesttype == IS_NOT_NULL)
+ {
+ Expr *nonnullarg = ((NullTest *) predicate)->arg;
+
+ if (is_opclause(clause) &&
+ member(nonnullarg, ((OpExpr *) clause)->args) &&
+ op_strict(((OpExpr *) clause)->opno))
+ return true;
+ if (is_funcclause(clause) &&
+ member(nonnullarg, ((FuncExpr *) clause)->args) &&
+ func_strict(((FuncExpr *) clause)->funcid))
+ return true;
+ return false; /* we can't succeed below... */
+ }
+
/*
* Can't do anything more unless they are both binary opclauses with a
* Const on one side, and identical subexpressions on the other sides.