Skip to content

Commit 589bb81

Browse files
committed
Fix setrefs.c code for adjusting partPruneInfos
We were transferring partPruneInfos from PlannerInfo into PlannerGlobal wrong, essentially relying on all of them being transferred, and adjusting their list indexes based on that. But apparently it's possible that some of them are skipped, so that strategy leads to a corrupted execution tree. Instead, adjust each Append/MergeAppend's partpruneinfo index as we copy from one list to the other, which seems safer anyway. This requires adjusting the RT offset of the RTE referenced in each partPruneInfo ahead of actually adjusting the RTE itself, which seems a bit too ad-hoc. This problem was introduced by commit ec38694. However, it may be that we no longer require the change introduced there, so perhaps we should revert both the present commit and that one. Problem noticed by sqlsmith. Author: Amit Langote <amitlangote09@gmail.com Discussion: https://postgr.es/m/CA+HiwqG6tbc2oadsbyyy24b2AL295XHQgyLRWghmA7u_SL1K8A@mail.gmail.com
1 parent f9054b7 commit 589bb81

File tree

1 file changed

+52
-31
lines changed

1 file changed

+52
-31
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,29 @@ set_plan_references(PlannerInfo *root, Plan *plan)
350350
palloc0(list_length(glob->subplans) * sizeof(bool));
351351
}
352352

353+
/* Also fix up the information in PartitionPruneInfos. */
354+
foreach(lc, root->partPruneInfos)
355+
{
356+
PartitionPruneInfo *pruneinfo = lfirst(lc);
357+
ListCell *l;
358+
359+
pruneinfo->root_parent_relids =
360+
offset_relid_set(pruneinfo->root_parent_relids, rtoffset);
361+
foreach(l, pruneinfo->prune_infos)
362+
{
363+
List *prune_infos = lfirst(l);
364+
ListCell *l2;
365+
366+
foreach(l2, prune_infos)
367+
{
368+
PartitionedRelPruneInfo *pinfo = lfirst(l2);
369+
370+
/* RT index of the table to which the pinfo belongs. */
371+
pinfo->rtindex += rtoffset;
372+
}
373+
}
374+
}
375+
353376
/* Now fix the Plan tree */
354377
result = set_plan_refs(root, plan, rtoffset);
355378

@@ -378,31 +401,6 @@ set_plan_references(PlannerInfo *root, Plan *plan)
378401
}
379402
}
380403

381-
/* Also fix up the information in PartitionPruneInfos. */
382-
foreach(lc, root->partPruneInfos)
383-
{
384-
PartitionPruneInfo *pruneinfo = lfirst(lc);
385-
ListCell *l;
386-
387-
pruneinfo->root_parent_relids =
388-
offset_relid_set(pruneinfo->root_parent_relids, rtoffset);
389-
foreach(l, pruneinfo->prune_infos)
390-
{
391-
List *prune_infos = lfirst(l);
392-
ListCell *l2;
393-
394-
foreach(l2, prune_infos)
395-
{
396-
PartitionedRelPruneInfo *pinfo = lfirst(l2);
397-
398-
/* RT index of the table to which the pinfo belongs. */
399-
pinfo->rtindex += rtoffset;
400-
}
401-
}
402-
403-
glob->partPruneInfos = lappend(glob->partPruneInfos, pruneinfo);
404-
}
405-
406404
return result;
407405
}
408406

@@ -1718,6 +1716,29 @@ set_customscan_references(PlannerInfo *root,
17181716
cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
17191717
}
17201718

1719+
/*
1720+
* register_partpruneinfo
1721+
* Subroutine for set_append_references and set_mergeappend_references
1722+
*
1723+
* Add the PartitionPruneInfo from root->partPruneInfos at the given index
1724+
* into PlannerGlobal->partPruneInfos and return its index there.
1725+
*/
1726+
static int
1727+
register_partpruneinfo(PlannerInfo *root, int part_prune_index)
1728+
{
1729+
PlannerGlobal *glob = root->glob;
1730+
PartitionPruneInfo *pruneinfo;
1731+
1732+
Assert(part_prune_index >= 0 &&
1733+
part_prune_index < list_length(root->partPruneInfos));
1734+
pruneinfo = list_nth_node(PartitionPruneInfo, root->partPruneInfos,
1735+
part_prune_index);
1736+
1737+
glob->partPruneInfos = lappend(glob->partPruneInfos, pruneinfo);
1738+
1739+
return list_length(glob->partPruneInfos) - 1;
1740+
}
1741+
17211742
/*
17221743
* set_append_references
17231744
* Do set_plan_references processing on an Append
@@ -1771,11 +1792,11 @@ set_append_references(PlannerInfo *root,
17711792
aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
17721793

17731794
/*
1774-
* PartitionPruneInfos will be added to a list in PlannerGlobal, so update
1775-
* the index.
1795+
* Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
17761796
*/
17771797
if (aplan->part_prune_index >= 0)
1778-
aplan->part_prune_index += list_length(root->glob->partPruneInfos);
1798+
aplan->part_prune_index =
1799+
register_partpruneinfo(root, aplan->part_prune_index);
17791800

17801801
/* We don't need to recurse to lefttree or righttree ... */
17811802
Assert(aplan->plan.lefttree == NULL);
@@ -1838,11 +1859,11 @@ set_mergeappend_references(PlannerInfo *root,
18381859
mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
18391860

18401861
/*
1841-
* PartitionPruneInfos will be added to a list in PlannerGlobal, so update
1842-
* the index.
1862+
* Add PartitionPruneInfo, if any, to PlannerGlobal and update the index.
18431863
*/
18441864
if (mplan->part_prune_index >= 0)
1845-
mplan->part_prune_index += list_length(root->glob->partPruneInfos);
1865+
mplan->part_prune_index =
1866+
register_partpruneinfo(root, mplan->part_prune_index);
18461867

18471868
/* We don't need to recurse to lefttree or righttree ... */
18481869
Assert(mplan->plan.lefttree == NULL);

0 commit comments

Comments
 (0)