diff options
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
| -rw-r--r-- | src/backend/optimizer/util/relnode.c | 116 |
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]; } } |
