mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-16 10:33:27 +08:00
Tablespaces can now be associated with a hypertable using the new user-facing API attach_tablespace(). Alternatively, if the main table, which is to be converted into a hypertable, was created with an associated tablespace, that tablespace will automatically be associated also with the hypertable. Whenever a chunk is created, a tablespace will be chosen from the ones associated with the chunk's hypertable (if any). This is done in a way that ensures consistency in one dimension. I.e., if a hypertable has a closed (space) dimension with a fixed number of slices (ranges), it will ensure that chunks that fall in the same slice will alsp be stored in the same tablespace. If a hypertable has more than one closed dimension, the first one will be used to assign tablespaces to chunks. If the table has no closed dimensions, but one or more open (time) dimensions, then the first time dimension will be used. However, since open dimensions do not have a fixed number of slices, tablespaces will be assigned in a round-robbin fashion as new slices are created. Still, chunks in the same time slice will be stored in the same tablespace.
130 lines
4.2 KiB
PL/PgSQL
130 lines
4.2 KiB
PL/PgSQL
-- This file contains functions associated with creating new
|
|
-- hypertables.
|
|
|
|
-- Creates a new schema if it does not exist.
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.create_schema(
|
|
schema_name NAME
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
BEGIN
|
|
EXECUTE format(
|
|
$$
|
|
CREATE SCHEMA IF NOT EXISTS %I
|
|
$$, schema_name);
|
|
END
|
|
$BODY$
|
|
SET client_min_messages = WARNING -- suppress NOTICE on IF EXISTS
|
|
;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_create_table(
|
|
chunk_id INT
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
chunk_row _timescaledb_catalog.chunk;
|
|
hypertable_row _timescaledb_catalog.hypertable;
|
|
tablespace_clause TEXT := '';
|
|
tablespace_name NAME;
|
|
tablespace_oid OID;
|
|
BEGIN
|
|
SELECT * INTO STRICT chunk_row
|
|
FROM _timescaledb_catalog.chunk
|
|
WHERE id = chunk_id;
|
|
|
|
SELECT * INTO STRICT hypertable_row
|
|
FROM _timescaledb_catalog.hypertable
|
|
WHERE id = chunk_row.hypertable_id;
|
|
|
|
tablespace_name := _timescaledb_internal.select_tablespace(chunk_row.hypertable_id,
|
|
chunk_row.id);
|
|
SELECT t.oid
|
|
INTO tablespace_oid
|
|
FROM pg_catalog.pg_tablespace t
|
|
WHERE t.spcname = tablespace_name;
|
|
|
|
IF tablespace_oid IS NOT NULL THEN
|
|
tablespace_clause := format('TABLESPACE %s', tablespace_name);
|
|
ELSIF tablespace_name IS NOT NULL THEN
|
|
RAISE EXCEPTION 'No tablespace % in database %', tablespace_name, current_database()
|
|
USING ERRCODE = 'IO501';
|
|
END IF;
|
|
|
|
EXECUTE format(
|
|
$$
|
|
CREATE TABLE IF NOT EXISTS %1$I.%2$I () INHERITS(%3$I.%4$I) %5$s;
|
|
$$,
|
|
chunk_row.schema_name, chunk_row.table_name,
|
|
hypertable_row.schema_name, hypertable_row.table_name, tablespace_clause
|
|
);
|
|
|
|
PERFORM _timescaledb_internal.chunk_add_constraints(chunk_id);
|
|
END
|
|
$BODY$;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.dimension_slice_get_constraint_sql(
|
|
dimension_slice_id INTEGER
|
|
)
|
|
RETURNS TEXT LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
dimension_slice_row _timescaledb_catalog.dimension_slice;
|
|
dimension_row _timescaledb_catalog.dimension;
|
|
BEGIN
|
|
SELECT * INTO STRICT dimension_slice_row
|
|
FROM _timescaledb_catalog.dimension_slice
|
|
WHERE id = dimension_slice_id;
|
|
|
|
SELECT * INTO STRICT dimension_row
|
|
FROM _timescaledb_catalog.dimension
|
|
WHERE id = dimension_slice_row.dimension_id;
|
|
|
|
IF dimension_row.partitioning_func IS NOT NULL THEN
|
|
return format(
|
|
$$
|
|
%1$I.%2$s(%3$I::text) >= %4$L AND %1$I.%2$s(%3$I::text) < %5$L
|
|
$$,
|
|
dimension_row.partitioning_func_schema, dimension_row.partitioning_func,
|
|
dimension_row.column_name, dimension_slice_row.range_start, dimension_slice_row.range_end);
|
|
ELSE
|
|
--TODO: only works with time for now
|
|
return format(
|
|
$$
|
|
%1$I >= %2$s AND %1$I < %3$s
|
|
$$,
|
|
dimension_row.column_name,
|
|
_timescaledb_internal.time_literal_sql(dimension_slice_row.range_start, dimension_row.column_type),
|
|
_timescaledb_internal.time_literal_sql(dimension_slice_row.range_end, dimension_row.column_type));
|
|
END IF;
|
|
END
|
|
$BODY$;
|
|
|
|
CREATE OR REPLACE FUNCTION _timescaledb_internal.chunk_add_constraints(
|
|
chunk_id INTEGER
|
|
)
|
|
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
|
|
$BODY$
|
|
DECLARE
|
|
constraint_row record;
|
|
BEGIN
|
|
FOR constraint_row IN
|
|
SELECT c.schema_name, c.table_name, ds.id as dimension_slice_id
|
|
FROM _timescaledb_catalog.chunk c
|
|
INNER JOIN _timescaledb_catalog.chunk_constraint cc ON (cc.chunk_id = c.id)
|
|
INNER JOIN _timescaledb_catalog.dimension_slice ds ON (ds.id = cc.dimension_slice_id)
|
|
WHERE c.id = chunk_add_constraints.chunk_id
|
|
LOOP
|
|
EXECUTE format(
|
|
$$
|
|
ALTER TABLE %1$I.%2$I
|
|
ADD CONSTRAINT constraint_%3$s CHECK(%4$s)
|
|
$$,
|
|
constraint_row.schema_name, constraint_row.table_name,
|
|
constraint_row.dimension_slice_id,
|
|
_timescaledb_internal.dimension_slice_get_constraint_sql(constraint_row.dimension_slice_id)
|
|
);
|
|
END LOOP;
|
|
END
|
|
$BODY$;
|