When testing usability of a partial index, recognize that an index
predicate of the form 'foo IS NOT NULL' is implied by a WHERE clause that uses 'foo' in any strict operator or function. Per suggestion and preliminary implementation by John Siracusa; some further hacking by moi.
This commit is contained in:
parent
5ae38167cf
commit
bc19d6641a
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -965,24 +965,38 @@ static const StrategyNumber
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*----------
|
||||||
* pred_test_simple_clause
|
* pred_test_simple_clause
|
||||||
* Does the "predicate inclusion test" for a "simple clause" predicate
|
* Does the "predicate inclusion test" for a "simple clause" predicate
|
||||||
* and a "simple clause" restriction.
|
* and a "simple clause" restriction.
|
||||||
*
|
*
|
||||||
* We have two strategies for determining whether one simple clause
|
* We have three strategies for determining whether one simple clause
|
||||||
* implies another. A simple and general way is to see if they are
|
* implies another:
|
||||||
* 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
|
* A simple and general way is to see if they are equal(); this works for any
|
||||||
* in some btree operator class. We use the above operator implication
|
* kind of expression. (Actually, there is an implied assumption that the
|
||||||
* table to be able to derive implications between nonidentical clauses.
|
* functions in the expression are immutable, ie dependent only on their input
|
||||||
|
* arguments --- but this was checked for the predicate by CheckPredicate().)
|
||||||
|
*
|
||||||
|
* 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.)
|
||||||
|
*
|
||||||
|
* 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
|
* Eventually, rtree operators could also be handled by defining an
|
||||||
* appropriate "RT_implic_table" array.
|
* appropriate "RT_implic_table" array.
|
||||||
|
*----------
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
pred_test_simple_clause(Expr *predicate, Node *clause)
|
pred_test_simple_clause(Expr *predicate, Node *clause)
|
||||||
@ -1020,6 +1034,23 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
|
|||||||
if (equal((Node *) predicate, clause))
|
if (equal((Node *) predicate, clause))
|
||||||
return true;
|
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
|
* Can't do anything more unless they are both binary opclauses with a
|
||||||
* Const on one side, and identical subexpressions on the other sides.
|
* Const on one side, and identical subexpressions on the other sides.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user