pgsql: Fix cross-type foreign keys in the batched fast-path FK check

From: Amit Langote <amitlan(at)postgresql(dot)org>
To: pgsql-committers(at)lists(dot)postgresql(dot)org
Subject: pgsql: Fix cross-type foreign keys in the batched fast-path FK check
Date: 2026-08-18 03:41:47
Message-ID: E1wwAhu-000000010Lu-0rth@gemulon.postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-committers

Fix cross-type foreign keys in the batched fast-path FK check

ri_FastPathFlushArray() rechecked a concurrently updated PK tuple with a
scan key it built itself, putting found_val, the key of the tuple it had
just locked, into sk_argument, and passing that same slot to
recheck_matched_pk_tuple(). Both operands therefore came from the locked
tuple, and since sk_argument is the operator's right-hand input, the PK
value was read as an FK value. For a foreign key using a cross-type
equality operator, such as a "date" primary key referenced by a "timestamp"
column, that compares days against microseconds, so the recheck always
failed and a batch that had to follow an update chain reported a violation
even though the version it locked still had the key.

Remove the recheck. For a same-type key it compared the tuple against
itself and so never rejected anything, which was harmless only because the
loop a few lines below does the real work: it already compares found_val,
read after the chain has been followed, against every buffered FK value,
with the arguments in the order the operator expects. That makes the
recheck redundant as well as wrong. Detection is not weakened by dropping
it, since the buffered value that led the scan to a tuple can be matched by
no other row visible to our snapshot.

ri_FastPathProbeOne() passes its original scan key, with the FK value still
in sk_argument, and was never affected; nor were single-row statements or
multi-column foreign keys, which go through it.

Add an isolation test covering the cross-type case, a permutation where
the key really does move away, and a same-type permutation that should
behave identically.

Reported-by: Peter Geoghegan <pg(at)bowt(dot)ie>
Co-authored-by: Peter Geoghegan <pg(at)bowt(dot)ie>
Discussion: https://postgr.es/m/CAH2-WznQjX3GByh_Ju7unuzMcik_5PJ5D7i_=qhwk=gPEkhfVQ@mail.gmail.com
Backpatch-through: 19

Branch
------
REL_19_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/3b70fa6f3d32ac832ed9ddd566c11b05e575f2c7

Modified Files
--------------
src/backend/utils/adt/ri_triggers.c | 43 ++++++++---------
.../isolation/expected/fk-crosstype-recheck.out | 37 +++++++++++++++
src/test/isolation/isolation_schedule | 1 +
src/test/isolation/specs/fk-crosstype-recheck.spec | 54 ++++++++++++++++++++++
4 files changed, 111 insertions(+), 24 deletions(-)

Browse pgsql-committers by date

  From Date Subject
Next Message Amit Langote 2026-08-18 03:42:01 pgsql: Fix cross-type foreign keys in the batched fast-path FK check
Previous Message Jeff Davis 2026-08-18 01:06:34 pgsql: pg_locale.c: Fix REL_18_STABLE for srclen < 0.