-- This file and its contents are licensed under the Timescale License. -- Please see the included NOTICE for copyright information and -- LICENSE-TIMESCALE for a copy of the license. -- test single column fk constraint from plain table to hypertable during hypertable creation CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 0:00:00', 'd1', 1.0); INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 1:00:00', 'd1', 1.0); CREATE TABLE event(time timestamptz references metrics(time), info text); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); \set ON_ERROR_STOP 0 -- should fail UPDATE event SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed BEGIN; UPDATE event SET time = '2020-01-01 01:00:00' WHERE time = '2020-01-01'; ROLLBACK; \set ON_ERROR_STOP 0 -- should fail DELETE FROM metrics WHERE time = '2020-01-01'; ERROR: update or delete on table "_hyper_1_1_chunk" violates foreign key constraint "event_time_fkey1" on table "event" -- should fail UPDATE metrics SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: update or delete on table "_hyper_1_1_chunk" violates foreign key constraint "event_time_fkey1" on table "event" \set ON_ERROR_STOP 1 SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_1_1_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid ------------------------+--------+--------------+--------------- "RI_FKey_noaction_del" | f | t | event "RI_FKey_noaction_upd" | f | t | event "RI_FKey_noaction_del" | t | t | event "RI_FKey_noaction_upd" | t | t | event (4 rows) -- create new chunk and repeat the test INSERT INTO metrics(time, device, value) VALUES ('2021-01-01', 'd1', 1.0); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2021-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2021-01-01', 'info2'); SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_1_1_chunk | t event_time_fkey2 | event | _timescaledb_internal._hyper_1_2_chunk | t (3 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid ------------------------+--------+--------------+--------------- "RI_FKey_noaction_del" | f | t | event "RI_FKey_noaction_upd" | f | t | event "RI_FKey_noaction_del" | t | t | event "RI_FKey_noaction_upd" | t | t | event "RI_FKey_noaction_del" | t | t | event "RI_FKey_noaction_upd" | t | t | event (6 rows) -- chunks referenced in fk constraints must not be dropped or truncated \set ON_ERROR_STOP 0 TRUNCATE metrics; ERROR: cannot truncate a table referenced in a foreign key constraint TRUNCATE _timescaledb_internal._hyper_1_1_chunk; ERROR: cannot truncate a table referenced in a foreign key constraint TRUNCATE _timescaledb_internal._hyper_1_2_chunk; ERROR: cannot truncate a table referenced in a foreign key constraint DROP TABLE _timescaledb_internal._hyper_1_1_chunk; ERROR: cannot drop table _timescaledb_internal._hyper_1_1_chunk because other objects depend on it DROP TABLE _timescaledb_internal._hyper_1_2_chunk; ERROR: cannot drop table _timescaledb_internal._hyper_1_2_chunk because other objects depend on it SELECT drop_chunks('metrics', '1 month'::interval); ERROR: cannot drop constraint 1_1_metrics_pkey on table _timescaledb_internal._hyper_1_1_chunk because other objects depend on it \set ON_ERROR_STOP 1 -- after removing constraint dropping should succeed ALTER TABLE event DROP CONSTRAINT event_time_fkey; SELECT drop_chunks('metrics', '1 month'::interval); drop_chunks ---------------------------------------- _timescaledb_internal._hyper_1_1_chunk _timescaledb_internal._hyper_1_2_chunk (2 rows) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to hypertable during hypertable creation with RESTRICT CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 0:00:00', 'd1', 1.0); INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 1:00:00', 'd1', 1.0); CREATE TABLE event(time timestamptz references metrics(time) ON DELETE RESTRICT ON UPDATE RESTRICT, info text); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); \set ON_ERROR_STOP 0 -- should fail UPDATE event SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed BEGIN; UPDATE event SET time = '2020-01-01 01:00:00' WHERE time = '2020-01-01'; ROLLBACK; \set ON_ERROR_STOP 0 -- should fail DELETE FROM metrics WHERE time = '2020-01-01'; ERROR: update or delete on table "_hyper_2_3_chunk" violates foreign key constraint "event_time_fkey1" on table "event" -- should fail UPDATE metrics SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: update or delete on table "_hyper_2_3_chunk" violates foreign key constraint "event_time_fkey1" on table "event" \set ON_ERROR_STOP 1 SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_2_3_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid ------------------------+--------+--------------+--------------- "RI_FKey_restrict_del" | f | t | event "RI_FKey_restrict_upd" | f | t | event "RI_FKey_restrict_del" | t | t | event "RI_FKey_restrict_upd" | t | t | event (4 rows) -- create new chunk and repeat the test INSERT INTO metrics(time, device, value) VALUES ('2021-01-01', 'd1', 1.0); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2021-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2021-01-01', 'info2'); SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_2_3_chunk | t event_time_fkey2 | event | _timescaledb_internal._hyper_2_4_chunk | t (3 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid ------------------------+--------+--------------+--------------- "RI_FKey_restrict_del" | f | t | event "RI_FKey_restrict_upd" | f | t | event "RI_FKey_restrict_del" | t | t | event "RI_FKey_restrict_upd" | t | t | event "RI_FKey_restrict_del" | t | t | event "RI_FKey_restrict_upd" | t | t | event (6 rows) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to hypertable during hypertable creation with CASCADE CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 0:00:00', 'd1', 1.0); INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 1:00:00', 'd1', 1.0); CREATE TABLE event(time timestamptz references metrics(time) ON DELETE CASCADE ON UPDATE CASCADE, info text); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); \set ON_ERROR_STOP 0 -- should fail UPDATE event SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed BEGIN; UPDATE event SET time = '2020-01-01 01:00:00' WHERE time = '2020-01-01'; ROLLBACK; -- should cascade BEGIN; DELETE FROM metrics WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------+------ (0 rows) ROLLBACK; -- should cascade BEGIN; UPDATE metrics SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------------------------------+------- Wed Jan 01 00:30:00 2020 PST | info2 (1 row) ROLLBACK; SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_3_5_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid -----------------------+--------+--------------+--------------- "RI_FKey_cascade_del" | f | t | event "RI_FKey_cascade_upd" | f | t | event "RI_FKey_cascade_del" | t | t | event "RI_FKey_cascade_upd" | t | t | event (4 rows) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to hypertable during hypertable creation with SET NULL CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 0:00:00', 'd1', 1.0); INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 1:00:00', 'd1', 1.0); CREATE TABLE event(time timestamptz references metrics(time) ON DELETE SET NULL ON UPDATE SET NULL, info text); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); \set ON_ERROR_STOP 0 -- should fail UPDATE event SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed BEGIN; UPDATE event SET time = '2020-01-01 01:00:00' WHERE time = '2020-01-01'; ROLLBACK; -- should cascade BEGIN; DELETE FROM metrics WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------+------- | info2 (1 row) ROLLBACK; -- should cascade BEGIN; UPDATE metrics SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------+------- | info2 (1 row) ROLLBACK; SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_4_6_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid -----------------------+--------+--------------+--------------- "RI_FKey_setnull_del" | f | t | event "RI_FKey_setnull_upd" | f | t | event "RI_FKey_setnull_del" | t | t | event "RI_FKey_setnull_upd" | t | t | event (4 rows) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to hypertable during hypertable creation with SET DEFAULT CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 0:00:00', 'd1', 1.0); INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 1:00:00', 'd1', 1.0); CREATE TABLE event(time timestamptz default null references metrics(time) ON DELETE SET DEFAULT ON UPDATE SET DEFAULT, info text); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); \set ON_ERROR_STOP 0 -- should fail UPDATE event SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed BEGIN; UPDATE event SET time = '2020-01-01 01:00:00' WHERE time = '2020-01-01'; ROLLBACK; -- should cascade BEGIN; DELETE FROM metrics WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------+------- | info2 (1 row) ROLLBACK; -- should cascade BEGIN; UPDATE metrics SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------+------- | info2 (1 row) ROLLBACK; SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_5_7_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid --------------------------+--------+--------------+--------------- "RI_FKey_setdefault_del" | f | t | event "RI_FKey_setdefault_upd" | f | t | event "RI_FKey_setdefault_del" | t | t | event "RI_FKey_setdefault_upd" | t | t | event (4 rows) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to hypertable with constraint being added separately CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01', 'd1', 1.0); CREATE TABLE event(time timestamptz, info text); ALTER TABLE event ADD CONSTRAINT event_time_fkey FOREIGN KEY (time) REFERENCES metrics(time) ON DELETE RESTRICT; -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); -- should fail \set ON_ERROR_STOP 0 DELETE FROM metrics WHERE time = '2020-01-01'; ERROR: update or delete on table "_hyper_6_8_chunk" violates foreign key constraint "event_time_fkey1" on table "event" \set ON_ERROR_STOP 1 SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_6_8_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid ------------------------+--------+--------------+--------------- "RI_FKey_restrict_del" | f | t | event "RI_FKey_noaction_upd" | f | t | event "RI_FKey_restrict_del" | t | t | event "RI_FKey_noaction_upd" | t | t | event (4 rows) DROP TABLE event; DROP TABLE metrics; -- test multi column fk constraint from plain table to hypertable CREATE TABLE metrics(time timestamptz , device text, value float, primary key (time, device)); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01', 'd1', 1.0); CREATE TABLE event(time timestamptz, device text, info text); ALTER TABLE event ADD CONSTRAINT event_time_fkey FOREIGN KEY (time,device) REFERENCES metrics(time,device) ON DELETE RESTRICT; -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, device, info) VALUES ('2020-01-02', 'd1', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" INSERT INTO event(time, device, info) VALUES ('2020-01-01', 'd2', 'info2'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, device, info) VALUES ('2020-01-01', 'd1', 'info2'); -- should fail \set ON_ERROR_STOP 0 DELETE FROM metrics WHERE time = '2020-01-01'; ERROR: update or delete on table "_hyper_7_9_chunk" violates foreign key constraint "event_time_device_fkey" on table "event" DELETE FROM metrics WHERE device = 'd1'; ERROR: update or delete on table "_hyper_7_9_chunk" violates foreign key constraint "event_time_device_fkey" on table "event" \set ON_ERROR_STOP 1 DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to hypertable with constraint being added separately while data is present CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01', 'd1', 1.0); CREATE TABLE event(time timestamptz, info text); INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); INSERT INTO event(time, info) VALUES ('2020-02-01', 'info1'); -- should fail \set ON_ERROR_STOP 0 ALTER TABLE event ADD CONSTRAINT event_time_fkey FOREIGN KEY (time) REFERENCES metrics(time) ON DELETE SET NULL; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 INSERT INTO metrics(time, device, value) VALUES ('2020-02-01', 'd1', 1.0); ALTER TABLE event ADD CONSTRAINT event_time_fkey FOREIGN KEY (time) REFERENCES metrics(time) ON DELETE CASCADE; -- delete should cascade DELETE FROM metrics WHERE time = '2020-01-01'; SELECT * FROM event; time | info ------------------------------+------- Sat Feb 01 00:00:00 2020 PST | info1 (1 row) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from plain table to compressed hypertable CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 0:00:00', 'd1', 1.0); INSERT INTO metrics(time, device, value) VALUES ('2020-01-01 1:00:00', 'd1', 1.0); ALTER TABLE metrics SET(timescaledb.compress, timescaledb.compress_segmentby='device'); NOTICE: default order by for hypertable "metrics" is set to ""time" DESC" SELECT count(compress_chunk(ch)) FROM show_chunks('metrics') ch; count ------- 1 (1 row) CREATE TABLE event(time timestamptz references metrics(time) ON DELETE CASCADE ON UPDATE CASCADE, info text); -- should fail \set ON_ERROR_STOP 0 INSERT INTO event(time, info) VALUES ('2020-01-02', 'info1'); ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed INSERT INTO event(time, info) VALUES ('2020-01-01', 'info2'); \set ON_ERROR_STOP 0 -- should fail UPDATE event SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; ERROR: insert or update on table "event" violates foreign key constraint "event_time_fkey" \set ON_ERROR_STOP 1 -- should succeed BEGIN; UPDATE event SET time = '2020-01-01 01:00:00' WHERE time = '2020-01-01'; ROLLBACK; -- should cascade BEGIN; DELETE FROM metrics WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------+------ (0 rows) ROLLBACK; -- should cascade BEGIN; UPDATE metrics SET time = '2020-01-01 00:30:00' WHERE time = '2020-01-01'; SELECT * FROM event ORDER BY event; time | info ------------------------------+------- Wed Jan 01 00:30:00 2020 PST | info2 (1 row) ROLLBACK; SELECT conname, conrelid::regclass, confrelid::regclass, conparentid <> 0 AS parent FROM pg_constraint WHERE conrelid='event'::regclass ORDER BY oid; conname | conrelid | confrelid | parent ------------------+----------+-----------------------------------------+-------- event_time_fkey | event | metrics | f event_time_fkey1 | event | _timescaledb_internal._hyper_9_12_chunk | t (2 rows) SELECT tgfoid::regproc, tgparentid <> 0 AS parent, tgisinternal, tgconstrrelid::regclass FROM pg_trigger WHERE tgconstrrelid='event'::regclass ORDER BY oid; tgfoid | parent | tgisinternal | tgconstrrelid -----------------------+--------+--------------+--------------- "RI_FKey_cascade_del" | f | t | event "RI_FKey_cascade_upd" | f | t | event "RI_FKey_cascade_del" | t | t | event "RI_FKey_cascade_upd" | t | t | event (4 rows) DROP TABLE event; DROP TABLE metrics; -- test single column fk constraint from hypertable to hypertable CREATE TABLE metrics(time timestamptz primary key, device text, value float); SELECT table_name FROM create_hypertable('metrics', 'time'); table_name ------------ metrics (1 row) CREATE TABLE event(time timestamptz, info text); SELECT table_name FROM create_hypertable('event', 'time'); NOTICE: adding not-null constraint to column "time" table_name ------------ event (1 row) \set ON_ERROR_STOP 0 ALTER TABLE event ADD CONSTRAINT event_time_fkey FOREIGN KEY (time) REFERENCES metrics(time); ERROR: hypertables cannot be used as foreign key references of hypertables \set ON_ERROR_STOP 1 CREATE TABLE event2(time timestamptz REFERENCES metrics(time), info text); \set ON_ERROR_STOP 0 SELECT table_name FROM create_hypertable('event2', 'time'); ERROR: hypertables cannot be used as foreign key references of hypertables \set ON_ERROR_STOP 1 DROP TABLE event; DROP TABLE event2; DROP TABLE metrics; -- test FK behavior with different cascading configurations CREATE TABLE fk_no_action(fk_no_action text primary key); CREATE TABLE fk_restrict(fk_restrict text primary key); CREATE TABLE fk_cascade(fk_cascade text primary key); CREATE TABLE fk_set_null(fk_set_null text primary key); CREATE TABLE fk_set_default(fk_set_default text primary key); CREATE TABLE ht( time timestamptz not null, fk_no_action text references fk_no_action(fk_no_action) ON DELETE NO ACTION ON UPDATE NO ACTION, fk_restrict text references fk_restrict(fk_restrict) ON DELETE RESTRICT ON UPDATE RESTRICT, fk_cascade text references fk_cascade(fk_cascade) ON DELETE CASCADE ON UPDATE CASCADE, fk_set_null text references fk_set_null(fk_set_null) ON DELETE SET NULL ON UPDATE SET NULL, fk_set_default text default 'default' references fk_set_default(fk_set_default) ON DELETE SET DEFAULT ON UPDATE SET DEFAULT ); SELECT table_name FROM create_hypertable('ht', 'time'); table_name ------------ ht (1 row) ALTER TABLE ht SET(timescaledb.compress, timescaledb.compress_segmentby='fk_no_action,fk_restrict,fk_cascade,fk_set_null,fk_set_default'); NOTICE: default order by for hypertable "ht" is set to ""time" DESC" \set ON_ERROR_STOP 0 INSERT INTO fk_set_default(fk_set_default) VALUES ('default'); INSERT INTO ht(time) VALUES ('2020-01-01'); -- NO ACTION -- should fail with foreign key violation INSERT INTO ht(time, fk_no_action) VALUES ('2020-01-01', 'fk_no_action'); ERROR: insert or update on table "_hyper_13_14_chunk" violates foreign key constraint "14_14_ht_fk_no_action_fkey" -- ON UPDATE NO ACTION BEGIN; INSERT INTO fk_no_action(fk_no_action) VALUES ('fk_no_action'); INSERT INTO ht(time, fk_no_action) VALUES ('2020-01-01', 'fk_no_action'); -- should error UPDATE fk_no_action SET fk_no_action = 'fk_no_action_updated'; ERROR: update or delete on table "fk_no_action" violates foreign key constraint "ht_fk_no_action_fkey" on table "ht" ROLLBACK; -- ON UPDATE NO ACTION with compression BEGIN; INSERT INTO fk_no_action(fk_no_action) VALUES ('fk_no_action'); INSERT INTO ht(time, fk_no_action) VALUES ('2020-01-01', 'fk_no_action'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should error UPDATE fk_no_action SET fk_no_action = 'fk_no_action_updated'; ERROR: update or delete on table "fk_no_action" violates foreign key constraint "ht_fk_no_action_fkey" on table "ht" ROLLBACK; -- ON DELETE NO ACTION BEGIN; INSERT INTO fk_no_action(fk_no_action) VALUES ('fk_no_action'); INSERT INTO ht(time, fk_no_action) VALUES ('2020-01-01', 'fk_no_action'); -- should error DELETE FROM fk_no_action; ERROR: update or delete on table "fk_no_action" violates foreign key constraint "ht_fk_no_action_fkey" on table "ht" ROLLBACK; -- ON DELETE NO ACTION with compression BEGIN; INSERT INTO fk_no_action(fk_no_action) VALUES ('fk_no_action'); INSERT INTO ht(time, fk_no_action) VALUES ('2020-01-01', 'fk_no_action'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should error DELETE FROM fk_no_action; ERROR: update or delete on table "fk_no_action" violates foreign key constraint "ht_fk_no_action_fkey" on table "ht" ROLLBACK; -- RESTRICT -- should fail with foreign key violation INSERT INTO ht(time, fk_restrict) VALUES ('2020-01-01', 'fk_restrict'); ERROR: insert or update on table "_hyper_13_14_chunk" violates foreign key constraint "14_15_ht_fk_restrict_fkey" -- ON UPDATE RESTRICT BEGIN; INSERT INTO fk_restrict(fk_restrict) VALUES ('fk_restrict'); INSERT INTO ht(time, fk_restrict) VALUES ('2020-01-01', 'fk_restrict'); -- should error UPDATE fk_restrict SET fk_restrict = 'fk_restrict_updated'; ERROR: update or delete on table "fk_restrict" violates foreign key constraint "ht_fk_restrict_fkey" on table "ht" ROLLBACK; -- ON UPDATE RESTRICT with compression BEGIN; INSERT INTO fk_restrict(fk_restrict) VALUES ('fk_restrict'); INSERT INTO ht(time, fk_restrict) VALUES ('2020-01-01', 'fk_restrict'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should error UPDATE fk_restrict SET fk_restrict = 'fk_restrict_updated'; ERROR: update or delete on table "fk_restrict" violates foreign key constraint "ht_fk_restrict_fkey" on table "ht" ROLLBACK; -- ON DELETE RESTRICT BEGIN; INSERT INTO fk_restrict(fk_restrict) VALUES ('fk_restrict'); INSERT INTO ht(time, fk_restrict) VALUES ('2020-01-01', 'fk_restrict'); -- should error DELETE FROM fk_restrict; ERROR: update or delete on table "fk_restrict" violates foreign key constraint "ht_fk_restrict_fkey" on table "ht" ROLLBACK; -- ON DELETE RESTRICT with compression BEGIN; INSERT INTO fk_restrict(fk_restrict) VALUES ('fk_restrict'); INSERT INTO ht(time, fk_restrict) VALUES ('2020-01-01', 'fk_restrict'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should error DELETE FROM fk_restrict; ERROR: update or delete on table "fk_restrict" violates foreign key constraint "ht_fk_restrict_fkey" on table "ht" ROLLBACK; -- CASCADE -- should fail with foreign key violation INSERT INTO ht(time, fk_cascade) VALUES ('2020-01-01', 'fk_cascade'); ERROR: insert or update on table "_hyper_13_14_chunk" violates foreign key constraint "14_13_ht_fk_cascade_fkey" -- ON UPDATE CASCADE BEGIN; INSERT INTO fk_cascade(fk_cascade) VALUES ('fk_cascade'); INSERT INTO ht(time, fk_cascade) VALUES ('2020-01-01', 'fk_cascade'); -- should cascade UPDATE fk_cascade SET fk_cascade = 'fk_cascade_updated'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+--------------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | fk_cascade_updated | | default (2 rows) ROLLBACK; -- ON UPDATE CASCADE with compression BEGIN; INSERT INTO fk_cascade(fk_cascade) VALUES ('fk_cascade'); INSERT INTO ht(time, fk_cascade) VALUES ('2020-01-01', 'fk_cascade'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should cascade UPDATE fk_cascade SET fk_cascade = 'fk_cascade_updated'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+--------------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | fk_cascade_updated | | default (2 rows) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------------- Append (actual rows=2 loops=1) -> Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_19_chunk (actual rows=1 loops=1) -> Seq Scan on _hyper_13_14_chunk (actual rows=1 loops=1) (4 rows) ROLLBACK; -- ON DELETE CASCADE BEGIN; INSERT INTO fk_cascade(fk_cascade) VALUES ('fk_cascade'); INSERT INTO ht(time, fk_cascade) VALUES ('2020-01-01', 'fk_cascade'); -- should cascade DELETE FROM fk_cascade; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default (1 row) ROLLBACK; -- ON DELETE CASCADE with compression without direct batch delete SET timescaledb.enable_compressed_direct_batch_delete TO false; BEGIN; INSERT INTO fk_cascade(fk_cascade) VALUES ('fk_cascade'); INSERT INTO ht(time, fk_cascade) VALUES ('2020-01-01', 'fk_cascade'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should cascade DELETE FROM fk_cascade; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default (1 row) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------------- Append (actual rows=1 loops=1) -> Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_20_chunk (actual rows=1 loops=1) -> Seq Scan on _hyper_13_14_chunk (actual rows=0 loops=1) (4 rows) ROLLBACK; RESET timescaledb.enable_compressed_direct_batch_delete; -- ON DELETE CASCADE with compression and direct batch delete BEGIN; INSERT INTO fk_cascade(fk_cascade) VALUES ('fk_cascade'); INSERT INTO ht(time, fk_cascade) VALUES ('2020-01-01', 'fk_cascade'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should cascade DELETE FROM fk_cascade; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default (1 row) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------- Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_21_chunk (actual rows=1 loops=1) (2 rows) ROLLBACK; -- SET NULL -- should fail with foreign key violation INSERT INTO ht(time, fk_set_null) VALUES ('2020-01-01', 'fk_set_null'); ERROR: insert or update on table "_hyper_13_14_chunk" violates foreign key constraint "14_17_ht_fk_set_null_fkey" -- ON UPDATE SET NULL BEGIN; INSERT INTO fk_set_null(fk_set_null) VALUES ('fk_set_null'); INSERT INTO ht(time, fk_set_null) VALUES ('2020-01-01', 'fk_set_null'); -- should set column to null UPDATE fk_set_null SET fk_set_null = 'fk_set_null_updated'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) ROLLBACK; -- ON UPDATE SET NULL with compression BEGIN; INSERT INTO fk_set_null(fk_set_null) VALUES ('fk_set_null'); INSERT INTO ht(time, fk_set_null) VALUES ('2020-01-01', 'fk_set_null'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should set column to null UPDATE fk_set_null SET fk_set_null = 'fk_set_null_updated'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------------- Append (actual rows=2 loops=1) -> Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_22_chunk (actual rows=1 loops=1) -> Seq Scan on _hyper_13_14_chunk (actual rows=1 loops=1) (4 rows) ROLLBACK; -- ON DELETE SET NULL BEGIN; INSERT INTO fk_set_null(fk_set_null) VALUES ('fk_set_null'); INSERT INTO ht(time, fk_set_null) VALUES ('2020-01-01', 'fk_set_null'); -- should set column to null DELETE FROM fk_set_null; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) ROLLBACK; -- ON DELETE SET NULL with compression BEGIN; INSERT INTO fk_set_null(fk_set_null) VALUES ('fk_set_null'); INSERT INTO ht(time, fk_set_null) VALUES ('2020-01-01', 'fk_set_null'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) -- should set column to null DELETE FROM fk_set_null; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------------- Append (actual rows=2 loops=1) -> Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_23_chunk (actual rows=1 loops=1) -> Seq Scan on _hyper_13_14_chunk (actual rows=1 loops=1) (4 rows) ROLLBACK; -- SET DEFAULT -- should fail with foreign key violation INSERT INTO ht(time, fk_set_default) VALUES ('2020-01-01', 'fk_set_default'); ERROR: insert or update on table "_hyper_13_14_chunk" violates foreign key constraint "14_16_ht_fk_set_default_fkey" -- ON UPDATE SET DEFAULT BEGIN; INSERT INTO fk_set_default(fk_set_default) VALUES ('fk_set_default'); INSERT INTO ht(time, fk_set_default) VALUES ('2020-01-01', 'fk_set_default'); SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | fk_set_default (2 rows) UPDATE fk_set_default SET fk_set_default = 'fk_set_default_updated' WHERE fk_set_default = 'fk_set_default'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) ROLLBACK; -- ON UPDATE SET DEFAULT with compression BEGIN; INSERT INTO fk_set_default(fk_set_default) VALUES ('fk_set_default'); INSERT INTO ht(time, fk_set_default) VALUES ('2020-01-01', 'fk_set_default'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | fk_set_default (2 rows) UPDATE fk_set_default SET fk_set_default = 'fk_set_default_updated' WHERE fk_set_default = 'fk_set_default'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------------- Append (actual rows=2 loops=1) -> Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_24_chunk (actual rows=1 loops=1) -> Seq Scan on _hyper_13_14_chunk (actual rows=1 loops=1) (4 rows) ROLLBACK; -- ON DELETE SET DEFAULT BEGIN; INSERT INTO fk_set_default(fk_set_default) VALUES ('fk_set_default'); INSERT INTO ht(time, fk_set_default) VALUES ('2020-01-01', 'fk_set_default'); SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | fk_set_default (2 rows) DELETE FROM fk_set_default WHERE fk_set_default = 'fk_set_default'; ROLLBACK; -- ON DELETE SET DEFAULT with compression BEGIN; INSERT INTO fk_set_default(fk_set_default) VALUES ('fk_set_default'); INSERT INTO ht(time, fk_set_default) VALUES ('2020-01-01', 'fk_set_default'); SELECT count(compress_chunk(ch)) FROM show_chunks('ht') ch; count ------- 1 (1 row) SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | fk_set_default (2 rows) DELETE FROM fk_set_default WHERE fk_set_default = 'fk_set_default'; SELECT * FROM ht; time | fk_no_action | fk_restrict | fk_cascade | fk_set_null | fk_set_default ------------------------------+--------------+-------------+------------+-------------+---------------- Wed Jan 01 00:00:00 2020 PST | | | | | default Wed Jan 01 00:00:00 2020 PST | | | | | default (2 rows) EXPLAIN (analyze, costs off, timing off, summary off) SELECT * FROM ht; QUERY PLAN ----------------------------------------------------------------------------------- Append (actual rows=2 loops=1) -> Custom Scan (DecompressChunk) on _hyper_13_14_chunk (actual rows=1 loops=1) -> Seq Scan on compress_hyper_14_25_chunk (actual rows=1 loops=1) -> Seq Scan on _hyper_13_14_chunk (actual rows=1 loops=1) (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); -- 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';