Re: BUG #18830: ExecInitMerge Segfault on MERGE
Tender Wang <tndrwang@gmail.com>
From: Tender Wang <tndrwang@gmail.com>
To: Dean Rasheed <dean.a.rasheed@gmail.com>
Cc: Amit Langote <amitlangote09@gmail.com>,
David Rowley <dgrowleyml@gmail.com>, pgsql-bugs@lists.postgresql.org, tharakan@gmail.com
Date: 2025-03-12T16:11:24Z
Lists: pgsql-bugs
Dean Rasheed <dean.a.rasheed@gmail.com> 于2025年3月12日周三 22:59写道:
> On Wed, 12 Mar 2025 at 12:24, Amit Langote <amitlangote09@gmail.com>
> wrote:
> >
> > Thanks -- I’ve studied the code and I agree with the conclusion: when
> > all result relations are pruned, we still need to lock and process the
> > first one to preserve executor invariants.
> >
> > Your examples with ExecMerge() and ExecInitPartitionInfo() make the
> > consequences of missing resultRelInfo[0] pretty clear. Locking and
> > including the first result relation, even if pruned, seems like the
> > most straightforward way to maintain correctness without deeper
> > structural changes.
> >
> > I've come up with the attached. I'll still need to add a test case.
>
> Hmm, this isn't quite sufficient.
>
> In ExecDoInitialPruning(), stmt->resultRelations contains all the
> result relations plus the root relation (if set) of each ModifyTable
> node in the planned stmt (see set_plan_refs()). Therefore, just adding
> the first result relation in that list may not be sufficient to ensure
> that every ModifyTable node ends up with at least one unpruned result
> relation.
>
> For example, consider:
>
> create table foo (a int);
> create table part_abc (a int, b text, c bool) partition by list (a);
> create table part_abc_1 (b text, c bool, a int);
> create table part_abc_2 (b text, a int, c bool);
> alter table part_abc attach partition part_abc_1 for values in (1);
> alter table part_abc attach partition part_abc_2 for values in (2);
> insert into part_abc_1 values ('b', true, 1);
> insert into part_abc_2 values ('c', 2, true);
> create function stable_one() returns int as
> $$ begin return 1; end; $$ language plpgsql stable;
>
> with t as (
> merge into part_abc pt using (values(1)) v(a) on pt.a = stable_one() + 2
> when not matched then insert values (v.a, 'd', false)
> returning pt.*
> )
> insert into foo select a from t;
>
> ERROR: trying to open a pruned relation
>
Nice catch. The above case can be another test case.
I can find another same error in the below query:
with t as (update part_abc set c = true where a = stable_one() +2
returning a) insert into foo select a from t;
--
Thanks,
Tender Wang
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Ensure first ModifyTable rel initialized if all are pruned
- 28317de723b6 18.0 landed
-
Don't lock partitions pruned by initial pruning
- 525392d5727f 18.0 cited
-
Fix an oversight in cbc127917 to handle MERGE correctly
- 75dfde13639a 18.0 cited
-
Remove some unnecessary fields from Plan trees.
- 52ed730d511b 12.0 cited