aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/plan/createplan.c78
-rw-r--r--src/backend/optimizer/plan/planner.c158
-rw-r--r--src/backend/optimizer/util/plancat.c248
-rw-r--r--src/backend/optimizer/util/relnode.c17
4 files changed, 328 insertions, 173 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index eb7e922d9a1..d78dd2c1e83 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.133 2003/01/22 00:07:00 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.134 2003/02/03 15:07:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,6 +34,7 @@
static Scan *create_scan_plan(Query *root, Path *best_path);
+static bool use_physical_tlist(RelOptInfo *rel);
static Join *create_join_plan(Query *root, JoinPath *best_path);
static Append *create_append_plan(Query *root, AppendPath *best_path);
static Result *create_result_plan(Query *root, ResultPath *best_path);
@@ -185,15 +186,41 @@ create_plan(Query *root, Path *best_path)
static Scan *
create_scan_plan(Query *root, Path *best_path)
{
- Scan *plan;
- List *tlist = best_path->parent->targetlist;
+ RelOptInfo *rel = best_path->parent;
+ List *tlist;
List *scan_clauses;
+ Scan *plan;
+
+ /*
+ * For table scans, rather than using the relation targetlist (which is
+ * only those Vars actually needed by the query), we prefer to generate a
+ * tlist containing all Vars in order. This will allow the executor to
+ * optimize away projection of the table tuples, if possible. (Note that
+ * planner.c may replace the tlist we generate here, forcing projection to
+ * occur.)
+ */
+ if (use_physical_tlist(rel))
+ {
+ int resdomno = 1;
+ List *v;
+
+ tlist = NIL;
+ foreach(v, rel->varlist)
+ {
+ Var *var = (Var *) lfirst(v);
+
+ tlist = lappend(tlist, create_tl_element(var, resdomno));
+ resdomno++;
+ }
+ }
+ else
+ tlist = rel->targetlist;
/*
* Extract the relevant restriction clauses from the parent relation;
* the executor must apply all these restrictions during the scan.
*/
- scan_clauses = get_actual_clauses(best_path->parent->baserestrictinfo);
+ scan_clauses = get_actual_clauses(rel->baserestrictinfo);
/* Sort clauses into best execution order */
scan_clauses = order_qual_clauses(root, scan_clauses);
@@ -242,6 +269,47 @@ create_scan_plan(Query *root, Path *best_path)
}
/*
+ * use_physical_tlist
+ * Decide whether to use a tlist matching relation structure,
+ * rather than only those Vars actually referenced.
+ */
+static bool
+use_physical_tlist(RelOptInfo *rel)
+{
+ List *t;
+
+ /*
+ * Currently, can't do this for subquery or function scans. (This
+ * is mainly because we don't set up the necessary info when creating
+ * their RelOptInfo nodes.)
+ */
+ if (rel->rtekind != RTE_RELATION)
+ return false;
+ /*
+ * Can't do it with inheritance cases either (mainly because Append
+ * doesn't project).
+ */
+ if (rel->reloptkind != RELOPT_BASEREL)
+ return false;
+ /*
+ * Can't do it if any system columns are requested, either. (This could
+ * possibly be fixed but would take some fragile assumptions in setrefs.c,
+ * I think.)
+ */
+ foreach(t, rel->targetlist)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(t);
+ Var *var = (Var *) tle->expr;
+
+ if (!var || !IsA(var, Var))
+ return false; /* probably can't happen */
+ if (var->varattno <= 0)
+ return false; /* system column! */
+ }
+ return true;
+}
+
+/*
* create_join_plan
* Create a join plan for 'best_path' and (recursively) plans for its
* inner and outer paths.
@@ -399,7 +467,7 @@ create_material_plan(Query *root, MaterialPath *best_path)
subplan = create_plan(root, best_path->subpath);
- plan = make_material(best_path->path.parent->targetlist, subplan);
+ plan = make_material(subplan->targetlist, subplan);
copy_path_costsize(&plan->plan, (Path *) best_path);
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 1b481ccbd25..f01b9feffe2 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.142 2003/01/25 23:10:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.143 2003/02/03 15:07:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,7 +55,11 @@ static Plan *inheritance_planner(Query *parse, List *inheritlist);
static Plan *grouping_planner(Query *parse, double tuple_fraction);
static bool hash_safe_grouping(Query *parse);
static List *make_subplanTargetList(Query *parse, List *tlist,
- AttrNumber **groupColIdx);
+ AttrNumber **groupColIdx, bool *need_tlist_eval);
+static void locate_grouping_columns(Query *parse,
+ List *tlist,
+ List *sub_tlist,
+ AttrNumber *groupColIdx);
static Plan *make_groupsortplan(Query *parse,
List *groupClause,
AttrNumber *grpColIdx,
@@ -530,6 +534,7 @@ grouping_planner(Query *parse, double tuple_fraction)
List *sub_tlist;
List *group_pathkeys;
AttrNumber *groupColIdx = NULL;
+ bool need_tlist_eval = true;
QualCost tlist_cost;
double sub_tuple_fraction;
Path *cheapest_path;
@@ -602,7 +607,8 @@ grouping_planner(Query *parse, double tuple_fraction)
* Generate appropriate target list for subplan; may be different
* from tlist if grouping or aggregation is needed.
*/
- sub_tlist = make_subplanTargetList(parse, tlist, &groupColIdx);
+ sub_tlist = make_subplanTargetList(parse, tlist,
+ &groupColIdx, &need_tlist_eval);
/*
* Calculate pathkeys that represent grouping/ordering
@@ -1003,45 +1009,65 @@ grouping_planner(Query *parse, double tuple_fraction)
/*
* create_plan() returns a plan with just a "flat" tlist of required
- * Vars. We want to insert the sub_tlist as the tlist of the top
- * plan node. If the top-level plan node is one that cannot do
- * expression evaluation, we must insert a Result node to project the
- * desired tlist.
- * Currently, the only plan node we might see here that falls into
- * that category is Append.
+ * Vars. Usually we need to insert the sub_tlist as the tlist of the
+ * top plan node. However, we can skip that if we determined that
+ * whatever query_planner chose to return will be good enough.
*/
- if (IsA(result_plan, Append))
+ if (need_tlist_eval)
{
- result_plan = (Plan *) make_result(sub_tlist, NULL, result_plan);
+ /*
+ * If the top-level plan node is one that cannot do expression
+ * evaluation, we must insert a Result node to project the desired
+ * tlist.
+ * Currently, the only plan node we might see here that falls into
+ * that category is Append.
+ */
+ if (IsA(result_plan, Append))
+ {
+ result_plan = (Plan *) make_result(sub_tlist, NULL,
+ result_plan);
+ }
+ else
+ {
+ /*
+ * Otherwise, just replace the subplan's flat tlist with
+ * the desired tlist.
+ */
+ result_plan->targetlist = sub_tlist;
+ }
+ /*
+ * Also, account for the cost of evaluation of the sub_tlist.
+ *
+ * Up to now, we have only been dealing with "flat" tlists,
+ * containing just Vars. So their evaluation cost is zero
+ * according to the model used by cost_qual_eval() (or if you
+ * prefer, the cost is factored into cpu_tuple_cost). Thus we can
+ * avoid accounting for tlist cost throughout query_planner() and
+ * subroutines. But now we've inserted a tlist that might contain
+ * actual operators, sub-selects, etc --- so we'd better account
+ * for its cost.
+ *
+ * Below this point, any tlist eval cost for added-on nodes should
+ * be accounted for as we create those nodes. Presently, of the
+ * node types we can add on, only Agg and Group project new tlists
+ * (the rest just copy their input tuples) --- so make_agg() and
+ * make_group() are responsible for computing the added cost.
+ */
+ cost_qual_eval(&tlist_cost, sub_tlist);
+ result_plan->startup_cost += tlist_cost.startup;
+ result_plan->total_cost += tlist_cost.startup +
+ tlist_cost.per_tuple * result_plan->plan_rows;
}
else
{
/*
- * Otherwise, just replace the flat tlist with the desired tlist.
+ * Since we're using query_planner's tlist and not the one
+ * make_subplanTargetList calculated, we have to refigure
+ * any grouping-column indexes make_subplanTargetList computed.
*/
- result_plan->targetlist = sub_tlist;
+ locate_grouping_columns(parse, tlist, result_plan->targetlist,
+ groupColIdx);
}
- /*
- * Also, account for the cost of evaluation of the sub_tlist.
- *
- * Up to now, we have only been dealing with "flat" tlists, containing
- * just Vars. So their evaluation cost is zero according to the
- * model used by cost_qual_eval() (or if you prefer, the cost is
- * factored into cpu_tuple_cost). Thus we can avoid accounting for
- * tlist cost throughout query_planner() and subroutines.
- * But now we've inserted a tlist that might contain actual operators,
- * sub-selects, etc --- so we'd better account for its cost.
- *
- * Below this point, any tlist eval cost for added-on nodes should
- * be accounted for as we create those nodes. Presently, of the
- * node types we can add on, only Agg and Group project new tlists
- * (the rest just copy their input tuples) --- so make_agg() and
- * make_group() are responsible for computing the added cost.
- */
- cost_qual_eval(&tlist_cost, sub_tlist);
- result_plan->startup_cost += tlist_cost.startup;
- result_plan->total_cost += tlist_cost.startup +
- tlist_cost.per_tuple * result_plan->plan_rows;
/*
* Insert AGG or GROUP node if needed, plus an explicit sort step
@@ -1245,10 +1271,17 @@ hash_safe_grouping(Query *parse)
* the extra computation to recompute a+b at the outer level; see
* replace_vars_with_subplan_refs() in setrefs.c.)
*
+ * If we are grouping or aggregating, *and* there are no non-Var grouping
+ * expressions, then the returned tlist is effectively dummy; we do not
+ * need to force it to be evaluated, because all the Vars it contains
+ * should be present in the output of query_planner anyway.
+ *
* 'parse' is the query being processed.
* 'tlist' is the query's target list.
* 'groupColIdx' receives an array of column numbers for the GROUP BY
- * expressions (if there are any) in the subplan's target list.
+ * expressions (if there are any) in the subplan's target list.
+ * 'need_tlist_eval' is set true if we really need to evaluate the
+ * result tlist.
*
* The result is the targetlist to be passed to the subplan.
*---------------
@@ -1256,7 +1289,8 @@ hash_safe_grouping(Query *parse)
static List *
make_subplanTargetList(Query *parse,
List *tlist,
- AttrNumber **groupColIdx)
+ AttrNumber **groupColIdx,
+ bool *need_tlist_eval)
{
List *sub_tlist;
List *extravars;
@@ -1269,7 +1303,10 @@ make_subplanTargetList(Query *parse,
* query_planner should receive the unmodified target list.
*/
if (!parse->hasAggs && !parse->groupClause && !parse->havingQual)
+ {
+ *need_tlist_eval = true;
return tlist;
+ }
/*
* Otherwise, start with a "flattened" tlist (having just the vars
@@ -1280,6 +1317,7 @@ make_subplanTargetList(Query *parse,
extravars = pull_var_clause(parse->havingQual, false);
sub_tlist = add_to_flat_tlist(sub_tlist, extravars);
freeList(extravars);
+ *need_tlist_eval = false; /* only eval if not flat tlist */
/*
* If grouping, create sub_tlist entries for all GROUP BY expressions
@@ -1320,6 +1358,7 @@ make_subplanTargetList(Query *parse,
false),
(Expr *) groupexpr);
sub_tlist = lappend(sub_tlist, te);
+ *need_tlist_eval = true; /* it's not flat anymore */
}
/* and save its resno */
@@ -1331,6 +1370,53 @@ make_subplanTargetList(Query *parse,
}
/*
+ * locate_grouping_columns
+ * Locate grouping columns in the tlist chosen by query_planner.
+ *
+ * This is only needed if we don't use the sub_tlist chosen by
+ * make_subplanTargetList. We have to forget the column indexes found
+ * by that routine and re-locate the grouping vars in the real sub_tlist.
+ */
+static void
+locate_grouping_columns(Query *parse,
+ List *tlist,
+ List *sub_tlist,
+ AttrNumber *groupColIdx)
+{
+ int keyno = 0;
+ List *gl;
+
+ /*
+ * No work unless grouping.
+ */
+ if (!parse->groupClause)
+ {
+ Assert(groupColIdx == NULL);
+ return;
+ }
+ Assert(groupColIdx != NULL);
+
+ foreach(gl, parse->groupClause)
+ {
+ GroupClause *grpcl = (GroupClause *) lfirst(gl);
+ Node *groupexpr = get_sortgroupclause_expr(grpcl, tlist);
+ TargetEntry *te = NULL;
+ List *sl;
+
+ foreach(sl, sub_tlist)
+ {
+ te = (TargetEntry *) lfirst(sl);
+ if (equal(groupexpr, te->expr))
+ break;
+ }
+ if (!sl)
+ elog(ERROR, "locate_grouping_columns: failed");
+
+ groupColIdx[keyno++] = te->resdom->resno;
+ }
+}
+
+/*
* make_groupsortplan
* Add a Sort node to explicitly sort according to the GROUP BY clause.
*
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 4a9f63312c3..3e0bbe69225 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.76 2003/01/28 22:13:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.77 2003/02/03 15:07:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,6 +23,7 @@
#include "catalog/pg_amop.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_index.h"
+#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
#include "parser/parsetree.h"
@@ -38,155 +39,160 @@
/*
* get_relation_info -
* Retrieves catalog information for a given relation.
- * Given the Oid of the relation, return the following info:
- * whether the relation has secondary indices
- * number of pages
- * number of tuples
- */
-void
-get_relation_info(Oid relationObjectId,
- bool *hasindex, long *pages, double *tuples)
-{
- HeapTuple relationTuple;
- Form_pg_class relation;
-
- relationTuple = SearchSysCache(RELOID,
- ObjectIdGetDatum(relationObjectId),
- 0, 0, 0);
- if (!HeapTupleIsValid(relationTuple))
- elog(ERROR, "get_relation_info: Relation %u not found",
- relationObjectId);
- relation = (Form_pg_class) GETSTRUCT(relationTuple);
-
- if (IsIgnoringSystemIndexes() && IsSystemClass(relation))
- *hasindex = false;
- else
- *hasindex = relation->relhasindex;
-
- *pages = relation->relpages;
- *tuples = relation->reltuples;
-
- ReleaseSysCache(relationTuple);
-}
-
-/*
- * find_secondary_indexes
- * Creates a list of IndexOptInfo nodes containing information for each
- * secondary index defined on the specified relation.
*
- * 'relationObjectId' is the OID of the relation for which indices are wanted
+ * Given the Oid of the relation, return the following info into fields
+ * of the RelOptInfo struct:
*
- * Returns a list of new IndexOptInfo nodes.
+ * varlist list of physical columns (expressed as Vars)
+ * indexlist list of IndexOptInfos for relation's indexes
+ * pages number of pages
+ * tuples number of tuples
*/
-List *
-find_secondary_indexes(Oid relationObjectId)
+void
+get_relation_info(Oid relationObjectId, RelOptInfo *rel)
{
- List *indexinfos = NIL;
- List *indexoidlist,
- *indexoidscan;
Relation relation;
+ Index varno = lfirsti(rel->relids);
+ bool hasindex;
+ List *varlist = NIL;
+ List *indexinfos = NIL;
+ int attrno,
+ numattrs;
+
+ relation = heap_open(relationObjectId, AccessShareLock);
/*
- * We used to scan pg_index directly, but now the relcache offers a
- * cached list of OID indexes for each relation. So, get that list
- * and then use the syscache to obtain pg_index entries.
+ * Make list of physical Vars. Note we do NOT ignore dropped columns;
+ * the intent is to model the physical tuples of the relation.
*/
- relation = heap_open(relationObjectId, AccessShareLock);
- indexoidlist = RelationGetIndexList(relation);
+ numattrs = RelationGetNumberOfAttributes(relation);
- foreach(indexoidscan, indexoidlist)
+ for (attrno = 1; attrno <= numattrs; attrno++)
{
- Oid indexoid = lfirsti(indexoidscan);
- Relation indexRelation;
- Form_pg_index index;
- IndexOptInfo *info;
- int i;
- int16 amorderstrategy;
-
- /* Extract info from the relation descriptor for the index */
- indexRelation = index_open(indexoid);
+ Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
+
+ varlist = lappend(varlist,
+ makeVar(varno,
+ attrno,
+ att_tup->atttypid,
+ att_tup->atttypmod,
+ 0));
+ }
- info = makeNode(IndexOptInfo);
+ rel->varlist = varlist;
- /*
- * Need to make these arrays large enough to be sure there is room
- * for a terminating 0 at the end of each one.
- */
- info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1));
- info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS + 1));
- info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1));
-
- /* Extract info from the pg_index tuple */
- index = indexRelation->rd_index;
- info->indexoid = index->indexrelid;
- info->indproc = index->indproc; /* functional index ?? */
- if (VARSIZE(&index->indpred) > VARHDRSZ) /* partial index ?? */
- {
- char *predString;
+ /*
+ * Make list of indexes. Ignore indexes on system catalogs if told to.
+ */
+ if (IsIgnoringSystemIndexes() && IsSystemClass(relation->rd_rel))
+ hasindex = false;
+ else
+ hasindex = relation->rd_rel->relhasindex;
- predString = DatumGetCString(DirectFunctionCall1(textout,
- PointerGetDatum(&index->indpred)));
- info->indpred = (List *) stringToNode(predString);
- pfree(predString);
- }
- else
- info->indpred = NIL;
- info->unique = index->indisunique;
+ if (hasindex)
+ {
+ List *indexoidlist,
+ *indexoidscan;
- for (i = 0; i < INDEX_MAX_KEYS; i++)
- {
- if (index->indclass[i] == (Oid) 0)
- break;
- info->classlist[i] = index->indclass[i];
- }
- info->classlist[i] = (Oid) 0;
- info->ncolumns = i;
+ indexoidlist = RelationGetIndexList(relation);
- for (i = 0; i < INDEX_MAX_KEYS; i++)
+ foreach(indexoidscan, indexoidlist)
{
- if (index->indkey[i] == 0)
- break;
- info->indexkeys[i] = index->indkey[i];
- }
- info->indexkeys[i] = 0;
- info->nkeys = i;
+ Oid indexoid = lfirsti(indexoidscan);
+ Relation indexRelation;
+ Form_pg_index index;
+ IndexOptInfo *info;
+ int i;
+ int16 amorderstrategy;
+
+ /* Extract info from the relation descriptor for the index */
+ indexRelation = index_open(indexoid);
+
+ info = makeNode(IndexOptInfo);
+
+ /*
+ * Need to make these arrays large enough to be sure there is room
+ * for a terminating 0 at the end of each one.
+ */
+ info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1));
+ info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS + 1));
+ info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1));
+
+ /* Extract info from the pg_index tuple */
+ index = indexRelation->rd_index;
+ info->indexoid = index->indexrelid;
+ info->indproc = index->indproc; /* functional index ?? */
+ if (VARSIZE(&index->indpred) > VARHDRSZ) /* partial index ?? */
+ {
+ char *predString;
- info->relam = indexRelation->rd_rel->relam;
- info->pages = indexRelation->rd_rel->relpages;
- info->tuples = indexRelation->rd_rel->reltuples;
- info->amcostestimate = index_cost_estimator(indexRelation);
- amorderstrategy = indexRelation->rd_am->amorderstrategy;
+ predString = DatumGetCString(DirectFunctionCall1(textout,
+ PointerGetDatum(&index->indpred)));
+ info->indpred = (List *) stringToNode(predString);
+ pfree(predString);
+ }
+ else
+ info->indpred = NIL;
+ info->unique = index->indisunique;
- /*
- * Fetch the ordering operators associated with the index, if any.
- */
- MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS + 1));
- if (amorderstrategy != 0)
- {
- int oprindex = amorderstrategy - 1;
+ for (i = 0; i < INDEX_MAX_KEYS; i++)
+ {
+ if (index->indclass[i] == (Oid) 0)
+ break;
+ info->classlist[i] = index->indclass[i];
+ }
+ info->classlist[i] = (Oid) 0;
+ info->ncolumns = i;
- for (i = 0; i < info->ncolumns; i++)
+ for (i = 0; i < INDEX_MAX_KEYS; i++)
{
- info->ordering[i] = indexRelation->rd_operator[oprindex];
- oprindex += indexRelation->rd_am->amstrategies;
+ if (index->indkey[i] == 0)
+ break;
+ info->indexkeys[i] = index->indkey[i];
}
- }
+ info->indexkeys[i] = 0;
+ info->nkeys = i;
+
+ info->relam = indexRelation->rd_rel->relam;
+ info->pages = indexRelation->rd_rel->relpages;
+ info->tuples = indexRelation->rd_rel->reltuples;
+ info->amcostestimate = index_cost_estimator(indexRelation);
+ amorderstrategy = indexRelation->rd_am->amorderstrategy;
+
+ /*
+ * Fetch the ordering operators associated with the index, if any.
+ */
+ MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS + 1));
+ if (amorderstrategy != 0)
+ {
+ int oprindex = amorderstrategy - 1;
- /* initialize cached join info to empty */
- info->outer_relids = NIL;
- info->inner_paths = NIL;
+ for (i = 0; i < info->ncolumns; i++)
+ {
+ info->ordering[i] = indexRelation->rd_operator[oprindex];
+ oprindex += indexRelation->rd_am->amstrategies;
+ }
+ }
- index_close(indexRelation);
+ /* initialize cached join info to empty */
+ info->outer_relids = NIL;
+ info->inner_paths = NIL;
- indexinfos = lcons(info, indexinfos);
+ index_close(indexRelation);
+
+ indexinfos = lcons(info, indexinfos);
+ }
+
+ freeList(indexoidlist);
}
- freeList(indexoidlist);
+ rel->indexlist = indexinfos;
+
+ rel->pages = relation->rd_rel->relpages;
+ rel->tuples = relation->rd_rel->reltuples;
/* XXX keep the lock here? */
heap_close(relation, AccessShareLock);
-
- return indexinfos;
}
/*
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 06a73bf4e9e..ebfaa4924d4 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.45 2003/01/24 03:58:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.46 2003/02/03 15:07:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -143,6 +143,7 @@ make_base_rel(Query *root, int relid)
rel->cheapest_unique_path = NULL;
rel->pruneable = true;
rel->rtekind = rte->rtekind;
+ rel->varlist = NIL;
rel->indexlist = NIL;
rel->pages = 0;
rel->tuples = 0;
@@ -159,16 +160,9 @@ make_base_rel(Query *root, int relid)
switch (rte->rtekind)
{
case RTE_RELATION:
- {
- /* Table --- retrieve statistics from the system catalogs */
- bool indexed;
-
- get_relation_info(rte->relid,
- &indexed, &rel->pages, &rel->tuples);
- if (indexed)
- rel->indexlist = find_secondary_indexes(rte->relid);
- break;
- }
+ /* Table --- retrieve statistics from the system catalogs */
+ get_relation_info(rte->relid, rel);
+ break;
case RTE_SUBQUERY:
case RTE_FUNCTION:
/* Subquery or function --- nothing to do here */
@@ -304,6 +298,7 @@ build_join_rel(Query *root,
joinrel->cheapest_unique_path = NULL;
joinrel->pruneable = true;
joinrel->rtekind = RTE_JOIN;
+ joinrel->varlist = NIL;
joinrel->indexlist = NIL;
joinrel->pages = 0;
joinrel->tuples = 0;