mirror of
https://github.com/timescale/timescaledb.git
synced 2025-06-01 10:46:43 +08:00
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.
1059 lines
47 KiB
Plaintext
1059 lines
47 KiB
Plaintext
-- 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';
|