diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index df3f8c2544..f0c1b52a2e 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -79,9 +79,7 @@ query_planner(PlannerInfo *root, root->initial_rels = NIL; /* - * Make a flattened version of the rangetable for faster access (this is - * OK because the rangetable won't change any more), and set up an empty - * array for indexing base relations. + * Set up arrays for accessing base relations and AppendRelInfos. */ setup_simple_rel_arrays(root); @@ -156,12 +154,6 @@ query_planner(PlannerInfo *root, } } - /* - * Populate append_rel_array with each AppendRelInfo to allow direct - * lookups by child relid. - */ - setup_append_rel_array(root); - /* * Construct RelOptInfo nodes for all base relations used in the query. * Appendrel member relations ("other rels") will be added later. diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 5a11c1235c..b01c9bbae7 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -132,16 +132,10 @@ plan_set_operations(PlannerInfo *root) /* * We'll need to build RelOptInfos for each of the leaf subqueries, which * are RTE_SUBQUERY rangetable entries in this Query. Prepare the index - * arrays for that. + * arrays for those, and for AppendRelInfos in case they're needed. */ setup_simple_rel_arrays(root); - /* - * Populate append_rel_array with each AppendRelInfo to allow direct - * lookups by child relid. - */ - setup_append_rel_array(root); - /* * Find the leftmost component Query. We need to use its column names for * all generated tlists (else SELECT INTO won't work right). diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 37d228ce5d..582c5dd979 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -67,24 +67,30 @@ static void build_child_join_reltarget(PlannerInfo *root, /* * setup_simple_rel_arrays - * Prepare the arrays we use for quickly accessing base relations. + * Prepare the arrays we use for quickly accessing base relations + * and AppendRelInfos. */ void setup_simple_rel_arrays(PlannerInfo *root) { + int size; Index rti; ListCell *lc; /* Arrays are accessed using RT indexes (1..N) */ - root->simple_rel_array_size = list_length(root->parse->rtable) + 1; + size = list_length(root->parse->rtable) + 1; + root->simple_rel_array_size = size; - /* simple_rel_array is initialized to all NULLs */ + /* + * simple_rel_array is initialized to all NULLs, since no RelOptInfos + * exist yet. It'll be filled by later calls to build_simple_rel(). + */ root->simple_rel_array = (RelOptInfo **) - palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *)); + palloc0(size * sizeof(RelOptInfo *)); /* simple_rte_array is an array equivalent of the rtable list */ root->simple_rte_array = (RangeTblEntry **) - palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *)); + palloc0(size * sizeof(RangeTblEntry *)); rti = 1; foreach(lc, root->parse->rtable) { @@ -92,21 +98,8 @@ setup_simple_rel_arrays(PlannerInfo *root) root->simple_rte_array[rti++] = rte; } -} - -/* - * setup_append_rel_array - * Populate the append_rel_array to allow direct lookups of - * AppendRelInfos by child relid. - * - * The array remains unallocated if there are no AppendRelInfos. - */ -void -setup_append_rel_array(PlannerInfo *root) -{ - ListCell *lc; - int size = list_length(root->parse->rtable) + 1; + /* append_rel_array is not needed if there are no AppendRelInfos */ if (root->append_rel_list == NIL) { root->append_rel_array = NULL; @@ -116,6 +109,12 @@ setup_append_rel_array(PlannerInfo *root) root->append_rel_array = (AppendRelInfo **) palloc0(size * sizeof(AppendRelInfo *)); + /* + * append_rel_array is filled with any already-existing AppendRelInfos, + * which currently could only come from UNION ALL flattening. We might + * add more later during inheritance expansion, but it's the + * responsibility of the expansion code to update the array properly. + */ foreach(lc, root->append_rel_list) { AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc); @@ -135,6 +134,10 @@ setup_append_rel_array(PlannerInfo *root) * expand_planner_arrays * Expand the PlannerInfo's per-RTE arrays by add_size members * and initialize the newly added entries to NULLs + * + * Note: this causes the append_rel_array to become allocated even if + * it was not before. This is okay for current uses, because we only call + * this when adding child relations, which always have AppendRelInfos. */ void expand_planner_arrays(PlannerInfo *root, int add_size) @@ -145,18 +148,18 @@ expand_planner_arrays(PlannerInfo *root, int add_size) new_size = root->simple_rel_array_size + add_size; - root->simple_rte_array = (RangeTblEntry **) - repalloc(root->simple_rte_array, - sizeof(RangeTblEntry *) * new_size); - MemSet(root->simple_rte_array + root->simple_rel_array_size, - 0, sizeof(RangeTblEntry *) * add_size); - root->simple_rel_array = (RelOptInfo **) repalloc(root->simple_rel_array, sizeof(RelOptInfo *) * new_size); MemSet(root->simple_rel_array + root->simple_rel_array_size, 0, sizeof(RelOptInfo *) * add_size); + root->simple_rte_array = (RangeTblEntry **) + repalloc(root->simple_rte_array, + sizeof(RangeTblEntry *) * new_size); + MemSet(root->simple_rte_array + root->simple_rel_array_size, + 0, sizeof(RangeTblEntry *) * add_size); + if (root->append_rel_array) { root->append_rel_array = (AppendRelInfo **) diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index e3c579ee44..13b147d85d 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -204,17 +204,16 @@ struct PlannerInfo /* * simple_rte_array is the same length as simple_rel_array and holds - * pointers to the associated rangetable entries. This lets us avoid - * rt_fetch(), which can be a bit slow once large inheritance sets have - * been expanded. + * pointers to the associated rangetable entries. Using this is a shade + * faster than using rt_fetch(), mostly due to fewer indirections. */ RangeTblEntry **simple_rte_array; /* rangetable as an array */ /* * append_rel_array is the same length as the above arrays, and holds * pointers to the corresponding AppendRelInfo entry indexed by - * child_relid, or NULL if none. The array itself is not allocated if - * append_rel_list is empty. + * child_relid, or NULL if the rel is not an appendrel child. The array + * itself is not allocated if append_rel_list is empty. */ struct AppendRelInfo **append_rel_array; diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h index 182ffeef4b..a12af54971 100644 --- a/src/include/optimizer/pathnode.h +++ b/src/include/optimizer/pathnode.h @@ -277,7 +277,6 @@ extern Path *reparameterize_path_by_child(PlannerInfo *root, Path *path, * prototypes for relnode.c */ extern void setup_simple_rel_arrays(PlannerInfo *root); -extern void setup_append_rel_array(PlannerInfo *root); extern void expand_planner_arrays(PlannerInfo *root, int add_size); extern RelOptInfo *build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent);