Re: BUG #18830: ExecInitMerge Segfault on MERGE - Mailing list pgsql-bugs

From Tender Wang
Subject Re: BUG #18830: ExecInitMerge Segfault on MERGE
Date
Msg-id CAHewXN=U0FPhkceSciQxqa8bJS_aY3+c4P8A+Nn=B_s0Xdbmtg@mail.gmail.com
Whole thread Raw
In response to Re: BUG #18830: ExecInitMerge Segfault on MERGE  (David Rowley <dgrowleyml@gmail.com>)
Responses Re: BUG #18830: ExecInitMerge Segfault on MERGE
List pgsql-bugs


David Rowley <dgrowleyml@gmail.com> 于2025年3月4日周二 17:30写道:
On Tue, 4 Mar 2025 at 19:58, Tender Wang <tndrwang@gmail.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

pgsql-bugs by date:

Previous
From: Amit Langote
Date:
Subject: Re: BUG #18830: ExecInitMerge Segfault on MERGE
Next
From: Amit Langote
Date:
Subject: Re: BUG #18830: ExecInitMerge Segfault on MERGE