Skip to content

Commit cbb9086

Browse files
committed
Fix bug in cbc1279 to handle nested Append correctly
A non-leaf partition with a subplan that is an Append node was omitted from PlannedStmt.unprunableRelids because it was mistakenly included in PlannerGlobal.prunableRelids due to the way PartitionedRelPruneInfo.leafpart_rti_map[] is constructed. This happened when a non-leaf partition used an unflattened Append or MergeAppend. As a result, ExecGetRangeTableRelation() reported an error when called from CreatePartitionPruneState() to process the partition's own PartitionPruneInfo, since it was treated as prunable when it should not have been. Reported-by: Alexander Lakhin <exclusion@gmail.com> (via sqlsmith) Diagnosed-by: Tender Wang <tndrwang@gmail.com> Reviewed-by: Tender Wang <tndrwang@gmail.com> Discussion: https://postgr.es/m/74839af6-aadc-4f60-ae77-ae65f94bf607@gmail.com
1 parent 48796a9 commit cbb9086

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

src/backend/executor/execPartition.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2589,9 +2589,9 @@ ExecFindMatchingSubPlans(PartitionPruneState *prunestate,
25892589
* find_matching_subplans_recurse
25902590
* Recursive worker function for ExecFindMatchingSubPlans
25912591
*
2592-
* Adds valid (non-prunable) subplan IDs to *validsubplans and the RT indexes
2593-
* of their corresponding leaf partitions to *validsubplan_rtis if
2594-
* it's non-NULL.
2592+
* Adds valid (non-prunable) subplan IDs to *validsubplans. If
2593+
* *validsubplan_rtis is non-NULL, it also adds the RT indexes of their
2594+
* corresponding partitions, but only if they are leaf partitions.
25952595
*/
25962596
static void
25972597
find_matching_subplans_recurse(PartitionPruningData *prunedata,
@@ -2628,7 +2628,12 @@ find_matching_subplans_recurse(PartitionPruningData *prunedata,
26282628
{
26292629
*validsubplans = bms_add_member(*validsubplans,
26302630
pprune->subplan_map[i]);
2631-
if (validsubplan_rtis)
2631+
2632+
/*
2633+
* Only report leaf partitions. Non-leaf partitions may appear
2634+
* here when they use an unflattened Append or MergeAppend.
2635+
*/
2636+
if (validsubplan_rtis && pprune->leafpart_rti_map[i])
26322637
*validsubplan_rtis = bms_add_member(*validsubplan_rtis,
26332638
pprune->leafpart_rti_map[i]);
26342639
}

src/backend/partitioning/partprune.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,14 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
687687
if (subplanidx >= 0)
688688
{
689689
present_parts = bms_add_member(present_parts, i);
690-
leafpart_rti_map[i] = (int) partrel->relid;
690+
691+
/*
692+
* Non-leaf partitions may appear here when they use an
693+
* unflattened Append or MergeAppend. These should not be
694+
* included in prunableRelids.
695+
*/
696+
if (partrel->nparts == -1)
697+
leafpart_rti_map[i] = (int) partrel->relid;
691698

692699
/* Record finding this subplan */
693700
subplansfound = bms_add_member(subplansfound, subplanidx);

src/test/regress/expected/partition_prune.out

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,5 +4590,53 @@ table part_abc_view;
45904590
2 | c | t
45914591
(1 row)
45924592

4593+
-- A case with nested MergeAppend with its own PartitionPruneInfo.
4594+
create index on part_abc (a);
4595+
alter table part_abc add d int;
4596+
create table part_abc_3 partition of part_abc for values in (3, 4) partition by range (d);
4597+
create table part_abc_3_1 partition of part_abc_3 for values from (minvalue) to (1);
4598+
create table part_abc_3_2 partition of part_abc_3 for values from (1) to (100);
4599+
create table part_abc_3_3 partition of part_abc_3 for values from (100) to (maxvalue);
4600+
explain (costs off)
4601+
select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d <= stable_one()
4602+
union all
4603+
select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d >= stable_one();
4604+
QUERY PLAN
4605+
----------------------------------------------------------------------------------------------
4606+
Append
4607+
-> Subquery Scan on "*SELECT* 1_1"
4608+
-> WindowAgg
4609+
-> Append
4610+
Subplans Removed: 1
4611+
-> Index Scan using part_abc_2_a_idx on part_abc_2 part_abc_1
4612+
Index Cond: (a >= (stable_one() + 1))
4613+
Filter: (d <= stable_one())
4614+
-> Merge Append
4615+
Sort Key: part_abc_3.a
4616+
Subplans Removed: 1
4617+
-> Index Scan using part_abc_3_1_a_idx on part_abc_3_1 part_abc_3
4618+
Index Cond: (a >= (stable_one() + 1))
4619+
Filter: (d <= stable_one())
4620+
-> Index Scan using part_abc_3_2_a_idx on part_abc_3_2 part_abc_4
4621+
Index Cond: (a >= (stable_one() + 1))
4622+
Filter: (d <= stable_one())
4623+
-> Subquery Scan on "*SELECT* 2"
4624+
-> WindowAgg
4625+
-> Append
4626+
Subplans Removed: 1
4627+
-> Index Scan using part_abc_2_a_idx on part_abc_2 part_abc_6
4628+
Index Cond: (a >= (stable_one() + 1))
4629+
Filter: (d >= stable_one())
4630+
-> Merge Append
4631+
Sort Key: a
4632+
Subplans Removed: 1
4633+
-> Index Scan using part_abc_3_2_a_idx on part_abc_3_2 part_abc_8
4634+
Index Cond: (a >= (stable_one() + 1))
4635+
Filter: (d >= stable_one())
4636+
-> Index Scan using part_abc_3_3_a_idx on part_abc_3_3 part_abc_9
4637+
Index Cond: (a >= (stable_one() + 1))
4638+
Filter: (d >= stable_one())
4639+
(33 rows)
4640+
45934641
drop view part_abc_view;
45944642
drop table part_abc;

src/test/regress/sql/partition_prune.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,5 +1397,17 @@ using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (q.pid = pt1.
13971397
when matched then delete returning pt.a;
13981398
table part_abc_view;
13991399

1400+
-- A case with nested MergeAppend with its own PartitionPruneInfo.
1401+
create index on part_abc (a);
1402+
alter table part_abc add d int;
1403+
create table part_abc_3 partition of part_abc for values in (3, 4) partition by range (d);
1404+
create table part_abc_3_1 partition of part_abc_3 for values from (minvalue) to (1);
1405+
create table part_abc_3_2 partition of part_abc_3 for values from (1) to (100);
1406+
create table part_abc_3_3 partition of part_abc_3 for values from (100) to (maxvalue);
1407+
explain (costs off)
1408+
select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d <= stable_one()
1409+
union all
1410+
select min(a) over (partition by a order by a) from part_abc where a >= stable_one() + 1 and d >= stable_one();
1411+
14001412
drop view part_abc_view;
14011413
drop table part_abc;

0 commit comments

Comments
 (0)