pgsql: Fix FK fast-path scan key ordering for mismatched column order

From: Amit Langote <amitlan(at)postgresql(dot)org>
To: pgsql-committers(at)lists(dot)postgresql(dot)org
Subject: pgsql: Fix FK fast-path scan key ordering for mismatched column order
Date: 2026-04-10 04:34:46
Message-ID: E1wB3Zt-000FIn-2G@gemulon.postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-committers

Fix FK fast-path scan key ordering for mismatched column order

The fast-path foreign key check introduced in 2da86c1ef9b assumed that
constraint key positions directly correspond to index column positions.
This is not always true as a FK constraint can reference PK columns in a
different order than they appear in the PK's unique index.

For example, if the PK is (a, b, c) and the FK references them as
(a, c, b), the constraint stores keys in the FK-specified order, but
the index has columns in PK order. The buggy code used the constraint
key index to access rd_opfamily[i], which retrieved the wrong operator
family when columns were reordered, causing "operator X is not a member
of opfamily Y" errors.

After fixing the opfamily lookup, a second issue started to happen:
btree index scans require scan keys to be ordered by attribute number.
The code was placing scan keys at array position i with attribute number
idx_attno, producing out-of-order keys when columns were swapped. This
caused "btree index keys must be ordered by attribute" errors.

The fix adds an index_attnos array to FastPathMeta that maps each
constraint key position to its corresponding index column position.
In ri_populate_fastpath_metadata(), we search indkey to find the actual
index column for each pk_attnums[i] and use that position for the
opfamily lookup. In build_index_scankeys(), we place each scan key at
the array position corresponding to its index column
(skeys[idx_attno-1]) rather than at the constraint key position,
ensuring scan keys are properly ordered by attribute number as btree
requires.

Reported-by: Fredrik Widlert <fredrik(dot)widlert(at)digpro(dot)se>
Author: Matheus Alcantara <matheusssilv97(at)gmail(dot)com>
Reviewed-by: Junwang Zhao <zhjwpku(at)gmail(dot)com>
Discussion: https://www.postgresql.org/message-id/CADfhSr-pCkbDxmiOVYSAGE5QGjsQ48KKH_W424SPk%2BpwzKZFaQ%40mail.gmail.com

Branch
------
master

Details
-------
https://git.postgresql.org/pg/commitdiff/980c1a85d819edc72c866001b9ca4fba454900fe

Modified Files
--------------
src/backend/utils/adt/ri_triggers.c | 40 +++++++++++++++++++++++++------
src/test/regress/expected/foreign_key.out | 19 +++++++++++++++
src/test/regress/sql/foreign_key.sql | 18 ++++++++++++++
3 files changed, 70 insertions(+), 7 deletions(-)

Browse pgsql-committers by date

  From Date Subject
Next Message Amit Langote 2026-04-10 06:28:30 pgsql: Assert index_attnos[0] == 1 in ri_FastPathFlushArray()
Previous Message Amit Langote 2026-04-10 04:33:36 pgsql: Fix typo left by 34a30786293