再次梳理 build_simple_rel 的执行内容:
/* * build_simple_rel * Construct a new RelOptInfo for a base relation or 'other' relation. */ RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind) { RelOptInfo *rel; RangeTblEntry *rte; /* Rel should not exist already */ Assert(relid > 0 && relid < root->simple_rel_array_size); if (root->simple_rel_array[relid] != NULL) elog(ERROR, "rel %d already exists", relid); /* Fetch RTE for relation */ rte = root->simple_rte_array[relid]; Assert(rte != NULL); rel = makeNode(RelOptInfo); rel->reloptkind = reloptkind; rel->relids = bms_make_singleton(relid); rel->rows = 0; ... rel->has_eclass_joins = false; /* Check type of rtable entry */ switch (rte->rtekind) { case RTE_RELATION: /* Table --- retrieve statistics from the system catalogs */ get_relation_info(root, rte->relid, rte->inh, rel); break; case RTE_SUBQUERY: case RTE_FUNCTION: case RTE_VALUES: case RTE_CTE: /* * Subquery, function, or values list --- set up attr range and * arrays * * Note: 0 is included in range to support whole-row Vars */ rel->min_attr = 0; rel->max_attr = list_length(rte->eref->colnames); rel->attr_needed = (Relids *) palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids)); rel->attr_widths = (int32 *) palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32)); break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind); break; } /* Save the finished struct in the query's simple_rel_array */ root->simple_rel_array[relid] = rel; ... return rel; }
可以看出,这是准备了 表信息的结构--RelOptInfo,然后再把它挂在计划树上:
root->simple_rel_array[relid] = rel;
需要注意的是,这里 relid 是 simple_rel_array数组的下标,而非oid。