Commit 1555566d authored by Robert Haas's avatar Robert Haas

Set partitioned_rels appropriately when UNION ALL is used.

In most cases, this omission won't matter, because the appropriate
locks will have been acquired during parse/plan or by AcquireExecutorLocks.
But it's a bug all the same.

Report by Ashutosh Bapat.  Patch by me, reviewed by Amit Langote.

Discussion: http://postgr.es/m/CAFjFpRdHb_ZnoDTuBXqrudWXh3H1ibLkr6nHsCFT96fSK4DXtA@mail.gmail.com
parent 1ab973ab
...@@ -1287,13 +1287,34 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, ...@@ -1287,13 +1287,34 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
ListCell *l; ListCell *l;
List *partitioned_rels = NIL; List *partitioned_rels = NIL;
RangeTblEntry *rte; RangeTblEntry *rte;
bool build_partitioned_rels = false;
/*
* A plain relation will already have a PartitionedChildRelInfo if it is
* partitioned. For a subquery RTE, no PartitionedChildRelInfo exists; we
* collect all partitioned_rels associated with any child. (This assumes
* that we don't need to look through multiple levels of subquery RTEs; if
* we ever do, we could create a PartitionedChildRelInfo with the
* accumulated list of partitioned_rels which would then be found when
* populated our parent rel with paths. For the present, that appears to
* be unnecessary.)
*/
rte = planner_rt_fetch(rel->relid, root); rte = planner_rt_fetch(rel->relid, root);
if (rte->relkind == RELKIND_PARTITIONED_TABLE) switch (rte->rtekind)
{ {
partitioned_rels = get_partitioned_child_rels(root, rel->relid); case RTE_RELATION:
/* The root partitioned table is included as a child rel */ if (rte->relkind == RELKIND_PARTITIONED_TABLE)
Assert(list_length(partitioned_rels) >= 1); {
partitioned_rels =
get_partitioned_child_rels(root, rel->relid);
Assert(list_length(partitioned_rels) >= 1);
}
break;
case RTE_SUBQUERY:
build_partitioned_rels = true;
break;
default:
elog(ERROR, "unexpcted rtekind: %d", (int) rte->rtekind);
} }
/* /*
...@@ -1306,6 +1327,19 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel, ...@@ -1306,6 +1327,19 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
RelOptInfo *childrel = lfirst(l); RelOptInfo *childrel = lfirst(l);
ListCell *lcp; ListCell *lcp;
/*
* If we need to build partitioned_rels, accumulate the partitioned
* rels for this child.
*/
if (build_partitioned_rels)
{
List *cprels;
cprels = get_partitioned_child_rels(root, childrel->relid);
partitioned_rels = list_concat(partitioned_rels,
list_copy(cprels));
}
/* /*
* If child has an unparameterized cheapest-total path, add that to * If child has an unparameterized cheapest-total path, add that to
* the unparameterized Append path we are constructing for the parent. * the unparameterized Append path we are constructing for the parent.
......
...@@ -6076,7 +6076,8 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) ...@@ -6076,7 +6076,8 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
* Returns a list of the RT indexes of the partitioned child relations * Returns a list of the RT indexes of the partitioned child relations
* with rti as the root parent RT index. * with rti as the root parent RT index.
* *
* Note: Only call this function on RTEs known to be partitioned tables. * Note: This function might get called even for range table entries that
* are not partitioned tables; in such a case, it will simply return NIL.
*/ */
List * List *
get_partitioned_child_rels(PlannerInfo *root, Index rti) get_partitioned_child_rels(PlannerInfo *root, Index rti)
...@@ -6095,8 +6096,5 @@ get_partitioned_child_rels(PlannerInfo *root, Index rti) ...@@ -6095,8 +6096,5 @@ get_partitioned_child_rels(PlannerInfo *root, Index rti)
} }
} }
/* The root partitioned table is included as a child rel */
Assert(list_length(result) >= 1);
return result; return result;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment