From: | Tender Wang <tndrwang(at)gmail(dot)com> |
---|---|
To: | Amit Langote <amitlangote09(at)gmail(dot)com> |
Cc: | 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-04 11:06:25 |
Message-ID: | CAHewXN=7DyB7xf5jKpgCJE0UvL8iH=WkrFBYhcj4ryOxWhxmaw@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-bugs |
Amit Langote <amitlangote09(at)gmail(dot)com> 于2025年3月4日周二 18:10写道:
> On Tue, Mar 4, 2025 at 3:16 PM Tender Wang <tndrwang(at)gmail(dot)com> wrote:
> > 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
>
> Hmm, interesting. Can you share the full test case?
>
> What's the behavior on v17 and older? Just want to be sure if we're
> looking at another bug in the code committed in v18.
>
Because all partitions are pruned, so bms_is_member(rti,
estate->es_unpruned_relids) is false, then mergeActionLists is empty.
Even though we initialize econtext to not null, but
in ExecMergeNotMatched(),
because actionStates list is empty, so no merge operation happens.
actionStates is empty due to empty mergeActionLists.
--
Thanks,
Tender Wang
From | Date | Subject | |
---|---|---|---|
Next Message | Amit Langote | 2025-03-04 11:32:12 | Re: BUG #18830: ExecInitMerge Segfault on MERGE |
Previous Message | Bertrand Drouvot | 2025-03-04 10:45:54 | Re: BUG #18828: Crash when pg_get_logical_snapshot_meta() passed empty string |