Skip to content

Commit

Permalink
Sync FK behaviour when creating hypertable
Browse files Browse the repository at this point in the history
We now allow FKs to hypertables but the initial check when creating
the hypertable was not adjusted so tables with pre-existing FKs
would not be allowed to be changed into hypertable while creating
the FK constraint afterwards succeeded.
  • Loading branch information
svenklemm committed Sep 30, 2024
1 parent b7a1074 commit 2649806
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 6 deletions.
1 change: 1 addition & 0 deletions .unreleased/pr_7301
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes: #7301 Make foreign key behaviour for hypertables consistent
5 changes: 4 additions & 1 deletion src/hypertable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1319,7 +1319,10 @@ hypertable_validate_constraints(Oid relid)
{
Form_pg_constraint form = (Form_pg_constraint) GETSTRUCT(tuple);

if (form->contype == CONSTRAINT_FOREIGN)
/*
* Hypertable <-> hypertable foreign keys are not supported.
*/
if (form->contype == CONSTRAINT_FOREIGN && ts_hypertable_relid_to_id(form->conrelid) != -1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
errmsg("cannot have FOREIGN KEY constraints to hypertable \"%s\"",
Expand Down
14 changes: 10 additions & 4 deletions test/expected/create_hypertable.out
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,6 @@ select * from tidrangescan_test where time > '2023-02-12 00:00:00+02:40'::timest
(3 rows)

drop table tidrangescan_test;
\set ON_ERROR_STOP 0
\set VERBOSITY default
set client_min_messages = WARNING;
-- test creating a hypertable from table referenced by a foreign key fails with
Expand All @@ -1065,6 +1064,13 @@ create table test_schema.fk_child(
id int,
foreign key (time, id) references test_schema.fk_parent(time, id)
);
select create_hypertable ('test_schema.fk_child', 'time');
create_hypertable
-----------------------------
(23,test_schema,fk_child,t)
(1 row)

\set ON_ERROR_STOP 0
select create_hypertable ('test_schema.fk_parent', 'time');
ERROR: cannot have FOREIGN KEY constraints to hypertable "fk_parent"
HINT: Remove all FOREIGN KEY constraints to table "fk_parent" before making it a hypertable.
Expand All @@ -1088,8 +1094,8 @@ SELECT * FROM test.show_indexes('test') ORDER BY 1;
SELECT * FROM show_chunks('test') ch, LATERAL test.show_indexes(ch) ORDER BY 1, 2;
ch | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace
------------------------------------------+--------------------------------------------------------+---------+------+--------+---------+-----------+------------
_timescaledb_internal._hyper_23_23_chunk | _timescaledb_internal._hyper_23_23_chunk_test_val_idx | {val} | | f | f | f |
_timescaledb_internal._hyper_23_23_chunk | _timescaledb_internal._hyper_23_23_chunk_test_time_idx | {time} | | f | f | f |
_timescaledb_internal._hyper_24_23_chunk | _timescaledb_internal._hyper_24_23_chunk_test_val_idx | {val} | | f | f | f |
_timescaledb_internal._hyper_24_23_chunk | _timescaledb_internal._hyper_24_23_chunk_test_time_idx | {time} | | f | f | f |
(2 rows)

DROP TABLE test;
Expand All @@ -1112,6 +1118,6 @@ SELECT * FROM test.show_indexes('test') ORDER BY 1;
SELECT * FROM show_chunks('test') ch, LATERAL test.show_indexes(ch) ORDER BY 1, 2;
ch | Index | Columns | Expr | Unique | Primary | Exclusion | Tablespace
------------------------------------------+-------------------------------------------------------+---------+------+--------+---------+-----------+------------
_timescaledb_internal._hyper_24_24_chunk | _timescaledb_internal._hyper_24_24_chunk_test_val_idx | {val} | | f | f | f |
_timescaledb_internal._hyper_25_24_chunk | _timescaledb_internal._hyper_25_24_chunk_test_val_idx | {val} | | f | f | f |
(1 row)

3 changes: 2 additions & 1 deletion test/sql/create_hypertable.sql
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,6 @@ select * from tidrangescan_test where time > '2023-02-12 00:00:00+02:40'::timest

drop table tidrangescan_test;

\set ON_ERROR_STOP 0
\set VERBOSITY default
set client_min_messages = WARNING;
-- test creating a hypertable from table referenced by a foreign key fails with
Expand All @@ -643,6 +642,8 @@ create table test_schema.fk_child(
id int,
foreign key (time, id) references test_schema.fk_parent(time, id)
);
select create_hypertable ('test_schema.fk_child', 'time');
\set ON_ERROR_STOP 0
select create_hypertable ('test_schema.fk_parent', 'time');
\set ON_ERROR_STOP 1

Expand Down
31 changes: 31 additions & 0 deletions tsl/test/expected/foreign_keys.out
Original file line number Diff line number Diff line change
Expand Up @@ -1025,3 +1025,34 @@ 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);
-- test foreign key constraints that have been created before hypertable conversion
create table converted_pk(time timestamptz, id int, unique(time, id));
create table converted_fk(time timestamptz, id int, foreign key (time, id) references converted_pk(time, id));
select table_name FROM create_hypertable ('converted_pk', 'time');
NOTICE: adding not-null constraint to column "time"
table_name
--------------
converted_pk
(1 row)

\set ON_ERROR_STOP 0
-- should fail
INSERT INTO converted_fk SELECT '2020-01-01', 1;
ERROR: insert or update on table "converted_fk" violates foreign key constraint "converted_fk_time_id_fkey"
\set ON_ERROR_STOP 1
INSERT INTO converted_pk SELECT '2020-01-01 0:01', 1;
\set ON_ERROR_STOP 0
-- should still fail
INSERT INTO converted_fk SELECT '2020-01-01', 1;
ERROR: insert or update on table "converted_fk" violates foreign key constraint "converted_fk_time_id_fkey"
\set ON_ERROR_STOP 1
INSERT INTO converted_fk SELECT '2020-01-01 0:01', 1;
\set ON_ERROR_STOP 0
-- should fail
DELETE FROM converted_pk WHERE time = '2020-01-01 0:01';
ERROR: update or delete on table "_hyper_16_27_chunk" violates foreign key constraint "converted_fk_time_id_fkey1" on table "converted_fk"
TRUNCATE converted_pk;
ERROR: cannot truncate a table referenced in a foreign key constraint
\set ON_ERROR_STOP 1
DELETE FROM converted_fk;
DELETE FROM converted_pk WHERE time = '2020-01-01 0:01';
28 changes: 28 additions & 0 deletions tsl/test/sql/foreign_keys.sql
Original file line number Diff line number Diff line change
Expand Up @@ -650,3 +650,31 @@ 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);

-- test foreign key constraints that have been created before hypertable conversion
create table converted_pk(time timestamptz, id int, unique(time, id));
create table converted_fk(time timestamptz, id int, foreign key (time, id) references converted_pk(time, id));

select table_name FROM create_hypertable ('converted_pk', 'time');

\set ON_ERROR_STOP 0
-- should fail
INSERT INTO converted_fk SELECT '2020-01-01', 1;
\set ON_ERROR_STOP 1

INSERT INTO converted_pk SELECT '2020-01-01 0:01', 1;

\set ON_ERROR_STOP 0
-- should still fail
INSERT INTO converted_fk SELECT '2020-01-01', 1;
\set ON_ERROR_STOP 1
INSERT INTO converted_fk SELECT '2020-01-01 0:01', 1;

\set ON_ERROR_STOP 0
-- should fail
DELETE FROM converted_pk WHERE time = '2020-01-01 0:01';
TRUNCATE converted_pk;
\set ON_ERROR_STOP 1

DELETE FROM converted_fk;
DELETE FROM converted_pk WHERE time = '2020-01-01 0:01';

0 comments on commit 2649806

Please sign in to comment.