Re: BUG #18238: Cross-partitition MERGE/UPDATE with delete-preventing trigger leads to incorrect memory access
Richard Guo <guofenglinux@gmail.com>
From: Richard Guo <guofenglinux@gmail.com>
To: Dean Rasheed <dean.a.rasheed@gmail.com>
Cc: jian he <jian.universality@gmail.com>, exclusion@gmail.com, pgsql-bugs@lists.postgresql.org
Date: 2023-12-12T09:50:27Z
Lists: pgsql-bugs
On Mon, Dec 11, 2023 at 8:53 PM Dean Rasheed <dean.a.rasheed@gmail.com> wrote: > The easiest way to do that is to have ExecDelete() return the > TM_Result status to ExecCrossPartitionUpdate(). I think > ExecCrossPartitionUpdate() should then return the TM_Result status to > ExecUpdateAct(), so that it can return the correct status, rather than > just assuming TM_Updated on failure, though possibly that's not > strictly necessary. > The simplest fix is for ExecMergeMatched() to pass canSetTag to > ExecUpdateAct(), so that it updates the command tag, if it does a > cross-partition update. That makes that code path in > ExecMergeMatched() more consistent with ExecUpdate(). > > So I think we need something like the attached. I think this is the right way to go. +1. BTW, while testing this patch, I encountered some confusion regarding cross-partition update. As we know, cross-partition update works by first deleting the old tuple from the current partition. So if we have BEFORE ROW DELETE triggers that suppress the delete, the update would be suppressed. For in-partition update, there is no such problem. For instance (based on Alexander's query): CREATE TABLE t (a int) PARTITION BY RANGE (a); CREATE TABLE tp1 PARTITION OF t FOR VALUES FROM (0) TO (10); CREATE TABLE tp2 PARTITION OF t FOR VALUES FROM (10) TO (20); INSERT INTO t VALUES (0), (5); -- into tp1 INSERT INTO t VALUES (10), (15); -- into tp2 CREATE FUNCTION tf() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN RETURN NULL; END; $$; CREATE TRIGGER tr BEFORE DELETE ON t FOR EACH ROW EXECUTE PROCEDURE tf(); -- update suppressed by the BEFORE ROW DELETE trigger # UPDATE t SET a = 15 WHERE a = 0; UPDATE 0 -- update performed successfully # UPDATE t SET a = 5 WHERE a = 0; UPDATE 1 Does this match the expected behavior? Thanks Richard
Commits
-
Fix BEFORE ROW trigger handling in cross-partition MERGE update.
- a0ff37173d7d 17.0 landed
- 7f07384dc269 16.2 landed
- 7e8c6d7af658 15.6 landed