Re: BUG #18830: ExecInitMerge Segfault on MERGE

From: Tender Wang <tndrwang(at)gmail(dot)com>
To: Dean Rasheed <dean(dot)a(dot)rasheed(at)gmail(dot)com>
Cc: Amit Langote <amitlangote09(at)gmail(dot)com>, David Rowley <dgrowleyml(at)gmail(dot)com>, pgsql-bugs(at)lists(dot)postgresql(dot)org, tharakan(at)gmail(dot)com
Subject: Re: BUG #18830: ExecInitMerge Segfault on MERGE
Date: 2025-03-12 16:11:24
Message-ID: CAHewXNkQpmfD1T4W0ORVR1KwOFWu6Oba7=71eh9-FEC2eFshPw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Dean Rasheed <dean(dot)a(dot)rasheed(at)gmail(dot)com> 于2025年3月12日周三 22:59写道:

> On Wed, 12 Mar 2025 at 12:24, Amit Langote <amitlangote09(at)gmail(dot)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

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Nathan Bossart 2025-03-12 19:03:04 Re: BUG #18828: Crash when pg_get_logical_snapshot_meta() passed empty string
Previous Message Tom Lane 2025-03-12 15:49:29 Re: Attribute of type record has wrong type error with MERGE ... WHEN NOT MATCHED BY SOURCE THEN DELETE