mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Restrict RI fast-path FK check to btree referenced indexes
The RI fast-path check probes the referenced index directly and, for single-column keys, uses SK_SEARCHARRAY. Both assume the index is a btree. A comment claimed "PK indexes are always btree", but a foreign key's referenced index need not be a primary key: transformFkeyCheckAttrs() accepts any unique (or, for temporal keys, exclusion) index, so an out-of-tree access method advertising amcanunique could supply a non-btree index reachable by the fast path. Add pk_index_is_btree to RI_ConstraintInfo, set from the referenced index's access method when the constraint is loaded, and make ri_fastpath_is_applicable() return false for non-btree indexes so such constraints fall back to the SPI path. Reported-by: Noah Misch <noah@leadboat.com> Reviewed-by: Ayush Tiwari <ayushtiwari.slg01@gmail.com> Discussion: https://postgr.es/m/20260705210533.ee.noahmisch@microsoft.com Backpatch-through: 19
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include "access/tableam.h"
|
||||
#include "access/xact.h"
|
||||
#include "catalog/index.h"
|
||||
#include "catalog/pg_am_d.h"
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
@@ -142,6 +143,7 @@ typedef struct RI_ConstraintInfo
|
||||
|
||||
Oid conindid;
|
||||
bool pk_is_partitioned;
|
||||
bool pk_index_is_btree; /* is conindid a btree index? */
|
||||
|
||||
FastPathMeta *fpmeta;
|
||||
} RI_ConstraintInfo;
|
||||
@@ -2503,6 +2505,8 @@ ri_LoadConstraintInfo(Oid constraintOid)
|
||||
riinfo->conindid = conForm->conindid;
|
||||
riinfo->pk_is_partitioned =
|
||||
(get_rel_relkind(riinfo->pk_relid) == RELKIND_PARTITIONED_TABLE);
|
||||
riinfo->pk_index_is_btree =
|
||||
(get_rel_relam(riinfo->conindid) == BTREE_AM_OID);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
@@ -3150,7 +3154,8 @@ ri_FastPathFlushArray(RI_FastPathEntry *fpentry, TupleTableSlot *fk_slot,
|
||||
* Build scan key with SK_SEARCHARRAY. The index AM code will internally
|
||||
* sort and deduplicate, then walk leaf pages in order.
|
||||
*
|
||||
* PK indexes are always btree, which supports SK_SEARCHARRAY.
|
||||
* ri_fastpath_is_applicable() restricts the fast path to btree indexes,
|
||||
* which support SK_SEARCHARRAY.
|
||||
*
|
||||
* This path handles single-column FKs only, so index_attnos[0] == 1.
|
||||
*/
|
||||
@@ -3359,6 +3364,17 @@ ri_fastpath_is_applicable(const RI_ConstraintInfo *riinfo)
|
||||
if (riinfo->hasperiod)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The fast path probes the referenced index directly and, for
|
||||
* single-column keys, uses SK_SEARCHARRAY. A foreign key's referenced
|
||||
* index need not be a primary key; transformFkeyCheckAttrs() accepts any
|
||||
* unique index, so an out-of-tree amcanunique access method could reach
|
||||
* here. Restrict the fast path to btree, which is what the direct probe
|
||||
* and SK_SEARCHARRAY assume; other access methods fall back to SPI.
|
||||
*/
|
||||
if (!riinfo->pk_index_is_btree)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user