summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c492
1 files changed, 307 insertions, 185 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 031e7097189..f08f1cdf7e7 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -25,6 +25,7 @@
#include "access/table.h"
#include "access/xact.h"
#include "catalog/pg_constraint.h"
+#include "catalog/pg_inherits.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
@@ -679,12 +680,14 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
flatten_simple_union_all(root);
/*
- * Detect whether any rangetable entries are RTE_JOIN kind; if not, we can
- * avoid the expense of doing flatten_join_alias_vars(). Likewise check
- * whether any are RTE_RESULT kind; if not, we can skip
- * remove_useless_result_rtes(). Also check for outer joins --- if none,
- * we can skip reduce_outer_joins(). And check for LATERAL RTEs, too.
- * This must be done after we have done pull_up_subqueries(), of course.
+ * Survey the rangetable to see what kinds of entries are present. We can
+ * skip some later processing if relevant SQL features are not used; for
+ * example if there are no JOIN RTEs we can avoid the expense of doing
+ * flatten_join_alias_vars(). This must be done after we have finished
+ * adding rangetable entries, of course. (Note: actually, processing of
+ * inherited or partitioned rels can cause RTEs for their child tables to
+ * get added later; but those must all be RTE_RELATION entries, so they
+ * don't invalidate the conclusions drawn here.)
*/
root->hasJoinRTEs = false;
root->hasLateralRTEs = false;
@@ -694,39 +697,49 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
{
RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
- if (rte->rtekind == RTE_JOIN)
+ switch (rte->rtekind)
{
- root->hasJoinRTEs = true;
- if (IS_OUTER_JOIN(rte->jointype))
- hasOuterJoins = true;
- }
- else if (rte->rtekind == RTE_RESULT)
- {
- hasResultRTEs = true;
+ case RTE_RELATION:
+ if (rte->inh)
+ {
+ /*
+ * Check to see if the relation actually has any children;
+ * if not, clear the inh flag so we can treat it as a
+ * plain base relation.
+ *
+ * Note: this could give a false-positive result, if the
+ * rel once had children but no longer does. We used to
+ * be able to clear rte->inh later on when we discovered
+ * that, but no more; we have to handle such cases as
+ * full-fledged inheritance.
+ */
+ rte->inh = has_subclass(rte->relid);
+ }
+ break;
+ case RTE_JOIN:
+ root->hasJoinRTEs = true;
+ if (IS_OUTER_JOIN(rte->jointype))
+ hasOuterJoins = true;
+ break;
+ case RTE_RESULT:
+ hasResultRTEs = true;
+ break;
+ default:
+ /* No work here for other RTE types */
+ break;
}
+
if (rte->lateral)
root->hasLateralRTEs = true;
}
/*
* Preprocess RowMark information. We need to do this after subquery
- * pullup (so that all non-inherited RTEs are present) and before
- * inheritance expansion (so that the info is available for
- * expand_inherited_tables to examine and modify).
+ * pullup, so that all base relations are present.
*/
preprocess_rowmarks(root);
/*
- * Expand any rangetable entries that are inheritance sets into "append
- * relations". This can add entries to the rangetable, but they must be
- * plain RTE_RELATION entries, so it's OK (and marginally more efficient)
- * to do it after checking for joins and other special RTEs. We must do
- * this after pulling up subqueries, else we'd fail to handle inherited
- * tables in subqueries.
- */
- expand_inherited_tables(root);
-
- /*
* Set hasHavingQual to remember if HAVING clause is present. Needed
* because preprocess_expression will reduce a constant-true condition to
* an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
@@ -1180,11 +1193,17 @@ inheritance_planner(PlannerInfo *root)
{
Query *parse = root->parse;
int top_parentRTindex = parse->resultRelation;
+ List *select_rtable;
+ List *select_appinfos;
+ List *child_appinfos;
+ List *old_child_rtis;
+ List *new_child_rtis;
Bitmapset *subqueryRTindexes;
- Bitmapset *modifiableARIindexes;
+ Index next_subquery_rti;
int nominalRelation = -1;
Index rootRelation = 0;
List *final_rtable = NIL;
+ List *final_rowmarks = NIL;
int save_rel_array_size = 0;
RelOptInfo **save_rel_array = NULL;
AppendRelInfo **save_append_rel_array = NULL;
@@ -1196,14 +1215,15 @@ inheritance_planner(PlannerInfo *root)
List *rowMarks;
RelOptInfo *final_rel;
ListCell *lc;
+ ListCell *lc2;
Index rti;
RangeTblEntry *parent_rte;
- PlannerInfo *parent_root;
- Query *parent_parse;
- Bitmapset *parent_relids = bms_make_singleton(top_parentRTindex);
- PlannerInfo **parent_roots = NULL;
+ Bitmapset *parent_relids;
+ Query **parent_parses;
- Assert(parse->commandType != CMD_INSERT);
+ /* Should only get here for UPDATE or DELETE */
+ Assert(parse->commandType == CMD_UPDATE ||
+ parse->commandType == CMD_DELETE);
/*
* We generate a modified instance of the original Query for each target
@@ -1234,39 +1254,14 @@ inheritance_planner(PlannerInfo *root)
}
/*
- * Next, we want to identify which AppendRelInfo items contain references
- * to any of the aforesaid subquery RTEs. These items will need to be
- * copied and modified to adjust their subquery references; whereas the
- * other ones need not be touched. It's worth being tense over this
- * because we can usually avoid processing most of the AppendRelInfo
- * items, thereby saving O(N^2) space and time when the target is a large
- * inheritance tree. We can identify AppendRelInfo items by their
- * child_relid, since that should be unique within the list.
- */
- modifiableARIindexes = NULL;
- if (subqueryRTindexes != NULL)
- {
- foreach(lc, root->append_rel_list)
- {
- AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
-
- if (bms_is_member(appinfo->parent_relid, subqueryRTindexes) ||
- bms_is_member(appinfo->child_relid, subqueryRTindexes) ||
- bms_overlap(pull_varnos((Node *) appinfo->translated_vars),
- subqueryRTindexes))
- modifiableARIindexes = bms_add_member(modifiableARIindexes,
- appinfo->child_relid);
- }
- }
-
- /*
* If the parent RTE is a partitioned table, we should use that as the
* nominal target relation, because the RTEs added for partitioned tables
* (including the root parent) as child members of the inheritance set do
* not appear anywhere else in the plan, so the confusion explained below
* for non-partitioning inheritance cases is not possible.
*/
- parent_rte = rt_fetch(top_parentRTindex, root->parse->rtable);
+ parent_rte = rt_fetch(top_parentRTindex, parse->rtable);
+ Assert(parent_rte->inh);
if (parent_rte->relkind == RELKIND_PARTITIONED_TABLE)
{
nominalRelation = top_parentRTindex;
@@ -1274,48 +1269,218 @@ inheritance_planner(PlannerInfo *root)
}
/*
- * The PlannerInfo for each child is obtained by translating the relevant
- * members of the PlannerInfo for its immediate parent, which we find
- * using the parent_relid in its AppendRelInfo. We save the PlannerInfo
- * for each parent in an array indexed by relid for fast retrieval. Since
- * the maximum number of parents is limited by the number of RTEs in the
- * query, we use that number to allocate the array. An extra entry is
- * needed since relids start from 1.
+ * Before generating the real per-child-relation plans, do a cycle of
+ * planning as though the query were a SELECT. The objective here is to
+ * find out which child relations need to be processed, using the same
+ * expansion and pruning logic as for a SELECT. We'll then pull out the
+ * RangeTblEntry-s generated for the child rels, and make use of the
+ * AppendRelInfo entries for them to guide the real planning. (This is
+ * rather inefficient; we could perhaps stop short of making a full Path
+ * tree. But this whole function is inefficient and slated for
+ * destruction, so let's not contort query_planner for that.)
+ */
+ {
+ PlannerInfo *subroot;
+
+ /*
+ * Flat-copy the PlannerInfo to prevent modification of the original.
+ */
+ subroot = makeNode(PlannerInfo);
+ memcpy(subroot, root, sizeof(PlannerInfo));
+
+ /*
+ * Make a deep copy of the parsetree for this planning cycle to mess
+ * around with, and change it to look like a SELECT. (Hack alert: the
+ * target RTE still has updatedCols set if this is an UPDATE, so that
+ * expand_partitioned_rtentry will correctly update
+ * subroot->partColsUpdated.)
+ */
+ subroot->parse = copyObject(root->parse);
+
+ subroot->parse->commandType = CMD_SELECT;
+ subroot->parse->resultRelation = 0;
+
+ /*
+ * Ensure the subroot has its own copy of the original
+ * append_rel_list, since it'll be scribbled on. (Note that at this
+ * point, the list only contains AppendRelInfos for flattened UNION
+ * ALL subqueries.)
+ */
+ subroot->append_rel_list = copyObject(root->append_rel_list);
+
+ /*
+ * Better make a private copy of the rowMarks, too.
+ */
+ subroot->rowMarks = copyObject(root->rowMarks);
+
+ /* There shouldn't be any OJ info to translate, as yet */
+ Assert(subroot->join_info_list == NIL);
+ /* and we haven't created PlaceHolderInfos, either */
+ Assert(subroot->placeholder_list == NIL);
+
+ /* Generate Path(s) for accessing this result relation */
+ grouping_planner(subroot, true, 0.0 /* retrieve all tuples */ );
+
+ /* Extract the info we need. */
+ select_rtable = subroot->parse->rtable;
+ select_appinfos = subroot->append_rel_list;
+
+ /*
+ * We need to propagate partColsUpdated back, too. (The later
+ * planning cycles will not set this because they won't run
+ * expand_partitioned_rtentry for the UPDATE target.)
+ */
+ root->partColsUpdated = subroot->partColsUpdated;
+ }
+
+ /*----------
+ * Since only one rangetable can exist in the final plan, we need to make
+ * sure that it contains all the RTEs needed for any child plan. This is
+ * complicated by the need to use separate subquery RTEs for each child.
+ * We arrange the final rtable as follows:
+ * 1. All original rtable entries (with their original RT indexes).
+ * 2. All the relation RTEs generated for children of the target table.
+ * 3. Subquery RTEs for children after the first. We need N * (K - 1)
+ * RT slots for this, if there are N subqueries and K child tables.
+ * 4. Additional RTEs generated during the child planning runs, such as
+ * children of inheritable RTEs other than the target table.
+ * We assume that each child planning run will create an identical set
+ * of type-4 RTEs.
+ *
+ * So the next thing to do is append the type-2 RTEs (the target table's
+ * children) to the original rtable. We look through select_appinfos
+ * to find them.
+ *
+ * To identify which AppendRelInfos are relevant as we thumb through
+ * select_appinfos, we need to look for both direct and indirect children
+ * of top_parentRTindex, so we use a bitmap of known parent relids.
+ * expand_inherited_rtentry() always processes a parent before any of that
+ * parent's children, so we should see an intermediate parent before its
+ * children.
+ *----------
+ */
+ child_appinfos = NIL;
+ old_child_rtis = NIL;
+ new_child_rtis = NIL;
+ parent_relids = bms_make_singleton(top_parentRTindex);
+ foreach(lc, select_appinfos)
+ {
+ AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
+ RangeTblEntry *child_rte;
+
+ /* append_rel_list contains all append rels; ignore others */
+ if (!bms_is_member(appinfo->parent_relid, parent_relids))
+ continue;
+
+ /* remember relevant AppendRelInfos for use below */
+ child_appinfos = lappend(child_appinfos, appinfo);
+
+ /* extract RTE for this child rel */
+ child_rte = rt_fetch(appinfo->child_relid, select_rtable);
+
+ /* and append it to the original rtable */
+ parse->rtable = lappend(parse->rtable, child_rte);
+
+ /* remember child's index in the SELECT rtable */
+ old_child_rtis = lappend_int(old_child_rtis, appinfo->child_relid);
+
+ /* and its new index in the final rtable */
+ new_child_rtis = lappend_int(new_child_rtis, list_length(parse->rtable));
+
+ /* if child is itself partitioned, update parent_relids */
+ if (child_rte->inh)
+ {
+ Assert(child_rte->relkind == RELKIND_PARTITIONED_TABLE);
+ parent_relids = bms_add_member(parent_relids, appinfo->child_relid);
+ }
+ }
+
+ /*
+ * It's possible that the RTIs we just assigned for the child rels in the
+ * final rtable are different from what they were in the SELECT query.
+ * Adjust the AppendRelInfos so that they will correctly map RT indexes to
+ * the final indexes. We can do this left-to-right since no child rel's
+ * final RT index could be greater than what it had in the SELECT query.
+ */
+ forboth(lc, old_child_rtis, lc2, new_child_rtis)
+ {
+ int old_child_rti = lfirst_int(lc);
+ int new_child_rti = lfirst_int(lc2);
+
+ if (old_child_rti == new_child_rti)
+ continue; /* nothing to do */
+
+ Assert(old_child_rti > new_child_rti);
+
+ ChangeVarNodes((Node *) child_appinfos,
+ old_child_rti, new_child_rti, 0);
+ }
+
+ /*
+ * Now set up rangetable entries for subqueries for additional children
+ * (the first child will just use the original ones). These all have to
+ * look more or less real, or EXPLAIN will get unhappy; so we just make
+ * them all clones of the original subqueries.
+ */
+ next_subquery_rti = list_length(parse->rtable) + 1;
+ if (subqueryRTindexes != NULL)
+ {
+ int n_children = list_length(child_appinfos);
+
+ while (n_children-- > 1)
+ {
+ int oldrti = -1;
+
+ while ((oldrti = bms_next_member(subqueryRTindexes, oldrti)) >= 0)
+ {
+ RangeTblEntry *subqrte;
+
+ subqrte = rt_fetch(oldrti, parse->rtable);
+ parse->rtable = lappend(parse->rtable, copyObject(subqrte));
+ }
+ }
+ }
+
+ /*
+ * The query for each child is obtained by translating the query for its
+ * immediate parent, since the AppendRelInfo data we have shows deltas
+ * between parents and children. We use the parent_parses array to
+ * remember the appropriate query trees. This is indexed by parent relid.
+ * Since the maximum number of parents is limited by the number of RTEs in
+ * the SELECT query, we use that number to allocate the array. An extra
+ * entry is needed since relids start from 1.
*/
- parent_roots = (PlannerInfo **) palloc0((list_length(parse->rtable) + 1) *
- sizeof(PlannerInfo *));
- parent_roots[top_parentRTindex] = root;
+ parent_parses = (Query **) palloc0((list_length(select_rtable) + 1) *
+ sizeof(Query *));
+ parent_parses[top_parentRTindex] = parse;
/*
* And now we can get on with generating a plan for each child table.
*/
- foreach(lc, root->append_rel_list)
+ foreach(lc, child_appinfos)
{
AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
+ Index this_subquery_rti = next_subquery_rti;
+ Query *parent_parse;
PlannerInfo *subroot;
RangeTblEntry *child_rte;
RelOptInfo *sub_final_rel;
Path *subpath;
- /* append_rel_list contains all append rels; ignore others */
- if (!bms_is_member(appinfo->parent_relid, parent_relids))
- continue;
-
/*
* expand_inherited_rtentry() always processes a parent before any of
- * that parent's children, so the parent_root for this relation should
- * already be available.
+ * that parent's children, so the parent query for this relation
+ * should already be available.
*/
- parent_root = parent_roots[appinfo->parent_relid];
- Assert(parent_root != NULL);
- parent_parse = parent_root->parse;
+ parent_parse = parent_parses[appinfo->parent_relid];
+ Assert(parent_parse != NULL);
/*
* We need a working copy of the PlannerInfo so that we can control
* propagation of information back to the main copy.
*/
subroot = makeNode(PlannerInfo);
- memcpy(subroot, parent_root, sizeof(PlannerInfo));
+ memcpy(subroot, root, sizeof(PlannerInfo));
/*
* Generate modified query with this rel as target. We first apply
@@ -1324,7 +1489,7 @@ inheritance_planner(PlannerInfo *root)
* then fool around with subquery RTEs.
*/
subroot->parse = (Query *)
- adjust_appendrel_attrs(parent_root,
+ adjust_appendrel_attrs(subroot,
(Node *) parent_parse,
1, &appinfo);
@@ -1360,9 +1525,7 @@ inheritance_planner(PlannerInfo *root)
if (child_rte->inh)
{
Assert(child_rte->relkind == RELKIND_PARTITIONED_TABLE);
- parent_relids = bms_add_member(parent_relids, appinfo->child_relid);
- parent_roots[appinfo->child_relid] = subroot;
-
+ parent_parses[appinfo->child_relid] = subroot->parse;
continue;
}
@@ -1383,108 +1546,38 @@ inheritance_planner(PlannerInfo *root)
* is used elsewhere in the plan, so using the original parent RTE
* would give rise to confusing use of multiple aliases in EXPLAIN
* output for what the user will think is the "same" table. OTOH,
- * it's not a problem in the partitioned inheritance case, because the
- * duplicate child RTE added for the parent does not appear anywhere
- * else in the plan tree.
+ * it's not a problem in the partitioned inheritance case, because
+ * there is no duplicate RTE for the parent.
*/
if (nominalRelation < 0)
nominalRelation = appinfo->child_relid;
/*
- * The rowMarks list might contain references to subquery RTEs, so
- * make a copy that we can apply ChangeVarNodes to. (Fortunately, the
- * executor doesn't need to see the modified copies --- we can just
- * pass it the original rowMarks list.)
- */
- subroot->rowMarks = copyObject(parent_root->rowMarks);
-
- /*
- * The append_rel_list likewise might contain references to subquery
- * RTEs (if any subqueries were flattenable UNION ALLs). So prepare
- * to apply ChangeVarNodes to that, too. As explained above, we only
- * want to copy items that actually contain such references; the rest
- * can just get linked into the subroot's append_rel_list.
- *
- * If we know there are no such references, we can just use the outer
- * append_rel_list unmodified.
- */
- if (modifiableARIindexes != NULL)
- {
- ListCell *lc2;
-
- subroot->append_rel_list = NIL;
- foreach(lc2, parent_root->append_rel_list)
- {
- AppendRelInfo *appinfo2 = lfirst_node(AppendRelInfo, lc2);
-
- if (bms_is_member(appinfo2->child_relid, modifiableARIindexes))
- appinfo2 = copyObject(appinfo2);
-
- subroot->append_rel_list = lappend(subroot->append_rel_list,
- appinfo2);
- }
- }
-
- /*
- * Add placeholders to the child Query's rangetable list to fill the
- * RT indexes already reserved for subqueries in previous children.
- * These won't be referenced, so there's no need to make them very
- * valid-looking.
+ * As above, each child plan run needs its own append_rel_list and
+ * rowmarks, which should start out as pristine copies of the
+ * originals. There can't be any references to UPDATE/DELETE target
+ * rels in them; but there could be subquery references, which we'll
+ * fix up in a moment.
*/
- while (list_length(subroot->parse->rtable) < list_length(final_rtable))
- subroot->parse->rtable = lappend(subroot->parse->rtable,
- makeNode(RangeTblEntry));
+ subroot->append_rel_list = copyObject(root->append_rel_list);
+ subroot->rowMarks = copyObject(root->rowMarks);
/*
- * If this isn't the first child Query, generate duplicates of all
- * subquery RTEs, and adjust Var numbering to reference the
- * duplicates. To simplify the loop logic, we scan the original rtable
- * not the copy just made by adjust_appendrel_attrs; that should be OK
- * since subquery RTEs couldn't contain any references to the target
- * rel.
+ * If this isn't the first child Query, adjust Vars and jointree
+ * entries to reference the appropriate set of subquery RTEs.
*/
if (final_rtable != NIL && subqueryRTindexes != NULL)
{
- ListCell *lr;
+ int oldrti = -1;
- rti = 1;
- foreach(lr, parent_parse->rtable)
+ while ((oldrti = bms_next_member(subqueryRTindexes, oldrti)) >= 0)
{
- RangeTblEntry *rte = lfirst_node(RangeTblEntry, lr);
-
- if (bms_is_member(rti, subqueryRTindexes))
- {
- Index newrti;
-
- /*
- * The RTE can't contain any references to its own RT
- * index, except in its securityQuals, so we can save a
- * few cycles by applying ChangeVarNodes to the rest of
- * the rangetable before we append the RTE to it.
- */
- newrti = list_length(subroot->parse->rtable) + 1;
- ChangeVarNodes((Node *) subroot->parse, rti, newrti, 0);
- ChangeVarNodes((Node *) subroot->rowMarks, rti, newrti, 0);
- /* Skip processing unchanging parts of append_rel_list */
- if (modifiableARIindexes != NULL)
- {
- ListCell *lc2;
-
- foreach(lc2, subroot->append_rel_list)
- {
- AppendRelInfo *appinfo2 = lfirst_node(AppendRelInfo, lc2);
+ Index newrti = next_subquery_rti++;
- if (bms_is_member(appinfo2->child_relid,
- modifiableARIindexes))
- ChangeVarNodes((Node *) appinfo2, rti, newrti, 0);
- }
- }
- rte = copyObject(rte);
- ChangeVarNodes((Node *) rte->securityQuals, rti, newrti, 0);
- subroot->parse->rtable = lappend(subroot->parse->rtable,
- rte);
- }
- rti++;
+ ChangeVarNodes((Node *) subroot->parse, oldrti, newrti, 0);
+ ChangeVarNodes((Node *) subroot->append_rel_list,
+ oldrti, newrti, 0);
+ ChangeVarNodes((Node *) subroot->rowMarks, oldrti, newrti, 0);
}
}
@@ -1514,22 +1607,43 @@ inheritance_planner(PlannerInfo *root)
/*
* If this is the first non-excluded child, its post-planning rtable
- * becomes the initial contents of final_rtable; otherwise, append
- * just its modified subquery RTEs to final_rtable.
+ * becomes the initial contents of final_rtable; otherwise, copy its
+ * modified subquery RTEs into final_rtable, to ensure we have sane
+ * copies of those. Also save the first non-excluded child's version
+ * of the rowmarks list; we assume all children will end up with
+ * equivalent versions of that.
*/
if (final_rtable == NIL)
+ {
final_rtable = subroot->parse->rtable;
+ final_rowmarks = subroot->rowMarks;
+ }
else
- final_rtable = list_concat(final_rtable,
- list_copy_tail(subroot->parse->rtable,
- list_length(final_rtable)));
+ {
+ Assert(list_length(final_rtable) ==
+ list_length(subroot->parse->rtable));
+ if (subqueryRTindexes != NULL)
+ {
+ int oldrti = -1;
+
+ while ((oldrti = bms_next_member(subqueryRTindexes, oldrti)) >= 0)
+ {
+ Index newrti = this_subquery_rti++;
+ RangeTblEntry *subqrte;
+ ListCell *newrticell;
+
+ subqrte = rt_fetch(newrti, subroot->parse->rtable);
+ newrticell = list_nth_cell(final_rtable, newrti - 1);
+ lfirst(newrticell) = subqrte;
+ }
+ }
+ }
/*
* We need to collect all the RelOptInfos from all child plans into
* the main PlannerInfo, since setrefs.c will need them. We use the
- * last child's simple_rel_array (previous ones are too short), so we
- * have to propagate forward the RelOptInfos that were already built
- * in previous children.
+ * last child's simple_rel_array, so we have to propagate forward the
+ * RelOptInfos that were already built in previous children.
*/
Assert(subroot->simple_rel_array_size >= save_rel_array_size);
for (rti = 1; rti < save_rel_array_size; rti++)
@@ -1543,7 +1657,11 @@ inheritance_planner(PlannerInfo *root)
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 */
+ /*
+ * Make sure any initplans from this rel get into the outer list. Note
+ * we're effectively assuming all children generate the same
+ * init_plans.
+ */
root->init_plans = subroot->init_plans;
/* Build list of sub-paths */
@@ -1626,6 +1744,9 @@ inheritance_planner(PlannerInfo *root)
root->simple_rte_array[rti++] = rte;
}
+
+ /* Put back adjusted rowmarks, too */
+ root->rowMarks = final_rowmarks;
}
/*
@@ -6127,9 +6248,10 @@ plan_create_index_workers(Oid tableOid, Oid indexOid)
/*
* Build a minimal RTE.
*
- * Set the target's table to be an inheritance parent. This is a kludge
- * that prevents problems within get_relation_info(), which does not
- * expect that any IndexOptInfo is currently undergoing REINDEX.
+ * Mark the RTE with inh = true. This is a kludge to prevent
+ * get_relation_info() from fetching index info, which is necessary
+ * because it does not expect that any IndexOptInfo is currently
+ * undergoing REINDEX.
*/
rte = makeNode(RangeTblEntry);
rte->rtekind = RTE_RELATION;