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
  • Loading branch information
svenklemm committed Sep 3, 2024
1 parent 6f1379e commit 2d5fac5
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/foreign_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,17 @@ constraint_get_trigger(Oid conoid, Oid *updtrigoid, Oid *deltrigoid)
table_close(rel, AccessShareLock);
}

static bool
array_has_member(const AttrNumber *array, int len, AttrNumber member)
{
for (int i = 0; i < len; i++)
{
if (array[i] == member)
return true;
}
return false;

Check warning on line 544 in src/foreign_key.c

View check run for this annotation

Codecov / codecov/patch

src/foreign_key.c#L544

Added line #L544 was not covered by tests
}

/*
* Return the oid of the index supporting the foreign key constraint.
*/
Expand All @@ -555,9 +566,13 @@ get_fk_index(Relation rel, int nkeys, AttrNumber *confkeys)
continue;
}

for (int i = 0; i < nkeys; i++)
for (int i = 0; i < nkeys && match; i++)
{
if (indexrel->rd_index->indkey.values[i] != confkeys[i])
/*
* 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
*/
if (!array_has_member(confkeys, nkeys, indexrel->rd_index->indkey.values[i]))
{
match = false;
}
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 @@ -1014,3 +1014,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 @@ -642,3 +642,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 2d5fac5

Please sign in to comment.