Skip to content

Commit

Permalink
Fix FK constraint where index and constraint column order differ
Browse files Browse the repository at this point in the history
The code for finding the constraint index was expecting the index
columns to be in the same order as the constraint columns. This
patch changes the check to require all columns be present independent
of the order.

Fixes #7226

(cherry picked from commit 887aed9)
  • Loading branch information
svenklemm committed Sep 11, 2024
1 parent 6b68fab commit b9a1a9b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 5 deletions.
1 change: 1 addition & 0 deletions .unreleased/pr_7229
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes: #7229 Fix foreign key constraints where index and constraint column order differ
19 changes: 14 additions & 5 deletions src/foreign_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,23 +547,32 @@ get_fk_index(Relation rel, int nkeys, AttrNumber *confkeys)
{
Oid indexoid = lfirst_oid(lc);
Relation indexrel = index_open(indexoid, AccessShareLock);
bool match = true;

if (!indexrel->rd_index->indisunique || indexrel->rd_index->indnkeyatts != nkeys)
{
index_close(indexrel, AccessShareLock);
continue;
}

Bitmapset *con_keys = NULL;
Bitmapset *ind_keys = NULL;

for (int i = 0; i < nkeys; i++)
{
if (indexrel->rd_index->indkey.values[i] != confkeys[i])
{
match = false;
}
/*
* Since ordering of the constraint definition and index definition can differ,
* we need to check that all the columns in the constraint are present in the index
*/
con_keys = bms_add_member(con_keys, confkeys[i]);
ind_keys = bms_add_member(ind_keys, indexrel->rd_index->indkey.values[i]);
}

bool match = bms_equal(con_keys, ind_keys);

index_close(indexrel, AccessShareLock);
bms_free(con_keys);
bms_free(ind_keys);

if (match)
{
return indexoid;
Expand Down
11 changes: 11 additions & 0 deletions tsl/test/expected/foreign_keys.out
Original file line number Diff line number Diff line change
Expand Up @@ -986,3 +986,14 @@ EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht;
(4 rows)

ROLLBACK;
-- #7226
-- test multi-column fk constraint where constraint column order is different from index column order
CREATE TABLE i7226(time timestamptz, device_id int, PRIMARY KEY (device_id, time));
SELECT create_hypertable('i7226', 'time');
create_hypertable
---------------------
(15,public,i7226,t)
(1 row)

CREATE TABLE i7226_valid(time timestamptz NOT NULL,device_id int NOT NULL, FOREIGN KEY(time, device_id) REFERENCES i7226(time, device_id));
INSERT INTO i7226 VALUES ('2024-08-29 12:00:00+00', 1);
8 changes: 8 additions & 0 deletions tsl/test/sql/foreign_keys.sql
Original file line number Diff line number Diff line change
Expand Up @@ -629,3 +629,11 @@ SELECT * FROM ht;
EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht;
ROLLBACK;

-- #7226
-- test multi-column fk constraint where constraint column order is different from index column order
CREATE TABLE i7226(time timestamptz, device_id int, PRIMARY KEY (device_id, time));
SELECT create_hypertable('i7226', 'time');

CREATE TABLE i7226_valid(time timestamptz NOT NULL,device_id int NOT NULL, FOREIGN KEY(time, device_id) REFERENCES i7226(time, device_id));
INSERT INTO i7226 VALUES ('2024-08-29 12:00:00+00', 1);

0 comments on commit b9a1a9b

Please sign in to comment.