99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.14 2007/03/17 00:11:04 tgl Exp $
12+ * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.15 2007/05/12 19:22:35 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -82,6 +82,7 @@ static Node *arrayexpr_next_fn(PredIterInfo info);
8282static void arrayexpr_cleanup_fn (PredIterInfo info );
8383static bool predicate_implied_by_simple_clause (Expr * predicate ,Node * clause );
8484static bool predicate_refuted_by_simple_clause (Expr * predicate ,Node * clause );
85+ static bool is_null_contradicts (NullTest * ntest ,Node * clause );
8586static Node * extract_not_arg (Node * clause );
8687static bool btree_predicate_proof (Expr * predicate ,Node * clause ,
8788bool refute_it );
@@ -987,7 +988,10 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
987988 *
988989 * When the predicate is of the form "foo IS NULL", we can conclude that
989990 * the predicate is refuted if the clause is a strict operator or function
990- * that has "foo" as an input.See notes for implication case.
991+ * that has "foo" as an input (see notes for implication case), or if the
992+ * clause is "foo IS NOT NULL". Conversely a clause "foo IS NULL" refutes
993+ * predicates of those types. (The motivation for covering these cases is
994+ * to support using IS NULL/IS NOT NULL as partition-defining constraints.)
991995 *
992996 * Finally, we may be able to deduce something using knowledge about btree
993997 * operator families; this is encapsulated in btree_predicate_proof().
@@ -1001,24 +1005,21 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
10011005if ((Node * )predicate == clause )
10021006return false;
10031007
1004- /* Try theIS NULL case */
1008+ /* Try thepredicate-IS- NULL case */
10051009if (predicate && IsA (predicate ,NullTest )&&
10061010((NullTest * )predicate )-> nulltesttype == IS_NULL )
10071011{
1008- Expr * isnullarg = ((NullTest * )predicate )-> arg ;
1012+ if (is_null_contradicts ((NullTest * )predicate ,clause ))
1013+ return true;
1014+ return false;/* we can't succeed below... */
1015+ }
10091016
1010- /* row IS NULL does not act in the simple way we have in mind */
1011- if (!type_is_rowtype (exprType ((Node * )isnullarg )))
1012- {
1013- if (is_opclause (clause )&&
1014- list_member (((OpExpr * )clause )-> args ,isnullarg )&&
1015- op_strict (((OpExpr * )clause )-> opno ))
1016- return true;
1017- if (is_funcclause (clause )&&
1018- list_member (((FuncExpr * )clause )-> args ,isnullarg )&&
1019- func_strict (((FuncExpr * )clause )-> funcid ))
1020- return true;
1021- }
1017+ /* Try the clause-IS-NULL case */
1018+ if (clause && IsA (clause ,NullTest )&&
1019+ ((NullTest * )clause )-> nulltesttype == IS_NULL )
1020+ {
1021+ if (is_null_contradicts ((NullTest * )clause , (Node * )predicate ))
1022+ return true;
10221023return false;/* we can't succeed below... */
10231024}
10241025
@@ -1027,6 +1028,40 @@ predicate_refuted_by_simple_clause(Expr *predicate, Node *clause)
10271028}
10281029
10291030
1031+ /*
1032+ * Check whether a "foo IS NULL" test contradicts clause. (We say
1033+ * "contradicts" rather than "refutes" because the refutation goes
1034+ * both ways.)
1035+ */
1036+ static bool
1037+ is_null_contradicts (NullTest * ntest ,Node * clause )
1038+ {
1039+ Expr * isnullarg = ntest -> arg ;
1040+
1041+ /* row IS NULL does not act in the simple way we have in mind */
1042+ if (type_is_rowtype (exprType ((Node * )isnullarg )))
1043+ return false;
1044+
1045+ /* foo IS NULL contradicts any strict op/func on foo */
1046+ if (is_opclause (clause )&&
1047+ list_member (((OpExpr * )clause )-> args ,isnullarg )&&
1048+ op_strict (((OpExpr * )clause )-> opno ))
1049+ return true;
1050+ if (is_funcclause (clause )&&
1051+ list_member (((FuncExpr * )clause )-> args ,isnullarg )&&
1052+ func_strict (((FuncExpr * )clause )-> funcid ))
1053+ return true;
1054+
1055+ /* foo IS NULL contradicts foo IS NOT NULL */
1056+ if (clause && IsA (clause ,NullTest )&&
1057+ ((NullTest * )clause )-> nulltesttype == IS_NOT_NULL &&
1058+ equal (((NullTest * )clause )-> arg ,isnullarg ))
1059+ return true;
1060+
1061+ return false;
1062+ }
1063+
1064+
10301065/*
10311066 * If clause asserts the non-truth of a subclause, return that subclause;
10321067 * otherwise return NULL.