Teach predtest.c that "foo" implies "foo IS NOT NULL".
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 1 Aug 2015 18:31:46 +0000 (14:31 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 1 Aug 2015 18:31:59 +0000 (14:31 -0400)
Per complaint from Peter Holzer.  It's useful to cover this special case,
since for a boolean variable "foo", earlier parts of the planner will have
reduced variants like "foo = true" to just "foo", and thus we may fail
to recognize the applicability of a partial index with predicate
"foo IS NOT NULL".

Back-patch to 9.5, but not further; given the lack of previous complaints
this doesn't seem like behavior to change in stable branches.

src/backend/optimizer/util/predtest.c

index d9e49d127e1a0a0cc2308a8b48479d68e75f6e91..7e86ca974be27ba59f00e366bcaa9a9fa4c2e358 100644 (file)
@@ -1028,6 +1028,8 @@ arrayexpr_cleanup_fn(PredIterInfo info)
  * "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.)
+ * Also, if the clause is just "foo" (meaning it's a boolean variable),
+ * the predicate is implied since the clause can't be true if "foo" is NULL.
  *
  * Finally, if both clauses are binary operator expressions, we may be able
  * to prove something using the system's knowledge about operators; those
@@ -1061,6 +1063,8 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause)
                list_member_strip(((FuncExpr *) clause)->args, nonnullarg) &&
                func_strict(((FuncExpr *) clause)->funcid))
                return true;
+           if (equal(clause, nonnullarg))
+               return true;
        }
        return false;           /* we can't succeed below... */
    }