*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.164 2004/08/29 05:06:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.165 2004/10/11 22:56:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
RestrictInfo *rinfo);
static Oid indexable_operator(Expr *clause, Oid opclass,
bool indexkey_on_left);
-static bool pred_test(List *predicate_list, List *restrictinfo_list);
+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_recurse_clause(Expr *predicate, Node *clause);
-static bool pred_test_recurse_pred(Expr *predicate, Node *clause);
+static bool pred_test_recurse_restrict(Expr *predicate, Node *clause);
static bool pred_test_simple_clause(Expr *predicate, Node *clause);
static Relids indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index);
static Path *make_innerjoin_index_path(Query *root,
* Recursively checks whether the clauses in restrictinfo_list imply
* that the given predicate is true.
*
- * This routine (together with the routines it calls) iterates over
- * ANDs in the predicate first, then reduces the qualification
- * clauses down to their constituent terms, and iterates over ORs
- * in the predicate last. This order is important to make the test
- * succeed whenever possible (assuming the predicate has been converted
- * to CNF format). --Nels, Jan '93
+ * This routine (together with the routines it calls) first breaks down
+ * the predicate to its constituent AND/OR elements, then similarly
+ * breaks down the restriction clauses to AND/OR elements in an effort
+ * to prove that each predicate element is implied. The top-level
+ * List structure of each list corresponds to an AND list.
*/
-static bool
+bool
pred_test(List *predicate_list, List *restrictinfo_list)
{
ListCell *pred;
{
/*
* if any clause is not implied, the whole predicate is not
- * implied. Note we assume that any sub-ANDs have been flattened
- * when the predicate was fed through canonicalize_qual().
+ * implied.
*/
- if (!pred_test_restrict_list(lfirst(pred), restrictinfo_list))
+ if (!pred_test_recurse_pred(lfirst(pred), restrictinfo_list))
return false;
}
return true;
/*
- * pred_test_restrict_list
+ * pred_test_recurse_pred
* Does the "predicate inclusion test" for one conjunct of a predicate
- * expression.
+ * 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
+ * Does the "predicate inclusion test" for one element of a predicate
+ * expression. Here we take care of the AND semantics of the top-level
+ * restrictinfo list.
*/
static bool
pred_test_restrict_list(Expr *predicate, List *restrictinfo_list)
{
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(item);
+ Assert(IsA(restrictinfo, RestrictInfo));
+
/* if any clause implies the predicate, return true */
- if (pred_test_recurse_clause(predicate,
- (Node *) restrictinfo->clause))
+ if (pred_test_recurse_restrict(predicate,
+ (Node *) restrictinfo->clause))
return true;
}
return false;
/*
- * pred_test_recurse_clause
- * Does the "predicate inclusion test" for a general restriction-clause
+ * pred_test_recurse_restrict
+ * Does the "predicate inclusion test" for one element of a predicate
* expression. Here we recursively deal with the possibility that the
- * restriction clause is itself an AND or OR structure.
+ * restriction-list element is itself an AND or OR structure.
*/
static bool
-pred_test_recurse_clause(Expr *predicate, Node *clause)
+pred_test_recurse_restrict(Expr *predicate, Node *clause)
{
List *items;
ListCell *item;
foreach(item, items)
{
/* if any OR item doesn't imply the predicate, clause doesn't */
- if (!pred_test_recurse_clause(predicate, lfirst(item)))
+ if (!pred_test_recurse_restrict(predicate, lfirst(item)))
return false;
}
return true;
* if any AND item implies the predicate, the whole clause
* does
*/
- if (pred_test_recurse_clause(predicate, lfirst(item)))
+ if (pred_test_recurse_restrict(predicate, lfirst(item)))
return true;
}
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 for a simple restriction clause. 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
return pred_test_simple_clause(predicate, clause);
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.62 2004/08/29 05:06:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.63 2004/10/11 22:56:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
List *indexquals;
Path subclause_path;
- /* Ignore partial indexes that do not match the query */
+ /*
+ * Ignore partial indexes that do not match the query. If predOK
+ * is true then the index's predicate is implied by top-level
+ * restriction clauses, so we can use it. However, it might also
+ * be implied by the current OR subclause (perhaps in conjunction
+ * with the top-level clauses), in which case we can use it for this
+ * particular scan.
+ *
+ * XXX this code is partially redundant with logic in
+ * group_clauses_by_indexkey_for_or(); consider refactoring.
+ */
if (index->indpred != NIL && !index->predOK)
- continue;
+ {
+ List *subclauserinfos;
+
+ if (and_clause((Node *) subclause))
+ subclauserinfos = list_copy(((BoolExpr *) subclause)->args);
+ else if (IsA(subclause, RestrictInfo))
+ subclauserinfos = list_make1(subclause);
+ else
+ continue; /* probably can't happen */
+ if (!pred_test(index->indpred,
+ list_concat(subclauserinfos,
+ rel->baserestrictinfo)))
+ continue;
+ }
/* Collect index clauses usable with this index */
indexclauses = group_clauses_by_indexkey_for_or(rel, index, subclause);
- /* Ignore index if it doesn't match the subclause at all */
- if (indexclauses == NIL)
+ /*
+ * Ignore index if it doesn't match the subclause at all; except
+ * that if it's a partial index, consider it anyway, since the
+ * selectivity of the predicate alone might make the index useful.
+ */
+ if (indexclauses == NIL && index->indpred == NIL)
continue;
/* Convert clauses to indexquals the executor can handle */