aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/indxpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/indxpath.c')
-rw-r--r--src/backend/optimizer/path/indxpath.c84
1 files changed, 44 insertions, 40 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 4c2b0109bc0..edb16ce0d6d 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.79 2000/02/05 18:26:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.80 2000/02/15 20:49:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -83,7 +83,8 @@ static List *index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index,
static bool useful_for_mergejoin(RelOptInfo *rel, IndexOptInfo *index,
List *joininfo_list);
static bool useful_for_ordering(Query *root, RelOptInfo *rel,
- IndexOptInfo *index);
+ IndexOptInfo *index,
+ ScanDirection scandir);
static bool match_index_to_operand(int indexkey, Var *operand,
RelOptInfo *rel, IndexOptInfo *index);
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel,
@@ -106,6 +107,8 @@ static bool string_lessthan(const char * str1, const char * str2,
/*
* create_index_paths()
* Generate all interesting index paths for the given relation.
+ * Candidate paths are added to the rel's pathlist (using add_path).
+ * Additional IndexPath nodes may also be added to rel's innerjoin list.
*
* To be considered for an index scan, an index must match one or more
* restriction clauses or join clauses from the query's qual condition,
@@ -120,29 +123,26 @@ static bool string_lessthan(const char * str1, const char * str2,
* in its join clauses. In that context, values for the other rels'
* attributes are available and fixed during any one scan of the indexpath.
*
- * This routine's return value is a list of plain IndexPaths for each
- * index the routine deems potentially interesting for the current query
+ * An IndexPath is generated and submitted to add_path() for each index
+ * this routine deems potentially interesting for the current query
* (at most one IndexPath per index on the given relation). An innerjoin
* path is also generated for each interesting combination of outer join
- * relations. The innerjoin paths are *not* in the return list, but are
- * appended to the "innerjoin" list of the relation itself.
+ * relations. The innerjoin paths are *not* passed to add_path(), but are
+ * appended to the "innerjoin" list of the relation for later consideration
+ * in nested-loop joins.
*
* 'rel' is the relation for which we want to generate index paths
* 'indices' is a list of available indexes for 'rel'
* 'restrictinfo_list' is a list of restrictinfo nodes for 'rel'
* 'joininfo_list' is a list of joininfo nodes for 'rel'
- *
- * Returns a list of IndexPath access path descriptors. Additional
- * IndexPath nodes may also be added to the rel->innerjoin list.
*/
-List *
+void
create_index_paths(Query *root,
RelOptInfo *rel,
List *indices,
List *restrictinfo_list,
List *joininfo_list)
{
- List *retval = NIL;
List *ilist;
foreach(ilist, indices)
@@ -189,9 +189,9 @@ create_index_paths(Query *root,
restrictinfo_list);
if (restrictclauses != NIL)
- retval = lappend(retval,
- create_index_path(root, rel, index,
- restrictclauses));
+ add_path(rel, (Path *) create_index_path(root, rel, index,
+ restrictclauses,
+ NoMovementScanDirection));
/*
* 3. If this index can be used for a mergejoin, then create an
@@ -205,10 +205,22 @@ create_index_paths(Query *root,
if (restrictclauses == NIL)
{
if (useful_for_mergejoin(rel, index, joininfo_list) ||
- useful_for_ordering(root, rel, index))
- retval = lappend(retval,
- create_index_path(root, rel, index, NIL));
+ useful_for_ordering(root, rel, index, ForwardScanDirection))
+ add_path(rel, (Path *)
+ create_index_path(root, rel, index,
+ NIL,
+ ForwardScanDirection));
}
+ /*
+ * Currently, backwards scan is never considered except for the case
+ * of matching a query result ordering. Possibly should consider
+ * it in other places?
+ */
+ if (useful_for_ordering(root, rel, index, BackwardScanDirection))
+ add_path(rel, (Path *)
+ create_index_path(root, rel, index,
+ NIL,
+ BackwardScanDirection));
/*
* 4. Create an innerjoin index path for each combination of
@@ -231,8 +243,6 @@ create_index_paths(Query *root,
joinouterrelids));
}
}
-
- return retval;
}
@@ -892,39 +902,26 @@ useful_for_mergejoin(RelOptInfo *rel,
* Determine whether the given index can produce an ordering matching
* the order that is wanted for the query result.
*
- * We check to see whether either forward or backward scan direction can
- * match the specified pathkeys.
- *
* 'rel' is the relation for which 'index' is defined
+ * 'scandir' is the contemplated scan direction
*/
static bool
useful_for_ordering(Query *root,
RelOptInfo *rel,
- IndexOptInfo *index)
+ IndexOptInfo *index,
+ ScanDirection scandir)
{
List *index_pathkeys;
if (root->query_pathkeys == NIL)
return false; /* no special ordering requested */
- index_pathkeys = build_index_pathkeys(root, rel, index);
+ index_pathkeys = build_index_pathkeys(root, rel, index, scandir);
if (index_pathkeys == NIL)
return false; /* unordered index */
- if (pathkeys_contained_in(root->query_pathkeys, index_pathkeys))
- return true;
-
- /* caution: commute_pathkeys destructively modifies its argument;
- * safe because we just built the index_pathkeys for local use here.
- */
- if (commute_pathkeys(index_pathkeys))
- {
- if (pathkeys_contained_in(root->query_pathkeys, index_pathkeys))
- return true; /* useful as a reverse-order path */
- }
-
- return false;
+ return pathkeys_contained_in(root->query_pathkeys, index_pathkeys);
}
/****************************************************************************
@@ -1433,7 +1430,12 @@ index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index,
pathnode->path.pathtype = T_IndexScan;
pathnode->path.parent = rel;
- pathnode->path.pathkeys = build_index_pathkeys(root, rel, index);
+ /*
+ * There's no point in marking the path with any pathkeys, since
+ * it will only ever be used as the inner path of a nestloop,
+ * and so its ordering does not matter.
+ */
+ pathnode->path.pathkeys = NIL;
indexquals = get_actual_clauses(clausegroup);
/* expand special operators to indexquals the executor can handle */
@@ -1446,11 +1448,13 @@ index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index,
pathnode->indexid = lconsi(index->indexoid, NIL);
pathnode->indexqual = lcons(indexquals, NIL);
+ /* We don't actually care what order the index scans in ... */
+ pathnode->indexscandir = NoMovementScanDirection;
+
/* joinrelids saves the rels needed on the outer side of the join */
pathnode->joinrelids = lfirst(outerrelids_list);
- pathnode->path.path_cost = cost_index(root, rel, index, indexquals,
- true);
+ cost_index(&pathnode->path, root, rel, index, indexquals, true);
path_list = lappend(path_list, pathnode);
outerrelids_list = lnext(outerrelids_list);