aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/orindxpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/orindxpath.c')
-rw-r--r--src/backend/optimizer/path/orindxpath.c89
1 files changed, 38 insertions, 51 deletions
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c
index 39fa69cdef8..450b8d7b2dc 100644
--- a/src/backend/optimizer/path/orindxpath.c
+++ b/src/backend/optimizer/path/orindxpath.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.30 1999/07/25 23:07:24 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.31 1999/07/27 03:51:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,11 +28,13 @@
static void best_or_subclause_indices(Query *root, RelOptInfo *rel,
List *subclauses, List *indices,
+ List **indexquals,
List **indexids,
Cost *cost, Cost *selec);
static void best_or_subclause_index(Query *root, RelOptInfo *rel,
- Expr *subclause, List *indices,
- int *indexid, Cost *cost, Cost *selec);
+ List *indexqual, List *indices,
+ int *retIndexid,
+ Cost *retCost, Cost *retSelec);
/*
@@ -84,8 +86,8 @@ create_or_index_paths(Query *root,
* best available index for each subclause.
*/
IndexPath *pathnode = makeNode(IndexPath);
+ List *indexquals;
List *indexids;
- List *orclause;
Cost cost;
Cost selec;
@@ -93,6 +95,7 @@ create_or_index_paths(Query *root,
rel,
clausenode->clause->args,
clausenode->indexids,
+ &indexquals,
&indexids,
&cost,
&selec);
@@ -111,43 +114,11 @@ create_or_index_paths(Query *root,
pathnode->path.pathorder->ord.sortop = NULL;
pathnode->path.pathkeys = NIL;
- /*
- * Generate an indexqual list from the OR clause's args.
- * We want two levels of sublist: the first is implicit OR
- * and the second is implicit AND. (Currently, we will never
- * see a sub-AND-clause because of cnfify(), but someday maybe
- * the code below will do something useful...)
- */
- pathnode->indexqual = NIL;
- foreach(orclause, clausenode->clause->args)
- {
- Expr *subclause = (Expr *) lfirst(orclause);
- List *sublist;
-
- if (and_clause((Node *) subclause))
- sublist = subclause->args;
- else
- sublist = lcons(subclause, NIL);
- /* expansion call... */
- pathnode->indexqual = lappend(pathnode->indexqual,
- sublist);
- }
+ pathnode->indexqual = indexquals;
pathnode->indexid = indexids;
pathnode->path.path_cost = cost;
clausenode->selectivity = (Cost) selec;
- /*
- * copy restrictinfo list into path for expensive function
- * processing -- JMH, 7/7/92
- */
- pathnode->path.loc_restrictinfo = set_difference(copyObject((Node *) rel->restrictinfo),
- lcons(clausenode, NIL));
-
-#ifdef NOT_USED /* fix xfunc */
- /* add in cost for expensive functions! -- JMH, 7/7/92 */
- if (XfuncMode != XFUNC_OFF)
- ((Path *) pathnode)->path_cost += xfunc_get_path_cost((Path) pathnode);
-#endif
path_list = lappend(path_list, pathnode);
}
}
@@ -163,11 +134,21 @@ create_or_index_paths(Query *root,
* indices. The cost is the sum of the individual index costs, since
* the executor will perform a scan for each subclause of the 'or'.
*
+ * This routine also creates the indexquals and indexids lists that will
+ * be needed by the executor. The indexquals list has one entry for each
+ * scan of the base rel, which is a sublist of indexqual conditions to
+ * apply in that scan. The implicit semantics are AND across each sublist
+ * of quals, and OR across the toplevel list (note that the executor
+ * takes care not to return any single tuple more than once). The indexids
+ * list gives the index to be used in each scan.
+ *
* 'rel' is the node of the relation on which the indexes are defined
* 'subclauses' are the subclauses of the 'or' clause
* 'indices' is a list of sublists of the index nodes that matched each
* subclause of the 'or' clause
- * '*indexids' gets a list of the best index ID to use for each subclause
+ * '*indexquals' gets the constructed indexquals for the path (a list
+ * of sublists of clauses, one sublist per scan of the base rel)
+ * '*indexids' gets a list of the index IDs for each scan of the rel
* '*cost' gets the total cost of the path
* '*selec' gets the total selectivity of the path.
*/
@@ -176,27 +157,41 @@ best_or_subclause_indices(Query *root,
RelOptInfo *rel,
List *subclauses,
List *indices,
+ List **indexquals, /* return value */
List **indexids, /* return value */
Cost *cost, /* return value */
Cost *selec) /* return value */
{
List *slist;
+ *indexquals = NIL;
*indexids = NIL;
- *selec = (Cost) 0.0;
*cost = (Cost) 0.0;
+ *selec = (Cost) 0.0;
foreach(slist, subclauses)
{
+ Expr *subclause = lfirst(slist);
+ List *indexqual;
int best_indexid;
Cost best_cost;
Cost best_selec;
- best_or_subclause_index(root, rel, lfirst(slist), lfirst(indices),
+ /* Convert this 'or' subclause to an indexqual list */
+ indexqual = make_ands_implicit(subclause);
+ /* expand special operators to indexquals the executor can handle */
+ indexqual = expand_indexqual_conditions(indexqual);
+
+ best_or_subclause_index(root, rel, indexqual, lfirst(indices),
&best_indexid, &best_cost, &best_selec);
+ *indexquals = lappend(*indexquals, indexqual);
*indexids = lappendi(*indexids, best_indexid);
*cost += best_cost;
+ /* We approximate the selectivity as the sum of the clause
+ * selectivities (but not more than 1).
+ * XXX This is too pessimistic, isn't it?
+ */
*selec += best_selec;
if (*selec > (Cost) 1.0)
*selec = (Cost) 1.0;
@@ -212,7 +207,7 @@ best_or_subclause_indices(Query *root,
* the least expensive.
*
* 'rel' is the node of the relation on which the index is defined
- * 'subclause' is the subclause
+ * 'indexqual' is the indexqual list derived from the subclause
* 'indices' is a list of index nodes that match the subclause
* '*retIndexid' gets the ID of the best index
* '*retCost' gets the cost of a scan with that index
@@ -221,14 +216,13 @@ best_or_subclause_indices(Query *root,
static void
best_or_subclause_index(Query *root,
RelOptInfo *rel,
- Expr *subclause,
+ List *indexqual,
List *indices,
int *retIndexid, /* return value */
Cost *retCost, /* return value */
Cost *retSelec) /* return value */
{
bool first_run = true;
- List *indexquals;
List *ilist;
/* if we don't match anything, return zeros */
@@ -236,13 +230,6 @@ best_or_subclause_index(Query *root,
*retCost = (Cost) 0.0;
*retSelec = (Cost) 0.0;
- /* convert 'or' subclause to an indexqual list */
- if (and_clause((Node *) subclause))
- indexquals = subclause->args;
- else
- indexquals = lcons(subclause, NIL);
- /* expansion call... */
-
foreach(ilist, indices)
{
RelOptInfo *index = (RelOptInfo *) lfirst(ilist);
@@ -254,7 +241,7 @@ best_or_subclause_index(Query *root,
index_selectivity(root,
lfirsti(rel->relids),
indexid,
- indexquals,
+ indexqual,
&npages,
&selec);