aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r--src/backend/optimizer/util/pathnode.c123
-rw-r--r--src/backend/optimizer/util/plancat.c475
-rw-r--r--src/backend/optimizer/util/relnode.c16
3 files changed, 235 insertions, 379 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 0f9bf1b8bbb..a2551391e00 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.55 1999/11/23 20:07:00 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.56 2000/01/09 00:26:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -15,8 +15,6 @@
#include "postgres.h"
-
-
#include "optimizer/cost.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
@@ -37,10 +35,7 @@
bool
path_is_cheaper(Path *path1, Path *path2)
{
- Cost cost1 = path1->path_cost;
- Cost cost2 = path2->path_cost;
-
- return (bool) (cost1 < cost2);
+ return (bool) (path1->path_cost < path2->path_cost);
}
/*
@@ -60,8 +55,8 @@ set_cheapest(RelOptInfo *parent_rel, List *pathlist)
List *p;
Path *cheapest_so_far;
- Assert(pathlist != NIL);
Assert(IsA(parent_rel, RelOptInfo));
+ Assert(pathlist != NIL);
cheapest_so_far = (Path *) lfirst(pathlist);
@@ -192,18 +187,11 @@ Path *
create_seqscan_path(RelOptInfo *rel)
{
Path *pathnode = makeNode(Path);
- int relid = 0;
pathnode->pathtype = T_SeqScan;
pathnode->parent = rel;
- pathnode->path_cost = 0.0;
pathnode->pathkeys = NIL; /* seqscan has unordered result */
-
- if (rel->relids != NIL) /* can this happen? */
- relid = lfirsti(rel->relids);
-
- pathnode->path_cost = cost_seqscan(relid,
- rel->pages, rel->tuples);
+ pathnode->path_cost = cost_seqscan(rel);
return pathnode;
}
@@ -222,7 +210,7 @@ create_seqscan_path(RelOptInfo *rel)
IndexPath *
create_index_path(Query *root,
RelOptInfo *rel,
- RelOptInfo *index,
+ IndexOptInfo *index,
List *restriction_clauses)
{
IndexPath *pathnode = makeNode(IndexPath);
@@ -239,8 +227,7 @@ create_index_path(Query *root,
* conditions. If we do have restriction conditions to use, they
* will get inserted below.
*/
- Assert(length(index->relids) == 1);
- pathnode->indexid = index->relids;
+ pathnode->indexid = lconsi(index->indexoid, NIL);
pathnode->indexqual = lcons(NIL, NIL);
pathnode->joinrelids = NIL; /* no join clauses here */
@@ -250,13 +237,9 @@ create_index_path(Query *root,
* We have no restriction clauses, so compute scan cost using
* selectivity of 1.0.
*/
- pathnode->path.path_cost = cost_index(lfirsti(index->relids),
+ pathnode->path.path_cost = cost_index(rel, index,
index->pages,
- 1.0,
- rel->pages,
- rel->tuples,
- index->pages,
- index->tuples,
+ (Selectivity) 1.0,
false);
}
else
@@ -266,9 +249,8 @@ create_index_path(Query *root,
* restriction clause(s). Also, place indexqual in path node.
*/
List *indexquals;
- float npages;
- float selec;
- Cost clausesel;
+ long npages;
+ Selectivity selec;
indexquals = get_actual_clauses(restriction_clauses);
/* expand special operators to indexquals the executor can handle */
@@ -280,39 +262,15 @@ create_index_path(Query *root,
lfirst(pathnode->indexqual) = indexquals;
index_selectivity(root,
- lfirsti(rel->relids),
- lfirsti(index->relids),
+ rel,
+ index,
indexquals,
&npages,
&selec);
- pathnode->path.path_cost = cost_index(lfirsti(index->relids),
- (int) npages,
- selec,
- rel->pages,
- rel->tuples,
- index->pages,
- index->tuples,
+ pathnode->path.path_cost = cost_index(rel, index,
+ npages, selec,
false);
-
- /*
- * Set selectivities of clauses used with index to the selectivity
- * of this index, subdividing the selectivity equally over each of
- * the clauses. To the extent that index_selectivity() can make a
- * better estimate of the joint selectivity of these clauses than
- * the product of individual estimates from compute_clause_selec()
- * would be, this should give us a more accurate estimate of the
- * total selectivity of all the clauses.
- *
- * XXX If there is more than one useful index for this rel, and the
- * indexes can be used with different but overlapping groups of
- * restriction clauses, we may end up with too optimistic an estimate,
- * since set_clause_selectivities() will save the minimum of the
- * per-clause selectivity estimated with each index. But that should
- * be fairly unlikely for typical index usage.
- */
- clausesel = pow(selec, 1.0 / (double) length(restriction_clauses));
- set_clause_selectivities(restriction_clauses, clausesel);
}
return pathnode;
@@ -331,14 +289,12 @@ create_tidscan_path(RelOptInfo *rel, List *tideval)
pathnode->path.pathtype = T_TidScan;
pathnode->path.parent = rel;
- pathnode->path.path_cost = 0.0;
pathnode->path.pathkeys = NIL;
-
- pathnode->path.path_cost = cost_tidscan(tideval);
+ pathnode->path.path_cost = cost_tidscan(rel, tideval);
/* divide selectivity for each clause to get an equal selectivity
* as IndexScan does OK ?
*/
- pathnode->tideval = copyObject(tideval);
+ pathnode->tideval = copyObject(tideval); /* is copy really necessary? */
pathnode->unjoined_relids = NIL;
return pathnode;
@@ -350,7 +306,6 @@ create_tidscan_path(RelOptInfo *rel, List *tideval)
* relations.
*
* 'joinrel' is the join relation.
- * 'outer_rel' is the outer join relation
* 'outer_path' is the outer path
* 'inner_path' is the inner path
* 'pathkeys' are the path keys of the new join path
@@ -360,7 +315,6 @@ create_tidscan_path(RelOptInfo *rel, List *tideval)
*/
NestPath *
create_nestloop_path(RelOptInfo *joinrel,
- RelOptInfo *outer_rel,
Path *outer_path,
Path *inner_path,
List *pathkeys)
@@ -371,15 +325,10 @@ create_nestloop_path(RelOptInfo *joinrel,
pathnode->path.parent = joinrel;
pathnode->outerjoinpath = outer_path;
pathnode->innerjoinpath = inner_path;
- pathnode->pathinfo = joinrel->restrictinfo;
pathnode->path.pathkeys = pathkeys;
- pathnode->path.path_cost = cost_nestloop(outer_path->path_cost,
- inner_path->path_cost,
- outer_rel->size,
- inner_path->parent->size,
- page_size(outer_rel->size,
- outer_rel->width),
+ pathnode->path.path_cost = cost_nestloop(outer_path,
+ inner_path,
IsA(inner_path, IndexPath));
return pathnode;
@@ -391,10 +340,6 @@ create_nestloop_path(RelOptInfo *joinrel,
* two relations
*
* 'joinrel' is the join relation
- * 'outersize' is the number of tuples in the outer relation
- * 'innersize' is the number of tuples in the inner relation
- * 'outerwidth' is the number of bytes per tuple in the outer relation
- * 'innerwidth' is the number of bytes per tuple in the inner relation
* 'outer_path' is the outer path
* 'inner_path' is the inner path
* 'pathkeys' are the path keys of the new join path
@@ -405,10 +350,6 @@ create_nestloop_path(RelOptInfo *joinrel,
*/
MergePath *
create_mergejoin_path(RelOptInfo *joinrel,
- int outersize,
- int innersize,
- int outerwidth,
- int innerwidth,
Path *outer_path,
Path *inner_path,
List *pathkeys,
@@ -433,19 +374,14 @@ create_mergejoin_path(RelOptInfo *joinrel,
pathnode->jpath.path.parent = joinrel;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
- pathnode->jpath.pathinfo = joinrel->restrictinfo;
pathnode->jpath.path.pathkeys = pathkeys;
pathnode->path_mergeclauses = mergeclauses;
pathnode->outersortkeys = outersortkeys;
pathnode->innersortkeys = innersortkeys;
- pathnode->jpath.path.path_cost = cost_mergejoin(outer_path->path_cost,
- inner_path->path_cost,
+ pathnode->jpath.path.path_cost = cost_mergejoin(outer_path,
+ inner_path,
outersortkeys,
- innersortkeys,
- outersize,
- innersize,
- outerwidth,
- innerwidth);
+ innersortkeys);
return pathnode;
}
@@ -455,10 +391,6 @@ create_mergejoin_path(RelOptInfo *joinrel,
* Creates a pathnode corresponding to a hash join between two relations.
*
* 'joinrel' is the join relation
- * 'outersize' is the number of tuples in the outer relation
- * 'innersize' is the number of tuples in the inner relation
- * 'outerwidth' is the number of bytes per tuple in the outer relation
- * 'innerwidth' is the number of bytes per tuple in the inner relation
* 'outer_path' is the cheapest outer path
* 'inner_path' is the cheapest inner path
* 'hashclauses' is a list of the hash join clause (always a 1-element list)
@@ -467,14 +399,10 @@ create_mergejoin_path(RelOptInfo *joinrel,
*/
HashPath *
create_hashjoin_path(RelOptInfo *joinrel,
- int outersize,
- int innersize,
- int outerwidth,
- int innerwidth,
Path *outer_path,
Path *inner_path,
List *hashclauses,
- Cost innerdisbursion)
+ Selectivity innerdisbursion)
{
HashPath *pathnode = makeNode(HashPath);
@@ -482,14 +410,11 @@ create_hashjoin_path(RelOptInfo *joinrel,
pathnode->jpath.path.parent = joinrel;
pathnode->jpath.outerjoinpath = outer_path;
pathnode->jpath.innerjoinpath = inner_path;
- pathnode->jpath.pathinfo = joinrel->restrictinfo;
/* A hashjoin never has pathkeys, since its ordering is unpredictable */
pathnode->jpath.path.pathkeys = NIL;
pathnode->path_hashclauses = hashclauses;
- pathnode->jpath.path.path_cost = cost_hashjoin(outer_path->path_cost,
- inner_path->path_cost,
- outersize, innersize,
- outerwidth, innerwidth,
+ pathnode->jpath.path.path_cost = cost_hashjoin(outer_path,
+ inner_path,
innerdisbursion);
return pathnode;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 03d29be4dcf..ef0dbfbda99 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -8,14 +8,15 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.40 1999/11/22 17:56:17 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.41 2000/01/09 00:26:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-#include <math.h>
#include "postgres.h"
+#include <math.h>
+
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catname.h"
@@ -23,20 +24,12 @@
#include "catalog/pg_inherits.h"
#include "optimizer/clauses.h"
#include "optimizer/internal.h"
+#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "parser/parsetree.h"
#include "utils/syscache.h"
-static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys,
- Oid *operatorObjectIds,
- AttrNumber *varAttributeNumbers,
- Datum *constValues,
- int *constFlags,
- float *idxPages,
- float *idxSelec);
-
-
/*
* relation_info -
* Retrieves catalog information for a given relation.
@@ -47,39 +40,33 @@ static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys,
*/
void
relation_info(Query *root, Index relid,
- bool *hasindex, int *pages, int *tuples)
+ bool *hasindex, long *pages, double *tuples)
{
+ Oid relationObjectId = getrelid(relid, root->rtable);
HeapTuple relationTuple;
Form_pg_class relation;
- Oid relationObjectId;
- relationObjectId = getrelid(relid, root->rtable);
relationTuple = SearchSysCacheTuple(RELOID,
ObjectIdGetDatum(relationObjectId),
0, 0, 0);
- if (HeapTupleIsValid(relationTuple))
- {
- relation = (Form_pg_class) GETSTRUCT(relationTuple);
-
- *hasindex = (relation->relhasindex) ? true : false;
- *pages = relation->relpages;
- *tuples = relation->reltuples;
- }
- else
- {
+ if (!HeapTupleIsValid(relationTuple))
elog(ERROR, "relation_info: Relation %u not found",
relationObjectId);
- }
+ relation = (Form_pg_class) GETSTRUCT(relationTuple);
+
+ *hasindex = (relation->relhasindex) ? true : false;
+ *pages = relation->relpages;
+ *tuples = relation->reltuples;
}
/*
* find_secondary_indexes
- * Creates a list of RelOptInfo nodes containing information for each
+ * Creates a list of IndexOptInfo nodes containing information for each
* secondary index defined on the given relation.
*
* 'relid' is the RT index of the relation for which indices are being located
*
- * Returns a list of new index RelOptInfo nodes.
+ * Returns a list of new IndexOptInfo nodes.
*/
List *
find_secondary_indexes(Query *root, Index relid)
@@ -105,7 +92,7 @@ find_secondary_indexes(Query *root, Index relid)
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
{
Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
- RelOptInfo *info = makeNode(RelOptInfo);
+ IndexOptInfo *info = makeNode(IndexOptInfo);
int i;
Relation indexRelation;
uint16 amstrategy;
@@ -120,7 +107,7 @@ find_secondary_indexes(Query *root, Index relid)
info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1));
/* Extract info from the pg_index tuple */
- info->relids = lconsi(index->indexrelid, NIL);
+ info->indexoid = index->indexrelid;
info->indproc = index->indproc; /* functional index ?? */
if (VARSIZE(&index->indpred) != 0) /* partial index ?? */
{
@@ -172,17 +159,6 @@ find_secondary_indexes(Query *root, Index relid)
info->ordering[i] = ((Form_pg_amop) GETSTRUCT(amopTuple))->amopopr;
}
- info->indexed = false; /* not indexed itself */
- info->size = 0;
- info->width = 0;
- info->targetlist = NIL;
- info->pathlist = NIL;
- info->cheapestpath = NULL;
- info->pruneable = true;
- info->restrictinfo = NIL;
- info->joininfo = NIL;
- info->innerjoin = NIL;
-
indexes = lcons(info, indexes);
}
@@ -200,77 +176,211 @@ find_secondary_indexes(Query *root, Index relid)
* but here we consider the cost of just one pass.
*
* 'root' is the query root
- * 'relid' is the RT index of the relation being scanned
- * 'indexid' is the OID of the index to be used
+ * 'rel' is the relation being scanned
+ * 'index' is the index to be used
* 'indexquals' is the list of qual condition exprs (implicit AND semantics)
* '*idxPages' receives an estimate of the number of index pages touched
- * '*idxSelec' receives an estimate of selectivity of the scan
+ * '*idxSelec' receives an estimate of selectivity of the scan, ie fraction
+ * of the relation's tuples that will be retrieved
*/
void
index_selectivity(Query *root,
- int relid,
- Oid indexid,
+ RelOptInfo *rel,
+ IndexOptInfo *index,
List *indexquals,
- float *idxPages,
- float *idxSelec)
+ long *idxPages,
+ Selectivity *idxSelec)
{
- int nclauses = length(indexquals);
- Oid *opno_array;
- AttrNumber *attno_array;
- Datum *value_array;
- int *flag_array;
+ int relid;
+ Oid baserelid,
+ indexrelid;
+ HeapTuple indRel,
+ indexTuple;
+ Form_pg_class indexrelation;
+ Oid relam;
+ Form_pg_index pgindex;
+ int nIndexKeys;
+ float64data npages,
+ select,
+ fattr_select;
+ bool nphack = false;
List *q;
- int i;
- if (nclauses <= 0)
- {
- *idxPages = 0.0;
- *idxSelec = 1.0;
- return;
- }
- opno_array = (Oid *) palloc(nclauses * sizeof(Oid));
- attno_array = (AttrNumber *) palloc(nclauses * sizeof(AttrNumber));
- value_array = (Datum *) palloc(nclauses * sizeof(Datum));
- flag_array = (int *) palloc(nclauses * sizeof(int));
+ Assert(length(rel->relids) == 1); /* must be a base rel */
+ relid = lfirsti(rel->relids);
+
+ baserelid = getrelid(relid, root->rtable);
+ indexrelid = index->indexoid;
+
+ indRel = SearchSysCacheTuple(RELOID,
+ ObjectIdGetDatum(indexrelid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(indRel))
+ elog(ERROR, "index_selectivity: index %u not found in pg_class",
+ indexrelid);
+ indexrelation = (Form_pg_class) GETSTRUCT(indRel);
+ relam = indexrelation->relam;
+
+ indexTuple = SearchSysCacheTuple(INDEXRELID,
+ ObjectIdGetDatum(indexrelid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(indexTuple))
+ elog(ERROR, "index_selectivity: index %u not found in pg_index",
+ indexrelid);
+ pgindex = (Form_pg_index) GETSTRUCT(indexTuple);
+
+ nIndexKeys = 1;
+ while (pgindex->indclass[nIndexKeys] != InvalidOid)
+ nIndexKeys++;
+
+ /*
+ * Hack for non-functional btree npages estimation: npages =
+ * index_pages * selectivity_of_1st_attr_clause(s) - vadim 04/24/97
+ */
+ if (relam == BTREE_AM_OID && pgindex->indproc == InvalidOid)
+ nphack = true;
+
+ npages = 0.0;
+ select = 1.0;
+ fattr_select = 1.0;
- i = 0;
foreach(q, indexquals)
{
Node *expr = (Node *) lfirst(q);
+ Oid opno;
int dummyrelid;
+ AttrNumber attno;
+ Datum value;
+ int flag;
+ Oid indclass;
+ HeapTuple amopTuple;
+ Form_pg_amop amop;
+ float64 amopnpages,
+ amopselect;
+ /*
+ * Extract info from clause.
+ */
if (is_opclause(expr))
- opno_array[i] = ((Oper *) ((Expr *) expr)->oper)->opno;
+ opno = ((Oper *) ((Expr *) expr)->oper)->opno;
else
- opno_array[i] = InvalidOid;
+ opno = InvalidOid;
+ get_relattval(expr, relid, &dummyrelid, &attno, &value, &flag);
- get_relattval(expr, relid, &dummyrelid, &attno_array[i],
- &value_array[i], &flag_array[i]);
- i++;
+ /*
+ * Find the AM class for this key.
+ */
+ if (pgindex->indproc != InvalidOid)
+ {
+ /*
+ * Functional index: AM class is the first one defined since
+ * functional indices have exactly one key.
+ */
+ indclass = pgindex->indclass[0];
+ }
+ else
+ {
+ int i;
+ indclass = InvalidOid;
+ for (i = 0; pgindex->indkey[i]; i++)
+ {
+ if (attno == pgindex->indkey[i])
+ {
+ indclass = pgindex->indclass[i];
+ break;
+ }
+ }
+ }
+ if (!OidIsValid(indclass))
+ {
+ /*
+ * Presumably this means that we are using a functional index
+ * clause and so had no variable to match to the index key ...
+ * if not we are in trouble.
+ */
+ elog(NOTICE, "index_selectivity: no key %d in index %u",
+ attno, indexrelid);
+ continue;
+ }
+
+ amopTuple = SearchSysCacheTuple(AMOPOPID,
+ ObjectIdGetDatum(indclass),
+ ObjectIdGetDatum(opno),
+ ObjectIdGetDatum(relam),
+ 0);
+ if (!HeapTupleIsValid(amopTuple))
+ {
+ /*
+ * We might get here because indxpath.c selected a binary-
+ * compatible index. Try again with the compatible operator.
+ */
+ if (opno != InvalidOid)
+ {
+ opno = indexable_operator((Expr *) expr, indclass, relam,
+ ((flag & SEL_RIGHT) != 0));
+ amopTuple = SearchSysCacheTuple(AMOPOPID,
+ ObjectIdGetDatum(indclass),
+ ObjectIdGetDatum(opno),
+ ObjectIdGetDatum(relam),
+ 0);
+ }
+ if (!HeapTupleIsValid(amopTuple))
+ elog(ERROR, "index_selectivity: no amop %u %u %u",
+ indclass, opno, relam);
+ }
+ amop = (Form_pg_amop) GETSTRUCT(amopTuple);
+
+ if (!nphack)
+ {
+ amopnpages = (float64) fmgr(amop->amopnpages,
+ (char *) opno,
+ (char *) baserelid,
+ (char *) (int) attno,
+ (char *) value,
+ (char *) flag,
+ (char *) nIndexKeys,
+ (char *) indexrelid);
+ if (PointerIsValid(amopnpages))
+ npages += *amopnpages;
+ }
+
+ amopselect = (float64) fmgr(amop->amopselect,
+ (char *) opno,
+ (char *) baserelid,
+ (char *) (int) attno,
+ (char *) value,
+ (char *) flag,
+ (char *) nIndexKeys,
+ (char *) indexrelid);
+ if (PointerIsValid(amopselect))
+ {
+ select *= *amopselect;
+ if (nphack && attno == pgindex->indkey[0])
+ fattr_select *= *amopselect;
+ }
}
- IndexSelectivity(indexid,
- getrelid(relid, root->rtable),
- nclauses,
- opno_array,
- attno_array,
- value_array,
- flag_array,
- idxPages,
- idxSelec);
-
- pfree(opno_array);
- pfree(attno_array);
- pfree(value_array);
- pfree(flag_array);
+ /*
+ * Estimation of npages below is hack of course, but it's better than
+ * it was before. - vadim 04/09/97
+ */
+ if (nphack)
+ {
+ npages = fattr_select * indexrelation->relpages;
+ *idxPages = (long) ceil((double) npages);
+ }
+ else
+ {
+ if (nIndexKeys > 1)
+ npages = npages / (1.0 + nIndexKeys);
+ *idxPages = (long) ceil((double) (npages / nIndexKeys));
+ }
+ *idxSelec = select;
}
/*
* restriction_selectivity
*
- * NOTE: The routine is now merged with RestrictionClauseSelectivity
- * as defined in plancat.c
- *
* Returns the selectivity of a specified operator.
* This code executes registered procedures stored in the
* operator relation, by calling the function manager.
@@ -279,7 +389,7 @@ index_selectivity(Query *root,
* relation OIDs or attribute numbers are 0, then the clause
* isn't of the form (op var const).
*/
-Cost
+Selectivity
restriction_selectivity(Oid functionObjectId,
Oid operatorObjectId,
Oid relationObjectId,
@@ -297,28 +407,25 @@ restriction_selectivity(Oid functionObjectId,
(char *) constFlag,
NULL);
if (!PointerIsValid(result))
- elog(ERROR, "RestrictionClauseSelectivity: bad pointer");
+ elog(ERROR, "restriction_selectivity: bad pointer");
if (*result < 0.0 || *result > 1.0)
- elog(ERROR, "RestrictionClauseSelectivity: bad value %lf",
- *result);
+ elog(ERROR, "restriction_selectivity: bad value %lf", *result);
- return (Cost) *result;
+ return (Selectivity) *result;
}
/*
* join_selectivity
- * Similarly, this routine is merged with JoinClauseSelectivity in
- * plancat.c
*
- * Returns the selectivity of an operator, given the join clause
- * information.
+ * Returns the selectivity of an operator, given the join clause
+ * information.
*
* XXX The assumption in the selectivity procedures is that if the
* relation OIDs or attribute numbers are 0, then the clause
* isn't of the form (op var var).
*/
-Cost
+Selectivity
join_selectivity(Oid functionObjectId,
Oid operatorObjectId,
Oid relationObjectId1,
@@ -336,13 +443,12 @@ join_selectivity(Oid functionObjectId,
(char *) (int) attributeNumber2,
NULL);
if (!PointerIsValid(result))
- elog(ERROR, "JoinClauseSelectivity: bad pointer");
+ elog(ERROR, "join_selectivity: bad pointer");
if (*result < 0.0 || *result > 1.0)
- elog(ERROR, "JoinClauseSelectivity: bad value %lf",
- *result);
+ elog(ERROR, "join_selectivity: bad value %lf", *result);
- return (Cost) *result;
+ return (Selectivity) *result;
}
/*
@@ -421,172 +527,3 @@ VersionGetParents(Oid verrelid)
}
#endif
-
-
-/*****************************************************************************
- *
- *****************************************************************************/
-
-/*
- * IndexSelectivity
- *
- * Calls the 'amopnpages' and 'amopselect' functions for each
- * AM operator when a given index (specified by 'indexrelid') is used.
- * The total number of pages and product of the selectivities are returned.
- *
- * Assumption: the attribute numbers and operator ObjectIds are in order
- * WRT to each other (otherwise, you have no way of knowing which
- * AM operator class or attribute number corresponds to which operator.
- *
- * 'nIndexKeys' is the number of qual clauses in use
- * 'varAttributeNumbers' contains attribute numbers for variables
- * 'constValues' contains the constant values
- * 'constFlags' describes how to treat the constants in each clause
- */
-static void
-IndexSelectivity(Oid indexrelid,
- Oid baserelid,
- int nIndexKeys,
- Oid *operatorObjectIds,
- AttrNumber *varAttributeNumbers,
- Datum *constValues,
- int *constFlags,
- float *idxPages,
- float *idxSelec)
-{
- int i,
- n;
- HeapTuple indexTuple,
- amopTuple,
- indRel;
- Form_pg_class indexrelation;
- Form_pg_index index;
- Form_pg_amop amop;
- Oid indclass;
- float64data npages,
- select;
- float64 amopnpages,
- amopselect;
- Oid relam;
- bool nphack = false;
- float64data fattr_select = 1.0;
-
- indRel = SearchSysCacheTuple(RELOID,
- ObjectIdGetDatum(indexrelid),
- 0, 0, 0);
- if (!HeapTupleIsValid(indRel))
- elog(ERROR, "IndexSelectivity: index %u not found",
- indexrelid);
- indexrelation = (Form_pg_class) GETSTRUCT(indRel);
- relam = indexrelation->relam;
-
- indexTuple = SearchSysCacheTuple(INDEXRELID,
- ObjectIdGetDatum(indexrelid),
- 0, 0, 0);
- if (!HeapTupleIsValid(indexTuple))
- elog(ERROR, "IndexSelectivity: index %u not found",
- indexrelid);
- index = (Form_pg_index) GETSTRUCT(indexTuple);
-
- /*
- * Hack for non-functional btree npages estimation: npages =
- * index_pages * selectivity_of_1st_attr_clause(s) - vadim 04/24/97
- */
- if (relam == BTREE_AM_OID &&
- varAttributeNumbers[0] != InvalidAttrNumber)
- nphack = true;
-
- npages = 0.0;
- select = 1.0;
- for (n = 0; n < nIndexKeys; n++)
- {
- /*
- * Find the AM class for this key.
- *
- * If the first attribute number is invalid then we have a functional
- * index, and AM class is the first one defined since functional
- * indices have exactly one key.
- */
- indclass = (varAttributeNumbers[0] == InvalidAttrNumber) ?
- index->indclass[0] : InvalidOid;
- i = 0;
- while ((i < nIndexKeys) && (indclass == InvalidOid))
- {
- if (varAttributeNumbers[n] == index->indkey[i])
- {
- indclass = index->indclass[i];
- break;
- }
- i++;
- }
- if (!OidIsValid(indclass))
- {
-
- /*
- * Presumably this means that we are using a functional index
- * clause and so had no variable to match to the index key ...
- * if not we are in trouble.
- */
- elog(NOTICE, "IndexSelectivity: no key %d in index %u",
- varAttributeNumbers[n], indexrelid);
- continue;
- }
-
- amopTuple = SearchSysCacheTuple(AMOPOPID,
- ObjectIdGetDatum(indclass),
- ObjectIdGetDatum(operatorObjectIds[n]),
- ObjectIdGetDatum(relam),
- 0);
- if (!HeapTupleIsValid(amopTuple))
- elog(ERROR, "IndexSelectivity: no amop %u %u %u",
- indclass, operatorObjectIds[n], relam);
- amop = (Form_pg_amop) GETSTRUCT(amopTuple);
-
- if (!nphack)
- {
- amopnpages = (float64) fmgr(amop->amopnpages,
- (char *) operatorObjectIds[n],
- (char *) baserelid,
- (char *) (int) varAttributeNumbers[n],
- (char *) constValues[n],
- (char *) constFlags[n],
- (char *) nIndexKeys,
- (char *) indexrelid);
- if (PointerIsValid(amopnpages))
- npages += *amopnpages;
- }
-
- amopselect = (float64) fmgr(amop->amopselect,
- (char *) operatorObjectIds[n],
- (char *) baserelid,
- (char *) (int) varAttributeNumbers[n],
- (char *) constValues[n],
- (char *) constFlags[n],
- (char *) nIndexKeys,
- (char *) indexrelid);
-
- if (PointerIsValid(amopselect))
- {
- select *= *amopselect;
- if (nphack && varAttributeNumbers[n] == index->indkey[0])
- fattr_select *= *amopselect;
- }
- }
-
- /*
- * Estimation of npages below is hack of course, but it's better than
- * it was before. - vadim 04/09/97
- */
- if (nphack)
- {
- npages = fattr_select * indexrelation->relpages;
- *idxPages = ceil((double) npages);
- }
- else
- {
- if (nIndexKeys > 1)
- npages = npages / (1.0 + nIndexKeys);
- *idxPages = ceil((double) (npages / nIndexKeys));
- }
- *idxSelec = select;
-}
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 885d0f0715c..bb6773dfe1b 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.19 1999/08/16 02:17:58 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.20 2000/01/09 00:26:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,21 +37,15 @@ get_base_rel(Query *root, int relid)
{
rel = makeNode(RelOptInfo);
rel->relids = relids;
- rel->indexed = false;
- rel->pages = 0;
- rel->tuples = 0;
- rel->size = 0;
+ rel->rows = 0;
rel->width = 0;
rel->targetlist = NIL;
rel->pathlist = NIL;
rel->cheapestpath = (Path *) NULL;
rel->pruneable = true;
- rel->classlist = NULL;
- rel->indexkeys = NULL;
- rel->ordering = NULL;
- rel->relam = InvalidOid;
- rel->indproc = InvalidOid;
- rel->indpred = NIL;
+ rel->indexed = false;
+ rel->pages = 0;
+ rel->tuples = 0;
rel->restrictinfo = NIL;
rel->joininfo = NIL;
rel->innerjoin = NIL;