mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-26 00:00:54 +08:00
The ProcessUtility hook doesn't give any information on applied DDL commands, which makes it hard to implement DDL processing that requires the result of a DDL command on a hypertable (for instance, adding a constraint or index without an explicit name). This change splits the DDL processing over start and end hooks, handling DDL commands before and after regular PostgreSQL processing, respectively. The start DDL hook is still based on the ProcessUtility hook, while the end DDL hook is based on an event trigger that allows getting information on the created/dropped/altered objects.
323 lines
9.1 KiB
SQL
323 lines
9.1 KiB
SQL
\o /dev/null
|
|
\ir include/create_single_db.sql
|
|
\o
|
|
|
|
CREATE TABLE hyper (
|
|
time BIGINT NOT NULL,
|
|
device_id TEXT NOT NULL,
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10)
|
|
);
|
|
|
|
|
|
SELECT * FROM create_hypertable('hyper', 'time', chunk_time_interval => 10);
|
|
|
|
--check and not-null constraints are inherited through regular inheritance.
|
|
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 9);
|
|
|
|
INSERT INTO hyper(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, NULL, 11);
|
|
|
|
\set ON_ERROR_STOP 1
|
|
|
|
INSERT INTO hyper(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
|
|
INSERT INTO hyper(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
|
|
----------------------- UNIQUE CONSTRAINTS ------------------
|
|
|
|
CREATE TABLE hyper_unique (
|
|
time BIGINT NOT NULL UNIQUE,
|
|
device_id TEXT NOT NULL,
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10)
|
|
);
|
|
|
|
|
|
SELECT * FROM create_hypertable('hyper_unique', 'time', chunk_time_interval => 10);
|
|
|
|
INSERT INTO hyper_unique(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
|
|
INSERT INTO hyper_unique(time, device_id,sensor_1) VALUES
|
|
(1257987800000000000, 'dev2', 11);
|
|
|
|
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_unique(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
\d+ hyper
|
|
\d+ hyper_unique
|
|
--should have unique constraint not just unique index
|
|
\d+ _timescaledb_internal._hyper_2_4_chunk
|
|
|
|
ALTER TABLE hyper_unique DROP CONSTRAINT hyper_unique_time_key;
|
|
\d+ _timescaledb_internal._hyper_2_4_chunk
|
|
|
|
--uniqueness not enforced
|
|
INSERT INTO hyper_unique(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev3', 11);
|
|
|
|
--shouldn't be able to create constraint
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper_unique ADD CONSTRAINT hyper_unique_time_key UNIQUE (time);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
DELETE FROM hyper_unique WHERE device_id = 'dev3';
|
|
|
|
-- Try multi-alter table statement with a constraint without a name
|
|
ALTER TABLE hyper_unique
|
|
ADD CHECK (time > 0),
|
|
ADD UNIQUE (time);
|
|
\d+ hyper_unique
|
|
\d+ _timescaledb_internal._hyper_2_4_chunk
|
|
|
|
ALTER TABLE hyper_unique
|
|
DROP CONSTRAINT hyper_unique_time_key,
|
|
DROP CONSTRAINT hyper_unique_time_check;
|
|
|
|
\d+ hyper_unique
|
|
\d+ _timescaledb_internal._hyper_2_4_chunk
|
|
|
|
CREATE UNIQUE INDEX hyper_unique_time_idx ON hyper_unique (time);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
-- Try adding constraint using existing index
|
|
ALTER TABLE hyper_unique ADD CONSTRAINT hyper_unique_time_key UNIQUE USING INDEX hyper_unique_time_idx;
|
|
\set ON_ERROR_STOP 1
|
|
DROP INDEX hyper_unique_time_idx;
|
|
|
|
--now can create
|
|
ALTER TABLE hyper_unique ADD CONSTRAINT hyper_unique_time_key UNIQUE (time);
|
|
\d+ _timescaledb_internal._hyper_2_4_chunk
|
|
|
|
--test adding constraint with same name to different table -- should fail
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper ADD CONSTRAINT hyper_unique_time_key UNIQUE (time);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
--uniquness violation fails
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_unique(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
--cannot create unique constraint on non-partition column
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper_unique ADD CONSTRAINT hyper_unique_invalid UNIQUE (device_id);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
|
|
----------------------- PRIMARY KEY ------------------
|
|
|
|
CREATE TABLE hyper_pk (
|
|
time BIGINT NOT NULL PRIMARY KEY,
|
|
device_id TEXT NOT NULL,
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10)
|
|
);
|
|
|
|
|
|
SELECT * FROM create_hypertable('hyper_pk', 'time', chunk_time_interval => 10);
|
|
|
|
INSERT INTO hyper_pk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_pk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
--should have unique constraint not just unique index
|
|
\d+ _timescaledb_internal._hyper_3_6_chunk
|
|
|
|
ALTER TABLE hyper_pk DROP CONSTRAINT hyper_pk_pkey;
|
|
\d+ _timescaledb_internal._hyper_3_6_chunk
|
|
|
|
--uniqueness not enforced
|
|
INSERT INTO hyper_pk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev3', 11);
|
|
|
|
|
|
--shouldn't be able to create pk
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper_pk ADD CONSTRAINT hyper_pk_pkey PRIMARY KEY (time);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
DELETE FROM hyper_pk WHERE device_id = 'dev3';
|
|
|
|
--cannot create pk constraint on non-partition column
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper_pk ADD CONSTRAINT hyper_pk_invalid PRIMARY KEY (device_id);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
--now can create
|
|
ALTER TABLE hyper_pk ADD CONSTRAINT hyper_pk_pkey PRIMARY KEY (time);
|
|
\d+ _timescaledb_internal._hyper_3_6_chunk
|
|
|
|
--test adding constraint with same name to different table -- should fail
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper ADD CONSTRAINT hyper_pk_pkey UNIQUE (time);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
--uniquness violation fails
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_pk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
|
|
----------------------- FOREIGN KEY ------------------
|
|
|
|
CREATE TABLE devices(
|
|
device_id TEXT NOT NULL,
|
|
PRIMARY KEY (device_id)
|
|
);
|
|
|
|
CREATE TABLE hyper_fk (
|
|
time BIGINT NOT NULL PRIMARY KEY,
|
|
device_id TEXT NOT NULL REFERENCES devices(device_id),
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10)
|
|
);
|
|
|
|
|
|
SELECT * FROM create_hypertable('hyper_fk', 'time', chunk_time_interval => 10);
|
|
|
|
--fail fk constraint
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_fk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
INSERT INTO devices VALUES ('dev2');
|
|
|
|
INSERT INTO hyper_fk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
|
|
--delete should fail
|
|
\set ON_ERROR_STOP 0
|
|
DELETE FROM devices;
|
|
\set ON_ERROR_STOP 1
|
|
|
|
ALTER TABLE hyper_fk DROP CONSTRAINT hyper_fk_device_id_fkey;
|
|
|
|
--should now be able to add non-fk rows
|
|
INSERT INTO hyper_fk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000001, 'dev3', 11);
|
|
|
|
--can't add fk because of dev3 row
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper_fk ADD CONSTRAINT hyper_fk_device_id_fkey
|
|
FOREIGN KEY (device_id) REFERENCES devices(device_id);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
DELETE FROM hyper_fk WHERE device_id = 'dev3';
|
|
|
|
ALTER TABLE hyper_fk ADD CONSTRAINT hyper_fk_device_id_fkey
|
|
FOREIGN KEY (device_id) REFERENCES devices(device_id);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_fk(time, device_id,sensor_1) VALUES
|
|
(1257987700000000002, 'dev3', 11);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
----------------------- FOREIGN KEY INTO A HYPERTABLE ------------------
|
|
|
|
|
|
--FOREIGN KEY references into a hypertable are currently broken.
|
|
--The referencing table will never find the corresponding row in the hypertable
|
|
--since it will only search the parent. Thus any insert will result in an ERROR
|
|
--TODO: block such foreign keys or fix. (Hard to block on create table so punting for now)
|
|
CREATE TABLE hyper_for_ref (
|
|
time BIGINT NOT NULL PRIMARY KEY,
|
|
device_id TEXT NOT NULL,
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10)
|
|
);
|
|
|
|
SELECT * FROM create_hypertable('hyper_for_ref', 'time', chunk_time_interval => 10);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
CREATE TABLE referrer (
|
|
time BIGINT NOT NULL REFERENCES hyper_for_ref(time)
|
|
);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
CREATE TABLE referrer2 (
|
|
time BIGINT NOT NULL
|
|
);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE referrer2 ADD CONSTRAINT hyper_fk_device_id_fkey
|
|
FOREIGN KEY (time) REFERENCES hyper_for_ref(time);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
----------------------- EXCLUSION CONSTRAINT ------------------
|
|
|
|
CREATE TABLE hyper_ex (
|
|
time BIGINT,
|
|
device_id TEXT NOT NULL REFERENCES devices(device_id),
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10),
|
|
canceled boolean DEFAULT false,
|
|
EXCLUDE USING btree (
|
|
time WITH =, device_id WITH =
|
|
) WHERE (not canceled)
|
|
);
|
|
|
|
SELECT * FROM create_hypertable('hyper_ex', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
|
|
|
INSERT INTO hyper_ex(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 11);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_ex(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 12);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
ALTER TABLE hyper_ex DROP CONSTRAINT hyper_ex_time_device_id_excl;
|
|
|
|
--can now add
|
|
INSERT INTO hyper_ex(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 12);
|
|
|
|
--cannot add because of conflicts
|
|
\set ON_ERROR_STOP 0
|
|
ALTER TABLE hyper_ex ADD CONSTRAINT hyper_ex_time_device_id_excl
|
|
EXCLUDE USING btree (
|
|
time WITH =, device_id WITH =
|
|
) WHERE (not canceled)
|
|
;
|
|
\set ON_ERROR_STOP 1
|
|
|
|
DELETE FROM hyper_ex WHERE sensor_1 = 12;
|
|
|
|
ALTER TABLE hyper_ex ADD CONSTRAINT hyper_ex_time_device_id_excl
|
|
EXCLUDE USING btree (
|
|
time WITH =, device_id WITH =
|
|
) WHERE (not canceled)
|
|
;
|
|
|
|
\set ON_ERROR_STOP 0
|
|
INSERT INTO hyper_ex(time, device_id,sensor_1) VALUES
|
|
(1257987700000000000, 'dev2', 12);
|
|
\set ON_ERROR_STOP 1
|
|
|
|
|
|
--cannot add exclusion constraint without partition key.
|
|
CREATE TABLE hyper_ex_invalid (
|
|
time BIGINT,
|
|
device_id TEXT NOT NULL REFERENCES devices(device_id),
|
|
sensor_1 NUMERIC NULL DEFAULT 1 CHECK (sensor_1 > 10),
|
|
canceled boolean DEFAULT false,
|
|
EXCLUDE USING btree (
|
|
device_id WITH =
|
|
) WHERE (not canceled)
|
|
);
|
|
|
|
\set ON_ERROR_STOP 0
|
|
SELECT * FROM create_hypertable('hyper_ex_invalid', 'time', chunk_time_interval=>_timescaledb_internal.interval_to_usec('1 month'));
|
|
\set ON_ERROR_STOP 1
|