timescaledb/sql/meta/cluster.sql
Rob Kiefer cb90eef350 Rename setup_db() and fix port for local connections
If a user attempts to setup a database while not connecting using
the network, port is NULL and thus fails constraint checks. Instead,
we now use the default Postgres port of 5432 when this happens.

Also, setup_db() is renamed to setup_timescaledb() for clarity in
the presence of other extensions.
2017-03-22 09:26:03 -04:00

167 lines
4.9 KiB
PL/PgSQL

-- Sets a database and hostname as a meta node.
CREATE OR REPLACE FUNCTION set_meta(
hostname TEXT = gethostname(),
port INT = inet_server_port(),
database_name NAME = current_database(),
username TEXT = current_user,
password TEXT = NULL
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
meta_row _timescaledb_catalog.meta;
BEGIN
SELECT *
INTO meta_row
FROM _timescaledb_catalog.meta
LIMIT 1;
IF meta_row IS NULL THEN
IF port IS NULL THEN
port = 5432;
END IF;
PERFORM add_cluster_user(username, password);
PERFORM _timescaledb_internal.setup_meta();
INSERT INTO _timescaledb_catalog.meta (database_name, hostname, port, server_name)
VALUES (database_name, hostname, port, database_name);
ELSE
IF meta_row.database_name <> database_name OR meta_row.hostname <> hostname THEN
RAISE EXCEPTION 'Changing meta info is not supported'
USING ERRCODE = 'IO101';
END IF;
END IF;
END
$BODY$;
-- Adds a new node to the cluster, with its database name and hostname.
CREATE OR REPLACE FUNCTION add_node(
database_name NAME,
hostname TEXT,
port INT
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
schema_name NAME;
new_id REGCLASS;
BEGIN
BEGIN
new_id := nextval(pg_get_serial_sequence('_timescaledb_catalog.node', 'id'));
schema_name := format('remote_%s_%s', new_id, database_name);
IF database_name = current_database() THEN
schema_name = '_timescaledb_catalog';
END IF;
INSERT INTO _timescaledb_catalog.node (database_name, schema_name, server_name, hostname, port, id)
VALUES (database_name, schema_name, database_name, hostname, port, new_id);
EXCEPTION
WHEN SQLSTATE '42710' THEN
RAISE EXCEPTION 'Node % already exists', database_name
USING ERRCODE = 'IO120';
END;
END
$BODY$;
-- Adds new user credentials for the cluster.
CREATE OR REPLACE FUNCTION add_cluster_user(
username TEXT = current_user,
password TEXT = NULL
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
BEGIN
INSERT INTO _timescaledb_catalog.cluster_user (username, password)
VALUES (username, password);
EXCEPTION
WHEN unique_violation THEN
RAISE EXCEPTION 'User % already exists', username
USING ERRCODE = 'IO130';
END
$BODY$;
CREATE OR REPLACE FUNCTION setup_timescaledb(
database NAME = current_database(),
username TEXT = current_user,
password TEXT = NULL,
hostname TEXT = gethostname(),
port INT = inet_server_port()
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
meta_row _timescaledb_catalog.meta;
BEGIN
SELECT *
INTO meta_row
FROM _timescaledb_catalog.meta
LIMIT 1;
IF port IS NULL THEN
port = 5432;
END IF;
IF meta_row IS NULL THEN
PERFORM set_meta(hostname, port, database, username, password);
PERFORM _timescaledb_internal.setup_main();
PERFORM add_node(database, hostname, port);
ELSE
RAISE EXCEPTION 'The node is already configured'
USING ERRCODE = 'IO501';
END IF;
END
$BODY$;
CREATE OR REPLACE FUNCTION add_partition_epoch(
hypertable_id INTEGER,
keyspace_start SMALLINT [],
number_partitions SMALLINT,
partitioning_column NAME,
partitioning_func_schema NAME,
partitioning_func NAME,
tablespace_name NAME
)
RETURNS VOID LANGUAGE SQL VOLATILE AS
$BODY$
WITH epoch AS (
INSERT INTO _timescaledb_catalog.partition_epoch (hypertable_id, start_time, end_time, num_partitions,
partitioning_func_schema, partitioning_func, partitioning_mod, partitioning_column)
VALUES (hypertable_id, NULL, NULL, number_partitions, partitioning_func_schema,
partitioning_func, 32768, partitioning_column)
RETURNING id
)
INSERT INTO _timescaledb_catalog.partition (epoch_id, keyspace_start, keyspace_end, tablespace)
SELECT
epoch.id,
lag(start, 1, 0)
OVER (),
start - 1,
tablespace_name
FROM unnest(keyspace_start :: INT [] || (32768) :: INT) start, epoch
$BODY$;
CREATE OR REPLACE FUNCTION add_equi_partition_epoch(
hypertable_id INTEGER,
number_partitions SMALLINT,
partitioning_column NAME,
partitioning_func_schema NAME,
partitioning_func NAME,
tablespace_name NAME
)
RETURNS VOID LANGUAGE SQL VOLATILE AS
$BODY$
SELECT add_partition_epoch(
hypertable_id,
(SELECT ARRAY(SELECT start * 32768 / (number_partitions)
FROM generate_series(1, number_partitions - 1) AS start) :: SMALLINT []),
number_partitions,
partitioning_column,
partitioning_func_schema,
partitioning_func,
tablespace_name
)
$BODY$;