Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement. - Mailing list pgsql-bugs

From Peter Geoghegan
Subject Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement.
Date
Msg-id CAM3SWZSiX3_6H149ZH6QF8Y9LuaYgpg1218bbF9_cjvyykaK4w@mail.gmail.com
Whole thread Raw
In response to Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement.  (Peter Geoghegan <pg@heroku.com>)
Responses Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement.  (Michael Paquier <michael.paquier@gmail.com>)
Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement.  (Stanislav Grozev <tacho@daemonz.org>)
Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement.  (Andres Freund <andres@anarazel.de>)
List pgsql-bugs
On Thu, Dec 3, 2015 at 1:10 PM, Peter Geoghegan <pg@heroku.com> wrote:
> I'll need to think about a fix.

The problem was with the pointer we pass to ExecUpdate().

It's a pointer to the target tuple in shared memory. So the field
"tuple.t_data->t_ctid" within ExecOnConflictUpdate() starts out
pointing to an ItemPointerData with the correct ctid (when it
initially points to the current/target tuple, since as an
about-to-be-upserted tuple the "t_ctid" field must be a pointer to the
self-same tuple). Then, it is modified in-place in shared memory by
heap_update(), within its critical section.

The fix is to take a deep copy (pass a pointer to an ItemPointerData
on the stack), as in the attached. I've also fixed up the tests, which
should have caught this, but didn't. Mea culpa.

Many thanks to Stanislav for the report! While I didn't adopt his
suggestion, he certainly almost had it right.

--
Peter Geoghegan

Attachment

pgsql-bugs by date:

Previous
From: Peter Geoghegan
Date:
Subject: Re: Incorrect UPDATE trigger invocation in the UPDATE clause of an UPSERT statement.
Next
From: Peter Eisentraut
Date:
Subject: Re: pg_rewind exiting with error code 1 when source and target are on the same timeline