Re: BUG #19536: UPDATE RETURNING OLD value is stale after concurrent update when table has a BEFORE UPDATE trigger

From: Dean Rasheed <dean(dot)a(dot)rasheed(at)gmail(dot)com>
To: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>
Cc: bobergj(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #19536: UPDATE RETURNING OLD value is stale after concurrent update when table has a BEFORE UPDATE trigger
Date: 2026-06-28 09:59:09
Message-ID: CAEZATCW8q47GDba1o+Ji9JUhCHFFbB35D9qMSbBhboCx0GXkQQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

On Sat, 27 Jun 2026 at 20:22, Bharath Rupireddy
<bharath(dot)rupireddyforpostgres(at)gmail(dot)com> wrote:
>
> In short: with a BEFORE UPDATE trigger, the trigger's tuple lock
> advances tupleid to the concurrently-updated row version, so the later
> table_tuple_update returns TM_Ok instead of TM_Updated. Since oldSlot
> is only refreshed on the TM_Updated path, the RETURNING clause keeps
> the pre-wait value (ctid=(0,1), n=7) instead of the actual
> concurrently-updated value (ctid=(0,2), n=17). Without the trigger,
> the wait happens inside table_tuple_update itself, which returns
> TM_Updated and correctly refreshes oldSlot.

Yes, that analysis seems correct.

This doesn't affect DELETE, because the DELETE code always fetches the
most recent version of the old tuple just before processing the
RETURNING clause. Similarly, it doesn't affect a cross-partition
UPDATE, which does a DELETE followed by an INSERT.

It also doesn't affect MERGE UPDATE/DELETE, because that does its own
EPQ handling, rather than relying on the trigger code to do it (see
9321c79c86e).

So I think we just need something like the attached.

Regards,
Dean

Attachment Content-Type Size
fix-returning-old-with-before-update-trigger.patch text/x-patch 21.8 KB

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Tender Wang 2026-06-28 11:33:47 Re: BUG #19534: Qual pushdown across a window subquery is unsafe with nondeterministic partition collations
Previous Message Bill Kim 2026-06-28 02:14:35 BUG #19524: NaN handling in btree_gist's float4/float8 opclasses