aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r--src/backend/optimizer/path/allpaths.c35
-rw-r--r--src/backend/optimizer/path/costsize.c60
-rw-r--r--src/backend/optimizer/path/pathkeys.c16
3 files changed, 67 insertions, 44 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index e6791dddd69..cd04af9f821 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.102 2003/04/24 23:43:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.103 2003/06/29 23:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -235,6 +235,9 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
RangeTblEntry *childrte;
Oid childOID;
RelOptInfo *childrel;
+ List *reltlist;
+ List *parentvars;
+ List *childvars;
childrte = rt_fetch(childRTindex, root->rtable);
childOID = childrte->relid;
@@ -251,21 +254,24 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
* Copy the parent's targetlist and restriction quals to the
* child, with attribute-number adjustment as needed. We don't
* bother to copy the join quals, since we can't do any joining of
- * the individual tables.
+ * the individual tables. Also, we just zap attr_needed rather
+ * than trying to adjust it; it won't be looked at in the child.
*/
- childrel->targetlist = (List *)
- adjust_inherited_attrs((Node *) rel->targetlist,
+ reltlist = FastListValue(&rel->reltargetlist);
+ reltlist = (List *)
+ adjust_inherited_attrs((Node *) reltlist,
parentRTindex,
parentOID,
childRTindex,
childOID);
+ FastListFromList(&childrel->reltargetlist, reltlist);
+ childrel->attr_needed = NULL;
childrel->baserestrictinfo = (List *)
adjust_inherited_attrs((Node *) rel->baserestrictinfo,
parentRTindex,
parentOID,
childRTindex,
childOID);
- childrel->baserestrictcost = rel->baserestrictcost;
/*
* Now compute child access paths, and save the cheapest.
@@ -274,10 +280,27 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
subpaths = lappend(subpaths, childrel->cheapest_total_path);
- /* Also update total size estimates */
+ /*
+ * Propagate size information from the child back to the parent.
+ * For simplicity, we use the largest widths from any child as the
+ * parent estimates.
+ */
rel->rows += childrel->rows;
if (childrel->width > rel->width)
rel->width = childrel->width;
+
+ childvars = FastListValue(&childrel->reltargetlist);
+ foreach(parentvars, FastListValue(&rel->reltargetlist))
+ {
+ Var *parentvar = (Var *) lfirst(parentvars);
+ Var *childvar = (Var *) lfirst(childvars);
+ int parentndx = parentvar->varattno - rel->min_attr;
+ int childndx = childvar->varattno - childrel->min_attr;
+
+ if (childrel->attr_widths[childndx] > rel->attr_widths[parentndx])
+ rel->attr_widths[parentndx] = childrel->attr_widths[childndx];
+ childvars = lnext(childvars);
+ }
}
/*
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 283987b63d5..34a3aaf1c94 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.108 2003/06/29 00:33:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.109 2003/06/29 23:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1792,13 +1792,9 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
rel->rows = temp;
/*
- * We could apply set_rel_width() to compute the output tuple width
- * from scratch, but at present it's always just the sum of the input
- * widths, so why work harder than necessary? If relnode.c is ever
- * taught to remove unneeded columns from join targetlists, go back to
- * using set_rel_width here.
+ * We need not compute the output width here, because build_joinrel_tlist
+ * already did.
*/
- rel->width = outer_rel->width + inner_rel->width;
}
/*
@@ -1858,13 +1854,16 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
/*
* set_rel_width
- * Set the estimated output width of the relation.
+ * Set the estimated output width of a base relation.
*
- * NB: this works best on base relations because it prefers to look at
+ * NB: this works best on plain relations because it prefers to look at
* real Vars. It will fail to make use of pg_statistic info when applied
* to a subquery relation, even if the subquery outputs are simple vars
* that we could have gotten info for. Is it worth trying to be smarter
* about subqueries?
+ *
+ * The per-attribute width estimates are cached for possible re-use while
+ * building join relations.
*/
static void
set_rel_width(Query *root, RelOptInfo *rel)
@@ -1872,38 +1871,41 @@ set_rel_width(Query *root, RelOptInfo *rel)
int32 tuple_width = 0;
List *tllist;
- foreach(tllist, rel->targetlist)
+ foreach(tllist, FastListValue(&rel->reltargetlist))
{
- TargetEntry *tle = (TargetEntry *) lfirst(tllist);
+ Var *var = (Var *) lfirst(tllist);
+ int ndx = var->varattno - rel->min_attr;
+ Oid relid;
int32 item_width;
- /*
- * If it's a Var, try to get statistical info from pg_statistic.
- */
- if (tle->expr && IsA(tle->expr, Var))
+ Assert(IsA(var, Var));
+
+ /* The width probably hasn't been cached yet, but may as well check */
+ if (rel->attr_widths[ndx] > 0)
{
- Var *var = (Var *) tle->expr;
- Oid relid;
+ tuple_width += rel->attr_widths[ndx];
+ continue;
+ }
- relid = getrelid(var->varno, root->rtable);
- if (relid != InvalidOid)
+ relid = getrelid(var->varno, root->rtable);
+ if (relid != InvalidOid)
+ {
+ item_width = get_attavgwidth(relid, var->varattno);
+ if (item_width > 0)
{
- item_width = get_attavgwidth(relid, var->varattno);
- if (item_width > 0)
- {
- tuple_width += item_width;
- continue;
- }
+ rel->attr_widths[ndx] = item_width;
+ tuple_width += item_width;
+ continue;
}
}
/*
- * Not a Var, or can't find statistics for it. Estimate using
- * just the type info.
+ * Not a plain relation, or can't find statistics for it.
+ * Estimate using just the type info.
*/
- item_width = get_typavgwidth(tle->resdom->restype,
- tle->resdom->restypmod);
+ item_width = get_typavgwidth(var->vartype, var->vartypmod);
Assert(item_width > 0);
+ rel->attr_widths[ndx] = item_width;
tuple_width += item_width;
}
Assert(tuple_width >= 0);
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index f8e4906c13b..d4d1179d545 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.49 2003/05/28 16:03:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.50 2003/06/29 23:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -703,20 +703,18 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
vartypeid;
int32 type_mod;
- foreach(temp, rel->targetlist)
+ foreach(temp, FastListValue(&rel->reltargetlist))
{
- Var *tle_var = (Var *) ((TargetEntry *) lfirst(temp))->expr;
+ Var *var = (Var *) lfirst(temp);
- if (IsA(tle_var, Var) &&
- tle_var->varattno == varattno)
- return tle_var;
+ if (IsA(var, Var) &&
+ var->varattno == varattno)
+ return var;
}
relid = rel->relid;
- Assert(relid > 0);
reloid = getrelid(relid, root->rtable);
- vartypeid = get_atttype(reloid, varattno);
- type_mod = get_atttypmod(reloid, varattno);
+ get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod);
return makeVar(relid, varattno, vartypeid, type_mod, 0);
}