mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-18 03:23:37 +08:00
This change refactors the chunk index handling to make better use of standard PostgreSQL catalog information, while removing the hypertable_index metadata table and associated triggers, including those on the chunk_index table. The chunk_index table itself is also simplified. A benefit of this refactoring is that indexes are no longer created using string mangling to construct the CREATE INDEX command for a chunk, based on the string definition of the hypertable index. Instead, indexes are created in C using proper index-related internal data structures. Chunk indexes can now also be renamed and are added in the parent index tablespace. Changing tablespace on a hypertable index also recurses to chunks, as expected. Default indexes that are added when creating a hypertable use the hypertable's tablespace. Creating Hypertable indexes with the CONCURRENTLY modifier is currently blocked, due to unclear semantics regarding concurrent creation over many tables, including how to deal with snapshots.
189 lines
6.7 KiB
PL/PgSQL
189 lines
6.7 KiB
PL/PgSQL
-- Creates a constraint on a chunk.
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_add_table_constraint(
|
|
chunk_constraint_row _timescaledb_catalog.chunk_constraint
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL AS
|
|
$BODY$
|
|
DECLARE
|
|
sql_code TEXT;
|
|
chunk_row _timescaledb_catalog.chunk;
|
|
hypertable_row _timescaledb_catalog.hypertable;
|
|
constraint_oid OID;
|
|
def TEXT;
|
|
BEGIN
|
|
SELECT * INTO STRICT chunk_row FROM _timescaledb_catalog.chunk c WHERE c.id = chunk_constraint_row.chunk_id;
|
|
SELECT * INTO STRICT hypertable_row FROM _timescaledb_catalog.hypertable h WHERE h.id = chunk_row.hypertable_id;
|
|
|
|
IF chunk_constraint_row.dimension_slice_id IS NOT NULL THEN
|
|
def := format('CHECK (%s)', _timescaledb_internal.dimension_slice_get_constraint_sql(chunk_constraint_row.dimension_slice_id));
|
|
ELSIF chunk_constraint_row.hypertable_constraint_name IS NOT NULL THEN
|
|
SELECT oid INTO STRICT constraint_oid FROM pg_constraint
|
|
WHERE conname=chunk_constraint_row.hypertable_constraint_name AND
|
|
conrelid = format('%I.%I', hypertable_row.schema_name, hypertable_row.table_name)::regclass::oid;
|
|
def := pg_get_constraintdef(constraint_oid);
|
|
ELSE
|
|
RAISE 'Unknown constraint type';
|
|
END IF;
|
|
|
|
sql_code := format(
|
|
$$ ALTER TABLE %I.%I ADD CONSTRAINT %I %s $$,
|
|
chunk_row.schema_name, chunk_row.table_name, chunk_constraint_row.constraint_name, def
|
|
);
|
|
EXECUTE sql_code;
|
|
END
|
|
$BODY$;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_constraint_drop_table_constraint(
|
|
chunk_constraint_row _timescaledb_catalog.chunk_constraint
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL AS
|
|
$BODY$
|
|
DECLARE
|
|
sql_code TEXT;
|
|
chunk_row _timescaledb_catalog.chunk;
|
|
BEGIN
|
|
SELECT * INTO STRICT chunk_row FROM _timescaledb_catalog.chunk c WHERE c.id = chunk_constraint_row.chunk_id;
|
|
|
|
sql_code := format(
|
|
$$ ALTER TABLE %I.%I DROP CONSTRAINT %I $$,
|
|
chunk_row.schema_name, chunk_row.table_name, chunk_constraint_row.constraint_name
|
|
);
|
|
|
|
EXECUTE sql_code;
|
|
END
|
|
$BODY$;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.create_chunk_constraint(
|
|
chunk_id INTEGER,
|
|
constraint_oid OID
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL AS
|
|
$BODY$
|
|
DECLARE
|
|
chunk_constraint_row _timescaledb_catalog.chunk_constraint;
|
|
constraint_row pg_constraint;
|
|
constraint_name TEXT;
|
|
hypertable_constraint_name TEXT = NULL;
|
|
BEGIN
|
|
SELECT * INTO STRICT constraint_row FROM pg_constraint WHERE OID = constraint_oid;
|
|
hypertable_constraint_name := constraint_row.conname;
|
|
constraint_name := format('%s_%s_%s', chunk_id, nextval('_timescaledb_catalog.chunk_constraint_name'), hypertable_constraint_name);
|
|
|
|
INSERT INTO _timescaledb_catalog.chunk_constraint (chunk_id, constraint_name, dimension_slice_id, hypertable_constraint_name)
|
|
VALUES (chunk_id, constraint_name, NULL, hypertable_constraint_name) RETURNING * INTO STRICT chunk_constraint_row;
|
|
|
|
PERFORM _timescaledb_internal.chunk_constraint_add_table_constraint(chunk_constraint_row);
|
|
END
|
|
$BODY$;
|
|
|
|
-- Drop a constraint on a chunk
|
|
-- static
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_chunk_constraint(
|
|
chunk_id INTEGER,
|
|
constraint_name NAME,
|
|
alter_table BOOLEAN = true
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL AS
|
|
$BODY$
|
|
DECLARE
|
|
chunk_row _timescaledb_catalog.chunk;
|
|
chunk_constraint_row _timescaledb_catalog.chunk_constraint;
|
|
BEGIN
|
|
SELECT * INTO STRICT chunk_row FROM _timescaledb_catalog.chunk c WHERE c.id = chunk_id;
|
|
|
|
DELETE FROM _timescaledb_catalog.chunk_constraint cc
|
|
WHERE cc.constraint_name = drop_chunk_constraint.constraint_name
|
|
AND cc.chunk_id = drop_chunk_constraint.chunk_id
|
|
RETURNING * INTO STRICT chunk_constraint_row;
|
|
|
|
IF alter_table THEN
|
|
EXECUTE format(
|
|
$$ ALTER TABLE %I.%I DROP CONSTRAINT %I $$,
|
|
chunk_row.schema_name, chunk_row.table_name, chunk_constraint_row.constraint_name
|
|
);
|
|
END IF;
|
|
|
|
END
|
|
$BODY$;
|
|
|
|
-- do I need to add a hypertable constraint to the chunks?;
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.need_chunk_constraint(
|
|
constraint_oid OID
|
|
)
|
|
RETURNS BOOLEAN LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
constraint_row record;
|
|
BEGIN
|
|
SELECT * INTO STRICT constraint_row FROM pg_constraint WHERE OID = constraint_oid;
|
|
|
|
IF constraint_row.contype IN ('c') THEN
|
|
-- check and not null constraints handled by regular inheritance (from docs):
|
|
-- All check constraints and not-null constraints on a parent table are automatically inherited by its children,
|
|
-- unless explicitly specified otherwise with NO INHERIT clauses. Other types of constraints
|
|
-- (unique, primary key, and foreign key constraints) are not inherited."
|
|
|
|
IF constraint_row.connoinherit THEN
|
|
RAISE 'NO INHERIT option not supported on hypertables: %', constraint_row.conname
|
|
USING ERRCODE = 'IO101';
|
|
END IF;
|
|
|
|
RETURN FALSE;
|
|
END IF;
|
|
RETURN TRUE;
|
|
END
|
|
$BODY$;
|
|
|
|
-- Creates a constraint on all chunks for a hypertable.
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.add_constraint(
|
|
hypertable_id INTEGER,
|
|
constraint_oid OID
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
constraint_row pg_constraint;
|
|
hypertable_row _timescaledb_catalog.hypertable;
|
|
BEGIN
|
|
IF _timescaledb_internal.need_chunk_constraint(constraint_oid) THEN
|
|
SELECT * INTO STRICT constraint_row FROM pg_constraint WHERE OID = constraint_oid;
|
|
|
|
PERFORM _timescaledb_internal.create_chunk_constraint(c.id, constraint_oid)
|
|
FROM _timescaledb_catalog.chunk c
|
|
WHERE c.hypertable_id = add_constraint.hypertable_id;
|
|
END IF;
|
|
END
|
|
$BODY$;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.add_constraint_by_name(
|
|
hypertable_id INTEGER,
|
|
constraint_name name
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
constraint_oid OID;
|
|
BEGIN
|
|
SELECT oid INTO STRICT constraint_oid FROM pg_constraint WHERE conname = constraint_name
|
|
AND conrelid = _timescaledb_internal.main_table_from_hypertable(hypertable_id);
|
|
|
|
PERFORM _timescaledb_internal.add_constraint(hypertable_id, constraint_oid);
|
|
END
|
|
$BODY$;
|
|
|
|
-- Drops constraint on all chunks for a hypertable.
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.drop_constraint(
|
|
hypertable_id INTEGER,
|
|
hypertable_constraint_name NAME
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
BEGIN
|
|
PERFORM _timescaledb_internal.drop_chunk_constraint(cc.chunk_id, cc.constraint_name)
|
|
FROM _timescaledb_catalog.chunk c
|
|
INNER JOIN _timescaledb_catalog.chunk_constraint cc ON (cc.chunk_id = c.id)
|
|
WHERE c.hypertable_id = drop_constraint.hypertable_id AND cc.hypertable_constraint_name = drop_constraint.hypertable_constraint_name;
|
|
END
|
|
$BODY$;
|