aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/path/allpaths.c4
-rw-r--r--src/backend/optimizer/path/indxpath.c109
-rw-r--r--src/backend/optimizer/path/orindxpath.c29
-rw-r--r--src/include/optimizer/paths.h5
4 files changed, 86 insertions, 61 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index bdc1c033296..fb55139a1e1 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.75 2001/06/05 05:26:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.76 2001/06/05 17:13:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -232,7 +232,7 @@ set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte)
create_index_paths(root, rel);
/* create_index_paths must be done before create_or_index_paths */
- create_or_index_paths(root, rel, rel->baserestrictinfo);
+ create_or_index_paths(root, rel);
/* Now find the cheapest of the paths for this rel */
set_cheapest(rel);
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index a5f5bb151da..6a1fd6b50a4 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.105 2001/05/20 20:28:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.106 2001/06/05 17:13:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -397,7 +397,7 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
clause, false);
}
-/*
+/*----------
* Given an OR subclause that has previously been determined to match
* the specified index, extract a list of specific opclauses that can be
* used as indexquals.
@@ -406,10 +406,25 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
* given opclause. However, if the OR subclause is an AND, we have to
* scan it to find the opclause(s) that match the index. (There should
* be at least one, if match_or_subclause_to_indexkey succeeded, but there
- * could be more.) Also, we apply expand_indexqual_conditions() to convert
- * any special matching opclauses to indexable operators.
+ * could be more.)
+ *
+ * Also, we can look at other restriction clauses of the rel to discover
+ * additional candidate indexquals: for example, consider
+ * ... where (a = 11 or a = 12) and b = 42;
+ * If we are dealing with an index on (a,b) then we can include the clause
+ * b = 42 in the indexqual list generated for each of the OR subclauses.
+ * Essentially, we are making an index-specific transformation from CNF to
+ * DNF. (NOTE: when we do this, we end up with a slightly inefficient plan
+ * because create_indexscan_plan is not very bright about figuring out which
+ * restriction clauses are implied by the generated indexqual condition.
+ * Currently we'll end up rechecking both the OR clause and the transferred
+ * restriction clause as qpquals. FIXME someday.)
+ *
+ * Also, we apply expand_indexqual_conditions() to convert any special
+ * matching opclauses to indexable operators.
*
* The passed-in clause is not changed.
+ *----------
*/
List *
extract_or_indexqual_conditions(RelOptInfo *rel,
@@ -417,54 +432,72 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
Expr *orsubclause)
{
List *quals = NIL;
+ int *indexkeys = index->indexkeys;
+ Oid *classes = index->classlist;
- if (and_clause((Node *) orsubclause))
+ /*
+ * Extract relevant indexclauses in indexkey order. This is essentially
+ * just like group_clauses_by_indexkey() except that the input and
+ * output are lists of bare clauses, not of RestrictInfo nodes.
+ */
+ do
{
+ int curIndxKey = indexkeys[0];
+ Oid curClass = classes[0];
+ List *clausegroup = NIL;
+ List *item;
- /*
- * Extract relevant sub-subclauses in indexkey order. This is
- * just like group_clauses_by_indexkey() except that the input and
- * output are lists of bare clauses, not of RestrictInfo nodes.
- */
- int *indexkeys = index->indexkeys;
- Oid *classes = index->classlist;
+ if (and_clause((Node *) orsubclause))
+ {
+ foreach(item, orsubclause->args)
+ {
+ Expr *subsubclause = (Expr *) lfirst(item);
- do
+ if (match_clause_to_indexkey(rel, index,
+ curIndxKey, curClass,
+ subsubclause, false))
+ clausegroup = lappend(clausegroup, subsubclause);
+ }
+ }
+ else if (match_clause_to_indexkey(rel, index,
+ curIndxKey, curClass,
+ orsubclause, false))
{
- int curIndxKey = indexkeys[0];
- Oid curClass = classes[0];
- List *clausegroup = NIL;
- List *item;
+ clausegroup = makeList1(orsubclause);
+ }
- foreach(item, orsubclause->args)
+ /*
+ * If we found no clauses for this indexkey in the OR subclause
+ * itself, try looking in the rel's top-level restriction list.
+ */
+ if (clausegroup == NIL)
+ {
+ foreach(item, rel->baserestrictinfo)
{
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
+
if (match_clause_to_indexkey(rel, index,
curIndxKey, curClass,
- lfirst(item), false))
- clausegroup = lappend(clausegroup, lfirst(item));
+ rinfo->clause, false))
+ clausegroup = lappend(clausegroup, rinfo->clause);
}
+ }
- /*
- * If no clauses match this key, we're done; we don't want to
- * look at keys to its right.
- */
- if (clausegroup == NIL)
- break;
+ /*
+ * If still no clauses match this key, we're done; we don't want to
+ * look at keys to its right.
+ */
+ if (clausegroup == NIL)
+ break;
- quals = nconc(quals, clausegroup);
+ quals = nconc(quals, clausegroup);
- indexkeys++;
- classes++;
- } while (!DoneMatchingIndexKeys(indexkeys, index));
+ indexkeys++;
+ classes++;
+ } while (!DoneMatchingIndexKeys(indexkeys, index));
- if (quals == NIL)
- elog(ERROR, "extract_or_indexqual_conditions: no matching clause");
- }
- else
- {
- /* we assume the caller passed a valid indexable qual */
- quals = makeList1(orsubclause);
- }
+ if (quals == NIL)
+ elog(ERROR, "extract_or_indexqual_conditions: no matching clause");
return expand_indexqual_conditions(quals);
}
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c
index 25cbc3e4fa2..889a3afee12 100644
--- a/src/backend/optimizer/path/orindxpath.c
+++ b/src/backend/optimizer/path/orindxpath.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.43 2001/05/20 20:28:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.44 2001/06/05 17:13:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,20 +38,17 @@ static void best_or_subclause_index(Query *root, RelOptInfo *rel,
* create_index_paths() must already have been called.
*
* 'rel' is the relation entry for which the paths are to be created
- * 'clauses' is the list of available restriction clause nodes
*
* Returns nothing, but adds paths to rel->pathlist via add_path().
*/
void
-create_or_index_paths(Query *root,
- RelOptInfo *rel,
- List *clauses)
+create_or_index_paths(Query *root, RelOptInfo *rel)
{
- List *clist;
+ List *rlist;
- foreach(clist, clauses)
+ foreach(rlist, rel->baserestrictinfo)
{
- RestrictInfo *clausenode = (RestrictInfo *) lfirst(clist);
+ RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(rlist);
/*
* Check to see if this clause is an 'or' clause, and, if so,
@@ -59,13 +56,13 @@ create_or_index_paths(Query *root,
* has been matched by an index. The information used was saved
* by create_index_paths().
*/
- if (restriction_is_or_clause(clausenode) &&
- clausenode->subclauseindices)
+ if (restriction_is_or_clause(restrictinfo) &&
+ restrictinfo->subclauseindices)
{
bool all_indexable = true;
List *temp;
- foreach(temp, clausenode->subclauseindices)
+ foreach(temp, restrictinfo->subclauseindices)
{
if (lfirst(temp) == NIL)
{
@@ -75,7 +72,6 @@ create_or_index_paths(Query *root,
}
if (all_indexable)
{
-
/*
* OK, build an IndexPath for this OR clause, using the
* best available index for each subclause.
@@ -93,10 +89,7 @@ create_or_index_paths(Query *root,
*/
pathnode->path.pathkeys = NIL;
- /*
- * We don't actually care what order the index scans in
- * ...
- */
+ /* We don't actually care what order the index scans in. */
pathnode->indexscandir = NoMovementScanDirection;
/* This isn't a nestloop innerjoin, so: */
@@ -106,8 +99,8 @@ create_or_index_paths(Query *root,
best_or_subclause_indices(root,
rel,
- clausenode->clause->args,
- clausenode->subclauseindices,
+ restrictinfo->clause->args,
+ restrictinfo->subclauseindices,
pathnode);
add_path(rel, (Path *) pathnode);
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 39afe74d2ad..f676e61d1f7 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: paths.h,v 1.53 2001/05/20 20:28:20 tgl Exp $
+ * $Id: paths.h,v 1.54 2001/06/05 17:13:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,8 +47,7 @@ extern List *expand_indexqual_conditions(List *indexquals);
* orindxpath.c
* additional routines for indexable OR clauses
*/
-extern void create_or_index_paths(Query *root, RelOptInfo *rel,
- List *clauses);
+extern void create_or_index_paths(Query *root, RelOptInfo *rel);
/*
* tidpath.h