summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/relnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r--src/backend/optimizer/util/relnode.c116
1 files changed, 33 insertions, 83 deletions
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index cef0c63a66..cedb808227 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.74 2005/12/20 02:30:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.75 2006/01/31 21:39:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,8 +30,6 @@ typedef struct JoinHashEntry
RelOptInfo *join_rel;
} JoinHashEntry;
-static RelOptInfo *make_reloptinfo(PlannerInfo *root, int relid,
- RelOptKind reloptkind);
static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *input_rel);
static List *build_joinrel_restrictlist(PlannerInfo *root,
@@ -49,71 +47,25 @@ static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,
/*
- * build_base_rel
- * Construct a new base relation RelOptInfo, and put it in the query's
- * base_rel_array.
- */
-void
-build_base_rel(PlannerInfo *root, int relid)
-{
- Assert(relid > 0);
-
- /* Rel should not exist already */
- if (relid < root->base_rel_array_size &&
- root->base_rel_array[relid] != NULL)
- elog(ERROR, "rel already exists");
-
- /* No existing RelOptInfo for this base rel, so make a new one */
- (void) make_reloptinfo(root, relid, RELOPT_BASEREL);
-}
-
-/*
- * build_other_rel
- * Returns relation entry corresponding to 'relid', creating a new one
- * if necessary. This is for 'other' relations, which are much like
- * base relations except that they have a different RelOptKind.
+ * build_simple_rel
+ * Construct a new RelOptInfo for a base relation or 'other' relation.
*/
RelOptInfo *
-build_other_rel(PlannerInfo *root, int relid)
+build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
{
RelOptInfo *rel;
+ RangeTblEntry *rte;
- Assert(relid > 0);
-
- /* Already made? */
- if (relid < root->base_rel_array_size)
- {
- rel = root->base_rel_array[relid];
- if (rel)
- {
- /* it should not exist as a base rel */
- if (rel->reloptkind == RELOPT_BASEREL)
- elog(ERROR, "rel already exists as base rel");
- /* otherwise, A-OK */
- return rel;
- }
- }
+ /* Fetch RTE for relation */
+ Assert(relid > 0 && relid <= list_length(root->parse->rtable));
+ rte = rt_fetch(relid, root->parse->rtable);
- /* No existing RelOptInfo for this other rel, so make a new one */
- /* presently, must be an inheritance child rel */
- rel = make_reloptinfo(root, relid, RELOPT_OTHER_CHILD_REL);
-
- return rel;
-}
-
-/*
- * make_reloptinfo
- * Construct a RelOptInfo for the specified rangetable index,
- * and enter it into base_rel_array.
- *
- * Common code for build_base_rel and build_other_rel.
- */
-static RelOptInfo *
-make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind)
-{
- RelOptInfo *rel = makeNode(RelOptInfo);
- RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
+ /* Rel should not exist already */
+ Assert(relid < root->simple_rel_array_size);
+ if (root->simple_rel_array[relid] != NULL)
+ elog(ERROR, "rel %d already exists", relid);
+ rel = makeNode(RelOptInfo);
rel->reloptkind = reloptkind;
rel->relids = bms_make_singleton(relid);
rel->rows = 0;
@@ -161,21 +113,8 @@ make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind)
break;
}
- /* Add the finished struct to the base_rel_array */
- if (relid >= root->base_rel_array_size)
- {
- int oldsize = root->base_rel_array_size;
- int newsize;
-
- newsize = Max(oldsize * 2, relid + 1);
- root->base_rel_array = (RelOptInfo **)
- repalloc(root->base_rel_array, newsize * sizeof(RelOptInfo *));
- MemSet(root->base_rel_array + oldsize, 0,
- (newsize - oldsize) * sizeof(RelOptInfo *));
- root->base_rel_array_size = newsize;
- }
-
- root->base_rel_array[relid] = rel;
+ /* Save the finished struct in the query's simple_rel_array */
+ root->simple_rel_array[relid] = rel;
return rel;
}
@@ -191,9 +130,9 @@ find_base_rel(PlannerInfo *root, int relid)
Assert(relid > 0);
- if (relid < root->base_rel_array_size)
+ if (relid < root->simple_rel_array_size)
{
- rel = root->base_rel_array[relid];
+ rel = root->simple_rel_array[relid];
if (rel)
return rel;
}
@@ -446,12 +385,24 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
foreach(vars, input_rel->reltargetlist)
{
- Var *var = (Var *) lfirst(vars);
+ Var *origvar = (Var *) lfirst(vars);
+ Var *var;
RelOptInfo *baserel;
int ndx;
- /* We can't run into any child RowExprs here */
- Assert(IsA(var, Var));
+ /*
+ * We can't run into any child RowExprs here, but we could find
+ * a whole-row Var with a ConvertRowtypeExpr atop it.
+ */
+ var = origvar;
+ while (!IsA(var, Var))
+ {
+ if (IsA(var, ConvertRowtypeExpr))
+ var = (Var *) ((ConvertRowtypeExpr *) var)->arg;
+ else
+ elog(ERROR, "unexpected node type in reltargetlist: %d",
+ (int) nodeTag(var));
+ }
/* Get the Var's original base rel */
baserel = find_base_rel(root, var->varno);
@@ -461,8 +412,7 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))
{
/* Yup, add it to the output */
- joinrel->reltargetlist = lappend(joinrel->reltargetlist, var);
- Assert(baserel->attr_widths[ndx] > 0);
+ joinrel->reltargetlist = lappend(joinrel->reltargetlist, origvar);
joinrel->width += baserel->attr_widths[ndx];
}
}