Commit 4e89bae7 authored by Tom Lane's avatar Tom Lane

Revert the logic for expanding AND/OR conditions in pred_test() to what

it was in 7.4, and add some comments explaining why it has to be this way.
I broke it for OR'd index predicates in a fit of code cleanup last summer.
Per example from Sergey Koshcheyev.
parent 5c4a91c2
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.167 2004/12/31 22:00:04 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.168 2005/03/01 00:24:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -64,9 +64,9 @@ static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index, ...@@ -64,9 +64,9 @@ static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
RestrictInfo *rinfo); RestrictInfo *rinfo);
static Oid indexable_operator(Expr *clause, Oid opclass, static Oid indexable_operator(Expr *clause, Oid opclass,
bool indexkey_on_left); bool indexkey_on_left);
static bool pred_test_recurse_pred(Expr *predicate, List *restrictinfo_list);
static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list); static bool pred_test_restrict_list(Expr *predicate, List *restrictinfo_list);
static bool pred_test_recurse_restrict(Expr *predicate, Node *clause); static bool pred_test_recurse_restrict(Expr *predicate, Node *clause);
static bool pred_test_recurse_pred(Expr *predicate, Node *clause);
static bool pred_test_simple_clause(Expr *predicate, Node *clause); static bool pred_test_simple_clause(Expr *predicate, Node *clause);
static Relids indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index); static Relids indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index);
static Path *make_innerjoin_index_path(Query *root, static Path *make_innerjoin_index_path(Query *root,
...@@ -749,11 +749,25 @@ check_partial_indexes(Query *root, RelOptInfo *rel) ...@@ -749,11 +749,25 @@ check_partial_indexes(Query *root, RelOptInfo *rel)
* Recursively checks whether the clauses in restrictinfo_list imply * Recursively checks whether the clauses in restrictinfo_list imply
* that the given predicate is true. * that the given predicate is true.
* *
* This routine (together with the routines it calls) first breaks down * This routine (together with the routines it calls) iterates over
* the predicate to its constituent AND/OR elements, then similarly * ANDs in the predicate first, then breaks down the restriction list
* breaks down the restriction clauses to AND/OR elements in an effort * to its constituent AND/OR elements, and iterates over ORs
* to prove that each predicate element is implied. The top-level * in the predicate last. This order is important to make the test
* List structure of each list corresponds to an AND list. * succeed whenever possible. --Nels, Jan '93
*
* For example, a restriction (a OR b) certainly implies a predicate
* (a OR b OR c), but no one element of the predicate is individually
* implied by the restriction. By expanding the predicate ORs last
* we are able to prove that the whole predicate is implied by each arm
* of the restriction. Conversely consider predicate (a AND b) with
* restriction (a AND b AND c). This should be implied but we will
* fail to prove it if we dissect the restriction first.
*
* The top-level List structure of each list corresponds to an AND list.
* We assume that canonicalize_qual() has been applied and so there
* are no explicit ANDs immediately below the top-level List structure.
* (If this is not true we might fail to prove an implication that is
* valid, but no worse consequences will ensue.)
*/ */
bool bool
pred_test(List *predicate_list, List *restrictinfo_list) pred_test(List *predicate_list, List *restrictinfo_list)
...@@ -779,65 +793,23 @@ pred_test(List *predicate_list, List *restrictinfo_list) ...@@ -779,65 +793,23 @@ pred_test(List *predicate_list, List *restrictinfo_list)
return false; /* no restriction clauses: the test must return false; /* no restriction clauses: the test must
* fail */ * fail */
/* Take care of the AND semantics of the top-level predicate list */
foreach(pred, predicate_list) foreach(pred, predicate_list)
{ {
/* /*
* if any clause is not implied, the whole predicate is not * if any clause is not implied, the whole predicate is not
* implied. * implied.
*/ */
if (!pred_test_recurse_pred(lfirst(pred), restrictinfo_list)) if (!pred_test_restrict_list(lfirst(pred), restrictinfo_list))
return false; return false;
} }
return true; return true;
} }
/*
* pred_test_recurse_pred
* Does the "predicate inclusion test" for one conjunct of a predicate
* expression. Here we recursively deal with the possibility that the
* predicate conjunct is itself an AND or OR structure.
*/
static bool
pred_test_recurse_pred(Expr *predicate, List *restrictinfo_list)
{
List *items;
ListCell *item;
Assert(predicate != NULL);
if (or_clause((Node *) predicate))
{
items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/* if any item is implied, the whole predicate is implied */
if (pred_test_recurse_pred(lfirst(item), restrictinfo_list))
return true;
}
return false;
}
else if (and_clause((Node *) predicate))
{
items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/*
* if any item is not implied, the whole predicate is not
* implied
*/
if (!pred_test_recurse_pred(lfirst(item), restrictinfo_list))
return false;
}
return true;
}
else
return pred_test_restrict_list(predicate, restrictinfo_list);
}
/* /*
* pred_test_restrict_list * pred_test_restrict_list
* Does the "predicate inclusion test" for one element of a predicate * Does the "predicate inclusion test" for one AND clause of a predicate
* expression. Here we take care of the AND semantics of the top-level * expression. Here we take care of the AND semantics of the top-level
* restrictinfo list. * restrictinfo list.
*/ */
...@@ -859,10 +831,10 @@ pred_test_restrict_list(Expr *predicate, List *restrictinfo_list) ...@@ -859,10 +831,10 @@ pred_test_restrict_list(Expr *predicate, List *restrictinfo_list)
/* /*
* pred_test_recurse_restrict * pred_test_recurse_restrict
* Does the "predicate inclusion test" for one element of a predicate * Does the "predicate inclusion test" for one AND clause of a predicate
* expression. Here we recursively deal with the possibility that the * expression. Here we recursively deal with the possibility that the
* restriction-list element is itself an AND or OR structure; also, * restriction-list element is itself an AND or OR structure; also,
* we strip off RestrictInfo nodes to find bare predicate expressions. * we strip off RestrictInfo nodes to find bare qualifier expressions.
*/ */
static bool static bool
pred_test_recurse_restrict(Expr *predicate, Node *clause) pred_test_recurse_restrict(Expr *predicate, Node *clause)
...@@ -903,6 +875,49 @@ pred_test_recurse_restrict(Expr *predicate, Node *clause) ...@@ -903,6 +875,49 @@ pred_test_recurse_restrict(Expr *predicate, Node *clause)
} }
return false; return false;
} }
else
return pred_test_recurse_pred(predicate, clause);
}
/*
* pred_test_recurse_pred
* Does the "predicate inclusion test" for one conjunct of a predicate
* expression. Here we recursively deal with the possibility that the
* predicate conjunct is itself an AND or OR structure.
*/
static bool
pred_test_recurse_pred(Expr *predicate, Node *clause)
{
List *items;
ListCell *item;
Assert(predicate != NULL);
if (or_clause((Node *) predicate))
{
items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/* if any item is implied, the whole predicate is implied */
if (pred_test_recurse_pred(lfirst(item), clause))
return true;
}
return false;
}
else if (and_clause((Node *) predicate))
{
items = ((BoolExpr *) predicate)->args;
foreach(item, items)
{
/*
* if any item is not implied, the whole predicate is not
* implied
*/
if (!pred_test_recurse_pred(lfirst(item), clause))
return false;
}
return true;
}
else else
return pred_test_simple_clause(predicate, clause); return pred_test_simple_clause(predicate, clause);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment