pg.ddx.io  pgsql-committers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Dean Rasheed <dean.a.rasheed@gmail.com>
To: pgsql-committers@lists.postgresql.org
Subject: pgsql: Fix trigger transition table capture for MERGE in CTE queries.
Date: Sat, 24 Jan 2026 11:36:35 +0000
Message-ID: <E1vjbwQ-002JtZ-1U@gemulon.postgresql.org> (raw)

Fix trigger transition table capture for MERGE in CTE queries.

When executing a data-modifying CTE query containing MERGE and some
other DML operation on a table with statement-level AFTER triggers,
the transition tables passed to the triggers would fail to include the
rows affected by the MERGE.

The reason is that, when initializing a ModifyTable node for MERGE,
MakeTransitionCaptureState() would create a TransitionCaptureState
structure with a single "tcs_private" field pointing to an
AfterTriggersTableData structure with cmdType == CMD_MERGE. Tuples
captured there would then not be included in the sets of tuples
captured when executing INSERT/UPDATE/DELETE ModifyTable nodes in the
same query.

Since there are no MERGE triggers, we should only create
AfterTriggersTableData structures for INSERT/UPDATE/DELETE. Individual
MERGE actions should then use those, thereby sharing the same capture
tuplestores as any other DML commands executed in the same query.

This requires changing the TransitionCaptureState structure, replacing
"tcs_private" with 3 separate pointers to AfterTriggersTableData
structures, one for each of INSERT, UPDATE, and DELETE. Nominally,
this is an ABI break to a public structure in commands/trigger.h.
However, since this is a private field pointing to an opaque data
structure, the only way to create a valid TransitionCaptureState is by
calling MakeTransitionCaptureState(), and no extensions appear to be
doing that anyway, so it seems safe for back-patching.

Backpatch to v15, where MERGE was introduced.

Bug: #19380
Reported-by: Daniel Woelfel <dwwoelfel@gmail.com>
Author: Dean Rasheed <dean.a.rasheed@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/19380-4e293be2b4007248%40postgresql.org
Backpatch-through: 15

Branch
------
REL_15_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/c5824536e7ca3c5ef5a9db59bd36c4e6beb23f51

Modified Files
--------------
src/backend/commands/trigger.c         | 148 +++++++++++++++++++++------------
src/include/commands/trigger.h         |   4 +-
src/test/regress/expected/triggers.out |   8 +-
src/test/regress/sql/triggers.sql      |   4 +
4 files changed, 107 insertions(+), 57 deletions(-)



view thread (5+ messages)  latest in thread

Message-ID: <E1vjbwQ-002JtZ-1U@gemulon.postgresql.org>
Permalink:  ../E1vjbwQ-002JtZ-1U@gemulon.postgresql.org/
Also on:    postgresql.org/message-id/E1vjbwQ-002JtZ-1U@gemulon.postgresql.org

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-committers@postgresql.org
  Cc: dean.a.rasheed@gmail.com, pgsql-committers@lists.postgresql.org
  Subject: Re: pgsql: Fix trigger transition table capture for MERGE in CTE queries.
  In-Reply-To: <E1vjbwQ-002JtZ-1U@gemulon.postgresql.org>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox