Skip to content

Commit 7a980df

Browse files
committed
Fix matching of sub-partitions when a partitioned plan is stale.
Since we no longer require AccessExclusiveLock to add a partition, the executor may see that a partitioned table has more partitions than the planner saw. ExecCreatePartitionPruneState's code for matching up the partition lists in such cases was faulty, and would misbehave if the planner had successfully pruned any partitions from the query. (Thus, trouble would occur only if a partition addition happens concurrently with a query that uses both static and dynamic partition pruning.) This led to an Assert failure in debug builds, and probably to crashes or query misbehavior in production builds. To repair the bug, just explicitly skip zeroes in the plan's relid_map[] list. I also made some cosmetic changes to make the code more readable (IMO anyway). Also, convert the cross-checking Assert to a regular test-and-elog, since it's now apparent that this logic is more fragile than one would like. Currently, there's no way to repeatably exercise this code, except with manual use of a debugger to stop the backend between planning and execution. Hence, no test case in this patch. We oughta do something about that testability gap, but that's for another day. Amit Langote and Tom Lane, per report from Justin Pryzby. Oversight in commit 898e5e3; backpatch to v12 where that appeared. Discussion: https://postgr.es/m/20200802181131.GA27754@telsasoft.com
1 parent f47b5e1 commit 7a980df

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

src/backend/executor/execPartition.c

+36-11
Original file line numberDiff line numberDiff line change
@@ -1667,26 +1667,51 @@ ExecCreatePartitionPruneState(PlanState *planstate,
16671667
* present in the one used to construct subplan_map and
16681668
* subpart_map. So we must construct new and longer arrays
16691669
* where the partitions that were originally present map to
1670-
* the same place, and any added indexes map to -1, as if the
1671-
* new partitions had been pruned.
1670+
* the same sub-structures, and any added partitions map to
1671+
* -1, as if the new partitions had been pruned.
1672+
*
1673+
* Note: pinfo->relid_map[] may contain InvalidOid entries for
1674+
* partitions pruned by the planner. We cannot tell exactly
1675+
* which of the partdesc entries these correspond to, but we
1676+
* don't have to; just skip over them. The non-pruned
1677+
* relid_map entries, however, had better be a subset of the
1678+
* partdesc entries and in the same order.
16721679
*/
16731680
pprune->subpart_map = palloc(sizeof(int) * partdesc->nparts);
1674-
for (pp_idx = 0; pp_idx < partdesc->nparts; ++pp_idx)
1681+
for (pp_idx = 0; pp_idx < partdesc->nparts; pp_idx++)
16751682
{
1676-
if (pinfo->relid_map[pd_idx] != partdesc->oids[pp_idx])
1677-
{
1678-
pprune->subplan_map[pp_idx] = -1;
1679-
pprune->subpart_map[pp_idx] = -1;
1680-
}
1681-
else
1683+
/* Skip any InvalidOid relid_map entries */
1684+
while (pd_idx < pinfo->nparts &&
1685+
!OidIsValid(pinfo->relid_map[pd_idx]))
1686+
pd_idx++;
1687+
1688+
if (pd_idx < pinfo->nparts &&
1689+
pinfo->relid_map[pd_idx] == partdesc->oids[pp_idx])
16821690
{
1691+
/* match... */
16831692
pprune->subplan_map[pp_idx] =
16841693
pinfo->subplan_map[pd_idx];
16851694
pprune->subpart_map[pp_idx] =
1686-
pinfo->subpart_map[pd_idx++];
1695+
pinfo->subpart_map[pd_idx];
1696+
pd_idx++;
1697+
}
1698+
else
1699+
{
1700+
/* this partdesc entry is not in the plan */
1701+
pprune->subplan_map[pp_idx] = -1;
1702+
pprune->subpart_map[pp_idx] = -1;
16871703
}
16881704
}
1689-
Assert(pd_idx == pinfo->nparts);
1705+
1706+
/*
1707+
* It might seem that we need to skip any trailing InvalidOid
1708+
* entries in pinfo->relid_map before checking that we scanned
1709+
* all of the relid_map. But we will have skipped them above,
1710+
* because they must correspond to some partdesc->oids
1711+
* entries; we just couldn't tell which.
1712+
*/
1713+
if (pd_idx != pinfo->nparts)
1714+
elog(ERROR, "could not match partition child tables to plan elements");
16901715
}
16911716

16921717
/* present_parts is also subject to later modification */

0 commit comments

Comments
 (0)