aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/planmain.c6
-rw-r--r--src/backend/optimizer/plan/planner.c4
-rw-r--r--src/backend/optimizer/prep/prepunion.c29
-rw-r--r--src/backend/optimizer/util/relnode.c70
-rw-r--r--src/include/nodes/relation.h10
-rw-r--r--src/include/optimizer/pathnode.h3
6 files changed, 74 insertions, 48 deletions
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index 7a34abca048..b05adc70c4a 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -125,6 +125,12 @@ query_planner(PlannerInfo *root, List *tlist,
setup_simple_rel_arrays(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 in query, and
* indirectly for all appendrel member relations ("other rels"). This
* will give us a RelOptInfo for every "simple" (non-join) rel involved in
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 1f09fb6e6ad..fd45c9767df 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1163,6 +1163,7 @@ inheritance_planner(PlannerInfo *root)
List *final_rtable = NIL;
int save_rel_array_size = 0;
RelOptInfo **save_rel_array = NULL;
+ AppendRelInfo **save_append_rel_array = NULL;
List *subpaths = NIL;
List *subroots = NIL;
List *resultRelations = NIL;
@@ -1529,6 +1530,7 @@ inheritance_planner(PlannerInfo *root)
}
save_rel_array_size = subroot->simple_rel_array_size;
save_rel_array = subroot->simple_rel_array;
+ save_append_rel_array = subroot->append_rel_array;
/* Make sure any initplans from this rel get into the outer list */
root->init_plans = subroot->init_plans;
@@ -1579,6 +1581,8 @@ inheritance_planner(PlannerInfo *root)
parse->rtable = final_rtable;
root->simple_rel_array_size = save_rel_array_size;
root->simple_rel_array = save_rel_array;
+ root->append_rel_array = save_append_rel_array;
+
/* Must reconstruct master's simple_rte_array, too */
root->simple_rte_array = (RangeTblEntry **)
palloc0((list_length(final_rtable) + 1) * sizeof(RangeTblEntry *));
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 0ab4014be6d..2d470240d5d 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -167,6 +167,12 @@ plan_set_operations(PlannerInfo *root)
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).
*/
@@ -2617,29 +2623,22 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
AppendRelInfo **
find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
{
- ListCell *lc;
AppendRelInfo **appinfos;
int cnt = 0;
+ int i;
*nappinfos = bms_num_members(relids);
appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
- foreach(lc, root->append_rel_list)
+ i = -1;
+ while ((i = bms_next_member(relids, i)) >= 0)
{
- AppendRelInfo *appinfo = lfirst(lc);
+ AppendRelInfo *appinfo = root->append_rel_array[i];
- if (bms_is_member(appinfo->child_relid, relids))
- {
- appinfos[cnt] = appinfo;
- cnt++;
+ if (!appinfo)
+ elog(ERROR, "child rel %d not found in append_rel_array", i);
- /* Stop when we have gathered all the AppendRelInfos. */
- if (cnt == *nappinfos)
- return appinfos;
- }
+ appinfos[cnt++] = appinfo;
}
-
- /* Should have found the entries ... */
- elog(ERROR, "did not find all requested child rels in append_rel_list");
- return NULL; /* not reached */
+ return appinfos;
}
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 82b78420e79..c69740eda6c 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -89,6 +89,43 @@ setup_simple_rel_arrays(PlannerInfo *root)
}
/*
+ * 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;
+
+ if (root->append_rel_list == NIL)
+ {
+ root->append_rel_array = NULL;
+ return;
+ }
+
+ root->append_rel_array = (AppendRelInfo **)
+ palloc0(size * sizeof(AppendRelInfo *));
+
+ foreach(lc, root->append_rel_list)
+ {
+ AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
+ int child_relid = appinfo->child_relid;
+
+ /* Sanity check */
+ Assert(child_relid < size);
+
+ if (root->append_rel_array[child_relid])
+ elog(ERROR, "child relation already exists");
+
+ root->append_rel_array[child_relid] = appinfo;
+ }
+}
+
+/*
* build_simple_rel
* Construct a new RelOptInfo for a base relation or 'other' relation.
*/
@@ -1185,36 +1222,6 @@ fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
/*
- * find_childrel_appendrelinfo
- * Get the AppendRelInfo associated with an appendrel child rel.
- *
- * This search could be eliminated by storing a link in child RelOptInfos,
- * but for now it doesn't seem performance-critical. (Also, it might be
- * difficult to maintain such a link during mutation of the append_rel_list.)
- */
-AppendRelInfo *
-find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
-{
- Index relid = rel->relid;
- ListCell *lc;
-
- /* Should only be called on child rels */
- Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
-
- foreach(lc, root->append_rel_list)
- {
- AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
-
- if (appinfo->child_relid == relid)
- return appinfo;
- }
- /* should have found the entry ... */
- elog(ERROR, "child rel %d not found in append_rel_list", relid);
- return NULL; /* not reached */
-}
-
-
-/*
* find_childrel_parents
* Compute the set of parent relids of an appendrel child rel.
*
@@ -1228,10 +1235,11 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
Relids result = NULL;
Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
+ Assert(rel->relid > 0 && rel->relid < root->simple_rel_array_size);
do
{
- AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, rel);
+ AppendRelInfo *appinfo = root->append_rel_array[rel->relid];
Index prelid = appinfo->parent_relid;
result = bms_add_member(result, prelid);
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 5af484024ae..346cf089367 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -162,6 +162,8 @@ typedef struct PlannerGlobal
* the passed-in Query data structure; someday that should stop.
*----------
*/
+struct AppendRelInfo;
+
typedef struct PlannerInfo
{
NodeTag type;
@@ -202,6 +204,14 @@ typedef struct PlannerInfo
RangeTblEntry **simple_rte_array; /* rangetable as an array */
/*
+ * append_rel_list 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.
+ */
+ struct AppendRelInfo **append_rel_array;
+
+ /*
* all_baserels is a Relids set of all base relids (but not "other"
* relids) in the query; that is, the Relids identifier of the final join
* we need to form. This is computed in make_one_rel, just before we
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index e99ae36befb..4ba358e72dc 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -261,6 +261,7 @@ 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 RelOptInfo *build_simple_rel(PlannerInfo *root, int relid,
RelOptInfo *parent);
extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
@@ -278,8 +279,6 @@ extern Relids min_join_parameterization(PlannerInfo *root,
extern RelOptInfo *build_empty_join_rel(PlannerInfo *root);
extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind,
Relids relids);
-extern AppendRelInfo *find_childrel_appendrelinfo(PlannerInfo *root,
- RelOptInfo *rel);
extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel);
extern ParamPathInfo *get_baserel_parampathinfo(PlannerInfo *root,
RelOptInfo *baserel,