Re: BUG #18830: ExecInitMerge Segfault on MERGE

From: Tender Wang <tndrwang(at)gmail(dot)com>
To: David Rowley <dgrowleyml(at)gmail(dot)com>
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org, Amit Langote <amitlangote09(at)gmail(dot)com>, tharakan(at)gmail(dot)com
Subject: Re: BUG #18830: ExecInitMerge Segfault on MERGE
Date: 2025-03-04 09:45:57
Message-ID: CAHewXN=U0FPhkceSciQxqa8bJS_aY3+c4P8A+Nn=B_s0Xdbmtg@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

David Rowley <dgrowleyml(at)gmail(dot)com> 于2025年3月4日周二 17:30写道:

> On Tue, 4 Mar 2025 at 19:58, Tender Wang <tndrwang(at)gmail(dot)com> wrote:
> > I found the partition_prune.sql does not cover merge into ... not match
> case, and I found an easy reproduce step, seeing below:
> >
> > postgres=# merge into part_abc_view pt
> > using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on
> (true) on pt.a = stable_one() +2
> > when not matched then insert values(1, 'd', false);
> > server closed the connection unexpectedly
> > This probably means the server terminated abnormally
> > before or while processing the request.
> > The connection to the server was lost. Attempting reset: Succeeded.
>
> It looks like this is happening because ExecInitModifyTable() skips
> adding mergeActionsList items when bms_is_member(rti,
> estate->es_unpruned_relids) is false for all resultRelations. This
> results in an empty actions list. Because the MERGE is performing a
> LEFT JOIN for the NOT MATCHED, ExecMerge() gets a row and runs
> ExecMergeNotMatched(), which crashes on "econtext->ecxt_scantuple =
> NULL;" because of a NULL econtext. econtext is NULL because
> ExecInitMerge() skips calling ExecAssignExprContext() when
> mergeActionLists is empty.
>
> There are a couple of ways I can see to fix this, 1) would be to move
> the ExecAssignExprContext() above the "if (mergeActionLists == NIL)"
> in ExecInitMerge(), or 2) add code to return NULL in
> ExecMergeNotMatched() if actionStates is NULL.
>
> I think maybe #1 is the better option as #2 adds additional code that
> executes on every ExecMergeNotMatched() call. The patch does #1. We
> should probably add your test case too.
>
>
Hmm, apply your patch, I get different results when set
enable_partition_pruning = off, seeing below:
postgres=# merge into part_abc_view pt
using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (true)
on pt.a = stable_one() +2
when not matched then insert values(1, 'd', false);
MERGE 0
postgres=# set enable_partition_pruning = off;
SET
postgres=# merge into part_abc_view pt
using (select stable_one() + 2 as pid) as q join part_abc_1 pt1 on (true)
on pt.a = stable_one() +2
when not matched then insert values(1, 'd', false);
MERGE 1

if all partitions are pruned, the resultRelation's mergeActions has no
chance to be set.

--
Thanks,
Tender Wang

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Amit Langote 2025-03-04 10:09:46 Re: BUG #18830: ExecInitMerge Segfault on MERGE
Previous Message Amit Langote 2025-03-04 09:41:34 Re: BUG #18830: ExecInitMerge Segfault on MERGE