timescaledb/sql/updates/reverse-dev.sql
Sven Klemm 101e4c57ef Add recompress optional argument to compress_chunk
This patch deprecates the recompress_chunk procedure as all that
functionality is covered by compress_chunk now. This patch also adds a
new optional boolean argument to compress_chunk to force applying
changed compression settings to existing compressed chunks.
2024-02-07 12:19:13 +01:00

798 lines
36 KiB
PL/PgSQL

-- check whether we can safely downgrade compression setup
DO $$
DECLARE
hypertable regclass;
ht_uncomp regclass;
chunk_relids oid[];
ht_id integer;
BEGIN
FOR hypertable, ht_uncomp, ht_id IN
SELECT
format('%I.%I',ht.schema_name,ht.table_name)::regclass,
format('%I.%I',ht_uncomp.schema_name,ht_uncomp.table_name)::regclass,
ht.id
FROM _timescaledb_catalog.hypertable ht_uncomp
INNER JOIN _timescaledb_catalog.hypertable ht
ON ht.id = ht_uncomp.compressed_hypertable_id
LOOP
-- hypertables need to at least have 1 compressed chunk so we can restore the columns
IF NOT EXISTS(SELECT FROM _timescaledb_catalog.chunk WHERE hypertable_id = ht_id) THEN
RAISE USING
ERRCODE = 'feature_not_supported',
MESSAGE = 'Cannot downgrade compressed hypertables with no compressed chunks. Disable compression on the affected hypertable before downgrading.',
DETAIL = 'The following hypertable is affected: '|| ht_uncomp::text;
END IF;
chunk_relids := array(SELECT format('%I.%I',schema_name,table_name)::regclass FROM _timescaledb_catalog.chunk WHERE hypertable_id = ht_id);
-- any hypertable with distinct compression settings cannot be downgraded
IF EXISTS (
SELECT FROM (
SELECT DISTINCT segmentby, orderby, orderby_desc, orderby_nullsfirst
FROM _timescaledb_catalog.compression_settings
WHERE relid = hypertable OR relid = ANY(chunk_relids)
) dist_settings HAVING count(*) > 1
) THEN
RAISE USING
ERRCODE = 'feature_not_supported',
MESSAGE = 'Cannot downgrade hypertables with distinct compression settings. Decompress the affected hypertable before downgrading.',
DETAIL = 'The following hypertable is affected: '|| ht_uncomp::text;
END IF;
END LOOP;
END
$$;
CREATE FUNCTION _timescaledb_functions.tmp_resolve_indkeys(oid,int2[]) RETURNS text[] LANGUAGE SQL AS $$
SELECT array_agg(attname)
FROM (
SELECT attname
FROM (SELECT unnest($2) attnum) indkeys
JOIN LATERAL (
SELECT attname FROM pg_attribute att WHERE att.attnum=indkeys.attnum AND att.attrelid=$1
) r ON true
) resolve;
$$ SET search_path TO pg_catalog, pg_temp;
DO $$
DECLARE
chunk regclass;
hypertable regclass;
ht_id integer;
chunk_id integer;
_index regclass;
ht_index regclass;
chunk_index regclass;
index_name name;
chunk_index_name name;
_indkey text[];
column_name name;
column_type regtype;
cmd text;
BEGIN
SET timescaledb.restoring TO ON;
FOR hypertable, ht_id IN
SELECT
format('%I.%I',ht.schema_name,ht.table_name)::regclass,
ht.id
FROM _timescaledb_catalog.hypertable ht_uncomp
INNER JOIN _timescaledb_catalog.hypertable ht
ON ht.id = ht_uncomp.compressed_hypertable_id
LOOP
-- get first chunk which we use as template for restoring columns and indexes
SELECT format('%I.%I',schema_name,table_name)::regclass INTO STRICT chunk FROM _timescaledb_catalog.chunk WHERE hypertable_id = ht_id ORDER by id LIMIT 1;
-- restore columns from the compressed hypertable
FOR column_name, column_type IN
SELECT attname, atttypid::regtype FROM pg_attribute WHERE attrelid = chunk AND attnum > 0
LOOP
cmd := format('ALTER TABLE %s ADD COLUMN %I %s', hypertable, column_name, column_type);
EXECUTE cmd;
END LOOP;
-- restore indexes on the compressed hypertable
FOR _index, _indkey IN
SELECT indexrelid::regclass, _timescaledb_functions.tmp_resolve_indkeys(indrelid, indkey) FROM pg_index WHERE indrelid = chunk
LOOP
SELECT relname INTO STRICT index_name FROM pg_class WHERE oid = _index;
cmd := pg_get_indexdef(_index);
cmd := replace(cmd, format(' INDEX %s ON ', index_name), ' INDEX ON ');
cmd := replace(cmd, chunk::text, hypertable::text);
EXECUTE cmd;
-- get indexrelid of index we just created on hypertable
SELECT indexrelid INTO STRICT ht_index FROM pg_index WHERE indrelid = hypertable AND _timescaledb_functions.tmp_resolve_indkeys(hypertable, indkey) = _indkey;
SELECT relname INTO STRICT index_name FROM pg_class WHERE oid = ht_index;
-- restore indexes in our catalog
FOR chunk, chunk_id IN
SELECT format('%I.%I',schema_name,table_name)::regclass, id FROM _timescaledb_catalog.chunk WHERE hypertable_id = ht_id
LOOP
SELECT indexrelid INTO STRICT chunk_index FROM pg_index WHERE indrelid = chunk AND _timescaledb_functions.tmp_resolve_indkeys(chunk, indkey) = _indkey;
SELECT relname INTO STRICT chunk_index_name FROM pg_class WHERE oid = chunk_index;
INSERT INTO _timescaledb_catalog.chunk_index (chunk_id, index_name, hypertable_id, hypertable_index_name)
VALUES (chunk_id, chunk_index_name, ht_id, index_name);
END LOOP;
END LOOP;
-- restore inheritance
cmd := format('ALTER TABLE %s INHERIT %s', chunk, hypertable);
EXECUTE cmd;
END LOOP;
SET timescaledb.restoring TO OFF;
END $$;
DROP FUNCTION _timescaledb_functions.tmp_resolve_indkeys;
CREATE FUNCTION _timescaledb_functions.ping_data_node(node_name NAME, timeout INTERVAL = NULL) RETURNS BOOLEAN
AS '@MODULE_PATHNAME@', 'ts_data_node_ping' LANGUAGE C VOLATILE;
CREATE FUNCTION _timescaledb_functions.remote_txn_heal_data_node(foreign_server_oid oid)
RETURNS INT
AS '@MODULE_PATHNAME@', 'ts_remote_txn_heal_data_node'
LANGUAGE C STRICT;
CREATE FUNCTION _timescaledb_functions.set_dist_id(dist_id UUID) RETURNS BOOL
AS '@MODULE_PATHNAME@', 'ts_dist_set_id' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION _timescaledb_functions.set_peer_dist_id(dist_id UUID) RETURNS BOOL
AS '@MODULE_PATHNAME@', 'ts_dist_set_peer_id' LANGUAGE C VOLATILE STRICT;
-- Function to validate that a node has local settings to function as
-- a data node. Throws error if validation fails.
CREATE FUNCTION _timescaledb_functions.validate_as_data_node() RETURNS void
AS '@MODULE_PATHNAME@', 'ts_dist_validate_as_data_node' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION _timescaledb_functions.show_connection_cache()
RETURNS TABLE (
node_name name,
user_name name,
host text,
port int,
database name,
backend_pid int,
connection_status text,
transaction_status text,
transaction_depth int,
processing boolean,
invalidated boolean)
AS '@MODULE_PATHNAME@', 'ts_remote_connection_cache_show' LANGUAGE C VOLATILE STRICT;
DROP FUNCTION IF EXISTS @extschema@.create_hypertable(relation REGCLASS, time_column_name NAME, partitioning_column NAME, number_partitions INTEGER, associated_schema_name NAME, associated_table_prefix NAME, chunk_time_interval ANYELEMENT, create_default_indexes BOOLEAN, if_not_exists BOOLEAN, partitioning_func REGPROC, migrate_data BOOLEAN, chunk_target_size TEXT, chunk_sizing_func REGPROC, time_partitioning_func REGPROC);
CREATE FUNCTION @extschema@.create_hypertable(
relation REGCLASS,
time_column_name NAME,
partitioning_column NAME = NULL,
number_partitions INTEGER = NULL,
associated_schema_name NAME = NULL,
associated_table_prefix NAME = NULL,
chunk_time_interval ANYELEMENT = NULL::bigint,
create_default_indexes BOOLEAN = TRUE,
if_not_exists BOOLEAN = FALSE,
partitioning_func REGPROC = NULL,
migrate_data BOOLEAN = FALSE,
chunk_target_size TEXT = NULL,
chunk_sizing_func REGPROC = '_timescaledb_functions.calculate_chunk_interval'::regproc,
time_partitioning_func REGPROC = NULL,
replication_factor INTEGER = NULL,
data_nodes NAME[] = NULL,
distributed BOOLEAN = NULL
) RETURNS TABLE(hypertable_id INT, schema_name NAME, table_name NAME, created BOOL) AS '@MODULE_PATHNAME@', 'ts_hypertable_create' LANGUAGE C VOLATILE;
CREATE FUNCTION @extschema@.create_distributed_hypertable(
relation REGCLASS,
time_column_name NAME,
partitioning_column NAME = NULL,
number_partitions INTEGER = NULL,
associated_schema_name NAME = NULL,
associated_table_prefix NAME = NULL,
chunk_time_interval ANYELEMENT = NULL::bigint,
create_default_indexes BOOLEAN = TRUE,
if_not_exists BOOLEAN = FALSE,
partitioning_func REGPROC = NULL,
migrate_data BOOLEAN = FALSE,
chunk_target_size TEXT = NULL,
chunk_sizing_func REGPROC = '_timescaledb_functions.calculate_chunk_interval'::regproc,
time_partitioning_func REGPROC = NULL,
replication_factor INTEGER = NULL,
data_nodes NAME[] = NULL
) RETURNS TABLE(hypertable_id INT, schema_name NAME, table_name NAME, created BOOL) AS '@MODULE_PATHNAME@', 'ts_hypertable_distributed_create' LANGUAGE C VOLATILE;
CREATE FUNCTION @extschema@.add_data_node(
node_name NAME,
host TEXT,
database NAME = NULL,
port INTEGER = NULL,
if_not_exists BOOLEAN = FALSE,
bootstrap BOOLEAN = TRUE,
password TEXT = NULL
) RETURNS TABLE(node_name NAME, host TEXT, port INTEGER, database NAME,
node_created BOOL, database_created BOOL, extension_created BOOL)
AS '@MODULE_PATHNAME@', 'ts_data_node_add' LANGUAGE C VOLATILE;
CREATE FUNCTION @extschema@.delete_data_node(
node_name NAME,
if_exists BOOLEAN = FALSE,
force BOOLEAN = FALSE,
repartition BOOLEAN = TRUE,
drop_database BOOLEAN = FALSE
) RETURNS BOOLEAN AS '@MODULE_PATHNAME@', 'ts_data_node_delete' LANGUAGE C VOLATILE;
CREATE FUNCTION @extschema@.attach_data_node(
node_name NAME,
hypertable REGCLASS,
if_not_attached BOOLEAN = FALSE,
repartition BOOLEAN = TRUE
) RETURNS TABLE(hypertable_id INTEGER, node_hypertable_id INTEGER, node_name NAME)
AS '@MODULE_PATHNAME@', 'ts_data_node_attach' LANGUAGE C VOLATILE;
CREATE FUNCTION @extschema@.detach_data_node(
node_name NAME,
hypertable REGCLASS = NULL,
if_attached BOOLEAN = FALSE,
force BOOLEAN = FALSE,
repartition BOOLEAN = TRUE,
drop_remote_data BOOLEAN = FALSE
) RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_data_node_detach' LANGUAGE C VOLATILE;
CREATE FUNCTION @extschema@.alter_data_node(
node_name NAME,
host TEXT = NULL,
database NAME = NULL,
port INTEGER = NULL,
available BOOLEAN = NULL
) RETURNS TABLE(node_name NAME, host TEXT, port INTEGER, database NAME, available BOOLEAN)
AS '@MODULE_PATHNAME@', 'ts_data_node_alter' LANGUAGE C VOLATILE;
CREATE PROCEDURE @extschema@.distributed_exec(
query TEXT,
node_list name[] = NULL,
transactional BOOLEAN = TRUE)
AS '@MODULE_PATHNAME@', 'ts_distributed_exec' LANGUAGE C;
CREATE FUNCTION @extschema@.create_distributed_restore_point(
name TEXT
) RETURNS TABLE(node_name NAME, node_type TEXT, restore_point pg_lsn)
AS '@MODULE_PATHNAME@', 'ts_create_distributed_restore_point' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION @extschema@.set_replication_factor(
hypertable REGCLASS,
replication_factor INTEGER
) RETURNS VOID
AS '@MODULE_PATHNAME@', 'ts_hypertable_distributed_set_replication_factor' LANGUAGE C VOLATILE;
CREATE TABLE _timescaledb_catalog.hypertable_compression (
hypertable_id integer NOT NULL,
attname name NOT NULL,
compression_algorithm_id smallint,
segmentby_column_index smallint,
orderby_column_index smallint,
orderby_asc boolean,
orderby_nullsfirst boolean,
-- table constraints
CONSTRAINT hypertable_compression_pkey PRIMARY KEY (hypertable_id, attname),
CONSTRAINT hypertable_compression_hypertable_id_orderby_column_index_key UNIQUE (hypertable_id, orderby_column_index),
CONSTRAINT hypertable_compression_hypertable_id_segmentby_column_index_key UNIQUE (hypertable_id, segmentby_column_index),
CONSTRAINT hypertable_compression_compression_algorithm_id_fkey FOREIGN KEY (compression_algorithm_id) REFERENCES _timescaledb_catalog.compression_algorithm (id)
);
INSERT INTO _timescaledb_catalog.hypertable_compression(
hypertable_id,
attname,
compression_algorithm_id,
segmentby_column_index,
orderby_column_index,
orderby_asc,
orderby_nullsfirst
) SELECT
ht.id,
att.attname,
CASE
WHEN att.attname = ANY(cs.segmentby) THEN 0
WHEN att.atttypid IN ('numeric'::regtype) THEN 1
WHEN att.atttypid IN ('float4'::regtype,'float8'::regtype) THEN 3
WHEN att.atttypid IN ('int2'::regtype,'int4'::regtype,'int8'::regtype,'date'::regtype,'timestamp'::regtype,'timestamptz'::regtype) THEN 4
WHEN EXISTS(SELECT FROM pg_operator op WHERE op.oprname = '=' AND op.oprkind = 'b' AND op.oprcanhash = true AND op.oprleft = att.atttypid AND op.oprright = att.atttypid) THEN 2
ELSE 1
END AS compression_algorithm_id,
CASE WHEN att.attname = ANY(cs.segmentby) THEN array_position(cs.segmentby, att.attname::text) ELSE NULL END AS segmentby_column_index,
CASE WHEN att.attname = ANY(cs.orderby) THEN array_position(cs.orderby, att.attname::text) ELSE NULL END AS orderby_column_index,
CASE WHEN att.attname = ANY(cs.orderby) THEN NOT cs.orderby_desc[array_position(cs.orderby, att.attname::text)] ELSE false END AS orderby_asc,
CASE WHEN att.attname = ANY(cs.orderby) THEN cs.orderby_nullsfirst[array_position(cs.orderby, att.attname::text)] ELSE false END AS orderby_nullsfirst
FROM _timescaledb_catalog.hypertable ht
INNER JOIN _timescaledb_catalog.compression_settings cs ON cs.relid = format('%I.%I',ht.schema_name,ht.table_name)::regclass
LEFT JOIN pg_attribute att ON att.attrelid = format('%I.%I',ht.schema_name,ht.table_name)::regclass AND attnum > 0
WHERE compressed_hypertable_id IS NOT NULL;
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.hypertable_compression', '');
GRANT SELECT ON _timescaledb_catalog.hypertable_compression TO PUBLIC;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.compression_settings;
DROP VIEW timescaledb_information.compression_settings;
ALTER EXTENSION timescaledb DROP TABLE _timescaledb_catalog.compression_settings;
DROP TABLE _timescaledb_catalog.compression_settings;
CREATE FUNCTION @extschema@.timescaledb_fdw_handler() RETURNS fdw_handler AS '@MODULE_PATHNAME@', 'ts_timescaledb_fdw_handler' LANGUAGE C STRICT;
CREATE FUNCTION @extschema@.timescaledb_fdw_validator(text[], oid) RETURNS void AS '@MODULE_PATHNAME@', 'ts_timescaledb_fdw_validator' LANGUAGE C STRICT;
CREATE FOREIGN DATA WRAPPER timescaledb_fdw HANDLER @extschema@.timescaledb_fdw_handler VALIDATOR @extschema@.timescaledb_fdw_validator;
CREATE FUNCTION _timescaledb_functions.create_chunk_replica_table(
chunk REGCLASS,
data_node_name NAME
) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_chunk_create_replica_table' LANGUAGE C VOLATILE;
CREATE FUNCTION _timescaledb_functions.chunk_drop_replica(
chunk REGCLASS,
node_name NAME
) RETURNS VOID
AS '@MODULE_PATHNAME@', 'ts_chunk_drop_replica' LANGUAGE C VOLATILE;
CREATE PROCEDURE _timescaledb_functions.wait_subscription_sync(
schema_name NAME,
table_name NAME,
retry_count INT DEFAULT 18000,
retry_delay_ms NUMERIC DEFAULT 0.200
)
LANGUAGE PLPGSQL AS
$BODY$
DECLARE
in_sync BOOLEAN;
BEGIN
FOR i in 1 .. retry_count
LOOP
SELECT pgs.srsubstate = 'r'
INTO in_sync
FROM pg_subscription_rel pgs
JOIN pg_class pgc ON relname = table_name
JOIN pg_namespace n ON (n.OID = pgc.relnamespace)
WHERE pgs.srrelid = pgc.oid AND schema_name = n.nspname;
if (in_sync IS NULL OR NOT in_sync) THEN
PERFORM pg_sleep(retry_delay_ms);
ELSE
RETURN;
END IF;
END LOOP;
RAISE 'subscription sync wait timedout';
END
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE FUNCTION _timescaledb_functions.health() RETURNS
TABLE (node_name NAME, healthy BOOL, in_recovery BOOL, error TEXT)
AS '@MODULE_PATHNAME@', 'ts_health_check' LANGUAGE C VOLATILE;
CREATE FUNCTION _timescaledb_functions.drop_stale_chunks(
node_name NAME,
chunks integer[] = NULL
) RETURNS VOID
AS '@MODULE_PATHNAME@', 'ts_chunks_drop_stale' LANGUAGE C VOLATILE;
CREATE FUNCTION _timescaledb_functions.rxid_in(cstring) RETURNS @extschema@.rxid
AS '@MODULE_PATHNAME@', 'ts_remote_txn_id_in' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION _timescaledb_functions.rxid_out(@extschema@.rxid) RETURNS cstring
AS '@MODULE_PATHNAME@', 'ts_remote_txn_id_out' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE TYPE @extschema@.rxid (
internallength = 16,
input = _timescaledb_functions.rxid_in,
output = _timescaledb_functions.rxid_out
);
CREATE FUNCTION _timescaledb_functions.data_node_hypertable_info(
node_name NAME,
schema_name_in name,
table_name_in name
)
RETURNS TABLE (
table_bytes bigint,
index_bytes bigint,
toast_bytes bigint,
total_bytes bigint)
AS '@MODULE_PATHNAME@', 'ts_dist_remote_hypertable_info' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION _timescaledb_functions.data_node_chunk_info(
node_name NAME,
schema_name_in name,
table_name_in name
)
RETURNS TABLE (
chunk_id integer,
chunk_schema name,
chunk_name name,
table_bytes bigint,
index_bytes bigint,
toast_bytes bigint,
total_bytes bigint)
AS '@MODULE_PATHNAME@', 'ts_dist_remote_chunk_info' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION _timescaledb_functions.data_node_compressed_chunk_stats(node_name name, schema_name_in name, table_name_in name)
RETURNS TABLE (
chunk_schema name,
chunk_name name,
compression_status text,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint
)
AS '@MODULE_PATHNAME@' , 'ts_dist_remote_compressed_chunk_info' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION _timescaledb_functions.data_node_index_size(node_name name, schema_name_in name, index_name_in name)
RETURNS TABLE ( hypertable_id INTEGER, total_bytes BIGINT)
AS '@MODULE_PATHNAME@' , 'ts_dist_remote_hypertable_index_info' LANGUAGE C VOLATILE STRICT;
CREATE FUNCTION timescaledb_experimental.block_new_chunks(data_node_name NAME, hypertable REGCLASS = NULL, force BOOLEAN = FALSE) RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_data_node_block_new_chunks' LANGUAGE C VOLATILE;
CREATE FUNCTION timescaledb_experimental.allow_new_chunks(data_node_name NAME, hypertable REGCLASS = NULL) RETURNS INTEGER
AS '@MODULE_PATHNAME@', 'ts_data_node_allow_new_chunks' LANGUAGE C VOLATILE;
CREATE PROCEDURE timescaledb_experimental.move_chunk(
chunk REGCLASS,
source_node NAME = NULL,
destination_node NAME = NULL,
operation_id NAME = NULL)
AS '@MODULE_PATHNAME@', 'ts_move_chunk_proc' LANGUAGE C;
CREATE PROCEDURE timescaledb_experimental.copy_chunk(
chunk REGCLASS,
source_node NAME = NULL,
destination_node NAME = NULL,
operation_id NAME = NULL)
AS '@MODULE_PATHNAME@', 'ts_copy_chunk_proc' LANGUAGE C;
CREATE FUNCTION timescaledb_experimental.subscription_exec(
subscription_command TEXT
) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_subscription_exec' LANGUAGE C VOLATILE;
CREATE PROCEDURE timescaledb_experimental.cleanup_copy_chunk_operation(
operation_id NAME)
AS '@MODULE_PATHNAME@', 'ts_copy_chunk_cleanup_proc' LANGUAGE C;
CREATE FUNCTION _timescaledb_functions.set_chunk_default_data_node(chunk REGCLASS, node_name NAME) RETURNS BOOLEAN
AS '@MODULE_PATHNAME@', 'ts_chunk_set_default_data_node' LANGUAGE C VOLATILE;
CREATE FUNCTION _timescaledb_functions.drop_dist_ht_invalidation_trigger(
raw_hypertable_id INTEGER
) RETURNS VOID AS '@MODULE_PATHNAME@', 'ts_drop_dist_ht_invalidation_trigger' LANGUAGE C STRICT VOLATILE;
-- restore multinode catalog tables
CREATE TABLE _timescaledb_catalog.remote_txn (
data_node_name name, --this is really only to allow us to cleanup stuff on a per-node basis.
remote_transaction_id text NOT NULL,
-- table constraints
CONSTRAINT remote_txn_pkey PRIMARY KEY (remote_transaction_id)
);
ALTER TABLE _timescaledb_catalog.remote_txn ADD CONSTRAINT remote_txn_remote_transaction_id_check CHECK (remote_transaction_id::@extschema@.rxid IS NOT NULL);
CREATE INDEX remote_txn_data_node_name_idx ON _timescaledb_catalog.remote_txn (data_node_name);
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.remote_txn', '');
GRANT SELECT ON TABLE _timescaledb_catalog.remote_txn TO PUBLIC;
CREATE TABLE _timescaledb_catalog.hypertable_data_node (
hypertable_id integer NOT NULL,
node_hypertable_id integer NULL,
node_name name NOT NULL,
block_chunks boolean NOT NULL,
-- table constraints
CONSTRAINT hypertable_data_node_hypertable_id_node_name_key UNIQUE (hypertable_id, node_name),
CONSTRAINT hypertable_data_node_node_hypertable_id_node_name_key UNIQUE (node_hypertable_id, node_name),
CONSTRAINT hypertable_data_node_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable (id)
);
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.hypertable_data_node', '');
GRANT SELECT ON TABLE _timescaledb_catalog.hypertable_data_node TO PUBLIC;
CREATE TABLE _timescaledb_catalog.chunk_data_node (
chunk_id integer NOT NULL,
node_chunk_id integer NOT NULL,
node_name name NOT NULL,
-- table constraints
CONSTRAINT chunk_data_node_chunk_id_node_name_key UNIQUE (chunk_id, node_name),
CONSTRAINT chunk_data_node_node_chunk_id_node_name_key UNIQUE (node_chunk_id, node_name),
CONSTRAINT chunk_data_node_chunk_id_fkey FOREIGN KEY (chunk_id) REFERENCES _timescaledb_catalog.chunk (id)
);
CREATE INDEX chunk_data_node_node_name_idx ON _timescaledb_catalog.chunk_data_node (node_name);
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.chunk_data_node', '');
GRANT SELECT ON TABLE _timescaledb_catalog.chunk_data_node TO PUBLIC;
CREATE SEQUENCE _timescaledb_catalog.chunk_copy_operation_id_seq MINVALUE 1;
GRANT SELECT ON SEQUENCE _timescaledb_catalog.chunk_copy_operation_id_seq TO PUBLIC;
CREATE TABLE _timescaledb_catalog.chunk_copy_operation (
operation_id name NOT NULL, -- the publisher/subscriber identifier used
backend_pid integer NOT NULL, -- the pid of the backend running this activity
completed_stage name NOT NULL, -- the completed stage/step
time_start timestamptz NOT NULL DEFAULT NOW(), -- start time of the activity
chunk_id integer NOT NULL,
compress_chunk_name name NOT NULL,
source_node_name name NOT NULL,
dest_node_name name NOT NULL,
delete_on_source_node bool NOT NULL, -- is a move or copy activity
-- table constraints
CONSTRAINT chunk_copy_operation_pkey PRIMARY KEY (operation_id),
CONSTRAINT chunk_copy_operation_chunk_id_fkey FOREIGN KEY (chunk_id) REFERENCES _timescaledb_catalog.chunk (id) ON DELETE CASCADE
);
GRANT SELECT ON TABLE _timescaledb_catalog.chunk_copy_operation TO PUBLIC;
CREATE TABLE _timescaledb_catalog.dimension_partition (
dimension_id integer NOT NULL REFERENCES _timescaledb_catalog.dimension (id) ON DELETE CASCADE,
range_start bigint NOT NULL,
data_nodes name[] NULL,
UNIQUE (dimension_id, range_start)
);
GRANT SELECT ON TABLE _timescaledb_catalog.dimension_partition TO PUBLIC;
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.dimension_partition', '');
CREATE FUNCTION _timescaledb_functions.hypertable_remote_size(
schema_name_in name,
table_name_in name)
RETURNS TABLE (
table_bytes bigint,
index_bytes bigint,
toast_bytes bigint,
total_bytes bigint,
node_name NAME)
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE FUNCTION _timescaledb_functions.chunks_remote_size(
schema_name_in name,
table_name_in name)
RETURNS TABLE (
chunk_id integer,
chunk_schema NAME,
chunk_name NAME,
table_bytes bigint,
index_bytes bigint,
toast_bytes bigint,
total_bytes bigint,
node_name NAME)
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE FUNCTION _timescaledb_functions.indexes_remote_size(
schema_name_in NAME,
table_name_in NAME,
index_name_in NAME
)
RETURNS BIGINT
LANGUAGE SQL VOLATILE STRICT AS
$BODY$
$BODY$ SET search_path TO pg_catalog, pg_temp;
CREATE FUNCTION _timescaledb_functions.compressed_chunk_remote_stats(schema_name_in name, table_name_in name)
RETURNS TABLE (
chunk_schema name,
chunk_name name,
compression_status text,
before_compression_table_bytes bigint,
before_compression_index_bytes bigint,
before_compression_toast_bytes bigint,
before_compression_total_bytes bigint,
after_compression_table_bytes bigint,
after_compression_index_bytes bigint,
after_compression_toast_bytes bigint,
after_compression_total_bytes bigint,
node_name name)
LANGUAGE SQL
STABLE STRICT
AS
$BODY$
$BODY$ SET search_path TO pg_catalog, pg_temp;
-- recreate the _timescaledb_catalog.hypertable table as new field was added
-- 1. drop CONSTRAINTS from other tables referencing the existing one
ALTER TABLE _timescaledb_config.bgw_job
DROP CONSTRAINT bgw_job_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.chunk
DROP CONSTRAINT chunk_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.chunk_index
DROP CONSTRAINT chunk_index_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.continuous_agg
DROP CONSTRAINT continuous_agg_mat_hypertable_id_fkey,
DROP CONSTRAINT continuous_agg_raw_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.continuous_aggs_bucket_function
DROP CONSTRAINT continuous_aggs_bucket_function_mat_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.continuous_aggs_invalidation_threshold
DROP CONSTRAINT continuous_aggs_invalidation_threshold_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.dimension
DROP CONSTRAINT dimension_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.hypertable
DROP CONSTRAINT hypertable_compressed_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.hypertable_data_node
DROP CONSTRAINT hypertable_data_node_hypertable_id_fkey;
ALTER TABLE _timescaledb_catalog.tablespace
DROP CONSTRAINT tablespace_hypertable_id_fkey;
-- drop dependent views
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.hypertables;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.job_stats;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.jobs;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.continuous_aggregates;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.chunks;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_information.dimensions;
ALTER EXTENSION timescaledb DROP VIEW _timescaledb_internal.hypertable_chunk_local_size;
ALTER EXTENSION timescaledb DROP VIEW _timescaledb_internal.compressed_chunk_stats;
ALTER EXTENSION timescaledb DROP VIEW timescaledb_experimental.policies;
DROP VIEW timescaledb_information.hypertables;
DROP VIEW timescaledb_information.job_stats;
DROP VIEW timescaledb_information.jobs;
DROP VIEW timescaledb_information.continuous_aggregates;
DROP VIEW timescaledb_information.chunks;
DROP VIEW timescaledb_information.dimensions;
DROP VIEW _timescaledb_internal.hypertable_chunk_local_size;
DROP VIEW _timescaledb_internal.compressed_chunk_stats;
DROP VIEW timescaledb_experimental.policies;
-- recreate table
CREATE TABLE _timescaledb_catalog.hypertable_tmp AS SELECT * FROM _timescaledb_catalog.hypertable;
CREATE TABLE _timescaledb_catalog.tmp_hypertable_seq_value AS SELECT last_value, is_called FROM _timescaledb_catalog.hypertable_id_seq;
ALTER EXTENSION timescaledb DROP TABLE _timescaledb_catalog.hypertable;
ALTER EXTENSION timescaledb DROP SEQUENCE _timescaledb_catalog.hypertable_id_seq;
SET timescaledb.restoring = on; -- must disable the hooks otherwise we can't do anything without the table _timescaledb_catalog.hypertable
DROP TABLE _timescaledb_catalog.hypertable;
CREATE SEQUENCE _timescaledb_catalog.hypertable_id_seq MINVALUE 1;
SELECT setval('_timescaledb_catalog.hypertable_id_seq', last_value, is_called) FROM _timescaledb_catalog.tmp_hypertable_seq_value;
DROP TABLE _timescaledb_catalog.tmp_hypertable_seq_value;
CREATE TABLE _timescaledb_catalog.hypertable (
id INTEGER PRIMARY KEY NOT NULL DEFAULT nextval('_timescaledb_catalog.hypertable_id_seq'),
schema_name name NOT NULL,
table_name name NOT NULL,
associated_schema_name name NOT NULL,
associated_table_prefix name NOT NULL,
num_dimensions smallint NOT NULL,
chunk_sizing_func_schema name NOT NULL,
chunk_sizing_func_name name NOT NULL,
chunk_target_size bigint NOT NULL, -- size in bytes
compression_state smallint NOT NULL DEFAULT 0,
compressed_hypertable_id integer,
replication_factor smallint NULL,
status int NOT NULL DEFAULT 0
);
SET timescaledb.restoring = off;
INSERT INTO _timescaledb_catalog.hypertable (
id,
schema_name,
table_name,
associated_schema_name,
associated_table_prefix,
num_dimensions,
chunk_sizing_func_schema,
chunk_sizing_func_name,
chunk_target_size,
compression_state,
compressed_hypertable_id
)
SELECT
id,
schema_name,
table_name,
associated_schema_name,
associated_table_prefix,
num_dimensions,
chunk_sizing_func_schema,
chunk_sizing_func_name,
chunk_target_size,
compression_state,
compressed_hypertable_id
FROM
_timescaledb_catalog.hypertable_tmp
ORDER BY id;
ALTER SEQUENCE _timescaledb_catalog.hypertable_id_seq OWNED BY _timescaledb_catalog.hypertable.id;
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.hypertable_id_seq', '');
GRANT SELECT ON _timescaledb_catalog.hypertable TO PUBLIC;
GRANT SELECT ON _timescaledb_catalog.hypertable_id_seq TO PUBLIC;
DROP TABLE _timescaledb_catalog.hypertable_tmp;
-- now add any constraints
ALTER TABLE _timescaledb_catalog.hypertable
-- ADD CONSTRAINT hypertable_pkey PRIMARY KEY (id),
ADD CONSTRAINT hypertable_associated_schema_name_associated_table_prefix_key UNIQUE (associated_schema_name, associated_table_prefix),
ADD CONSTRAINT hypertable_table_name_schema_name_key UNIQUE (table_name, schema_name),
ADD CONSTRAINT hypertable_schema_name_check CHECK (schema_name != '_timescaledb_catalog'),
-- internal compressed hypertables have compression state = 2
ADD CONSTRAINT hypertable_dim_compress_check CHECK (num_dimensions > 0 OR compression_state = 2),
ADD CONSTRAINT hypertable_chunk_target_size_check CHECK (chunk_target_size >= 0),
ADD CONSTRAINT hypertable_compress_check CHECK ( (compression_state = 0 OR compression_state = 1 ) OR (compression_state = 2 AND compressed_hypertable_id IS NULL)),
ADD CONSTRAINT hypertable_replication_factor_check CHECK (replication_factor > 0 OR replication_factor = -1),
ADD CONSTRAINT hypertable_compressed_hypertable_id_fkey FOREIGN KEY (compressed_hypertable_id) REFERENCES _timescaledb_catalog.hypertable (id);
GRANT SELECT ON TABLE _timescaledb_catalog.hypertable TO PUBLIC;
-- 3. reestablish constraints on other tables
ALTER TABLE _timescaledb_config.bgw_job
ADD CONSTRAINT bgw_job_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.chunk
ADD CONSTRAINT chunk_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id);
ALTER TABLE _timescaledb_catalog.chunk_index
ADD CONSTRAINT chunk_index_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.continuous_agg
ADD CONSTRAINT continuous_agg_mat_hypertable_id_fkey FOREIGN KEY (mat_hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE,
ADD CONSTRAINT continuous_agg_raw_hypertable_id_fkey FOREIGN KEY (raw_hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.continuous_aggs_bucket_function
ADD CONSTRAINT continuous_aggs_bucket_function_mat_hypertable_id_fkey FOREIGN KEY (mat_hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.continuous_aggs_invalidation_threshold
ADD CONSTRAINT continuous_aggs_invalidation_threshold_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.dimension
ADD CONSTRAINT dimension_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.hypertable_compression
ADD CONSTRAINT hypertable_compression_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
ALTER TABLE _timescaledb_catalog.hypertable_data_node
ADD CONSTRAINT hypertable_data_node_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id);
ALTER TABLE _timescaledb_catalog.tablespace
ADD CONSTRAINT tablespace_hypertable_id_fkey FOREIGN KEY (hypertable_id) REFERENCES _timescaledb_catalog.hypertable(id) ON DELETE CASCADE;
DROP FUNCTION IF EXISTS _timescaledb_debug.extension_state;
DROP SCHEMA IF EXISTS _timescaledb_debug;
DROP FUNCTION IF EXISTS _timescaledb_internal.hypertable_constraint_add_table_fk_constraint;
DROP FUNCTION _timescaledb_functions.constraint_clone;
CREATE FUNCTION _timescaledb_functions.hypertable_constraint_add_table_fk_constraint(user_ht_constraint_name name,user_ht_schema_name name,user_ht_table_name name,compress_ht_id integer) RETURNS void LANGUAGE PLPGSQL AS $$BEGIN END$$ SET search_path TO pg_catalog,pg_temp;
CREATE FUNCTION _timescaledb_functions.chunks_in(record RECORD, chunks INTEGER[]) RETURNS BOOL
AS 'BEGIN END' LANGUAGE PLPGSQL SET search_path TO pg_catalog,pg_temp;
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.metadata', $$
WHERE KEY = 'exported_uuid' $$);
DROP TRIGGER metadata_insert_trigger ON _timescaledb_catalog.metadata;
DROP FUNCTION _timescaledb_functions.metadata_insert_trigger();
DROP FUNCTION IF EXISTS _timescaledb_functions.get_orderby_defaults(regclass,text[]);
DROP FUNCTION IF EXISTS _timescaledb_functions.get_segmentby_defaults(regclass);
--- re-include in the pg_dump config
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_cache.cache_inval_hypertable', '');
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_cache.cache_inval_extension', '');
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_cache.cache_inval_bgw_job', '');
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_internal.job_errors', '');
-- Remove unwanted entry from extconfig and extcondition in pg_extension
ALTER EXTENSION timescaledb DROP TABLE _timescaledb_catalog.hypertable;
-- Associate the above table back to keep the dependencies safe
ALTER EXTENSION timescaledb ADD TABLE _timescaledb_catalog.hypertable;
-- include this now in the config
SELECT pg_catalog.pg_extension_config_dump('_timescaledb_catalog.hypertable', '');
DROP FUNCTION IF EXISTS _timescaledb_functions.relation_approximate_size(relation REGCLASS);
DROP FUNCTION IF EXISTS @extschema@.hypertable_approximate_detailed_size(relation REGCLASS);
DROP FUNCTION IF EXISTS @extschema@.hypertable_approximate_size(hypertable REGCLASS);
DROP FUNCTION IF EXISTS @extschema@.compress_chunk;
CREATE FUNCTION @extschema@.compress_chunk(uncompressed_chunk REGCLASS, if_not_compressed BOOLEAN = true) RETURNS REGCLASS AS '' LANGUAGE SQL SET search_path TO pg_catalog,pg_temp;