timescaledb/sql/main/namespace_triggers.sql
2016-11-07 11:25:58 -05:00

202 lines
5.7 KiB
PL/PgSQL

CREATE OR REPLACE FUNCTION create_schema(
schema_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE SCHEMA %I
$$, schema_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION create_cluster_table(
schema_name NAME,
table_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE TABLE IF NOT EXISTS %I.%I (
time BIGINT NOT NULL
)
$$, schema_name, table_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION create_cluster_distinct_table(
schema_name NAME,
table_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE TABLE IF NOT EXISTS %1$I.%2$I (
field TEXT,
value TEXT,
last_time_approx BIGINT,
PRIMARY KEY(field, value)
);
$$, schema_name, table_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION create_local_distinct_table(
schema_name NAME,
table_name NAME,
cluster_table_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE TABLE IF NOT EXISTS %1$I.%2$I (PRIMARY KEY(field, value))
INHERITS(%1$I.%3$I);
$$, schema_name, table_name, cluster_table_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION create_remote_distinct_table(
schema_name NAME,
local_table_name NAME,
remote_table_name NAME,
cluster_table_name NAME,
server_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE FOREIGN TABLE IF NOT EXISTS %1$I.%2$I () INHERITS(%1$I.%3$I) SERVER %4$I
OPTIONS (schema_name %1$L, table_name %5$L)
$$,
schema_name, remote_table_name, cluster_table_name, server_name, local_table_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION create_master_table(
schema_name NAME,
table_name NAME,
cluster_table_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE TABLE IF NOT EXISTS %1$I.%2$I () INHERITS(%1$I.%3$I)
$$,
schema_name, table_name, cluster_table_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION create_remote_table(
schema_name NAME,
remote_table_name NAME,
master_table_name NAME,
cluster_table_name NAME,
server_name NAME
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
BEGIN
EXECUTE format(
$$
CREATE FOREIGN TABLE IF NOT EXISTS %1$I.%2$I () INHERITS(%1$I.%3$I) SERVER %4$I OPTIONS (schema_name %1$L, table_name %5$L)
$$,
schema_name, remote_table_name, cluster_table_name, server_name, master_table_name);
END
$BODY$;
CREATE OR REPLACE FUNCTION _sysinternal.on_create_namespace()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
DECLARE
remote_node node;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'Only inserts supported on namespace table'
USING ERRCODE = 'IO101';
END IF;
IF NEW.schema_name = 'public' THEN
RAISE EXCEPTION 'public is not an allowed namespace name'
USING ERRCODE = 'IO104';
END IF;
IF position('_' IN NEW.schema_name) = 1 THEN
RAISE EXCEPTION 'Namespace cannot begin with an underscore (_)'
USING ERRCODE = 'IO104';
END IF;
PERFORM create_schema(NEW.schema_name);
PERFORM create_cluster_table(NEW.schema_name, NEW.cluster_table_name);
PERFORM create_cluster_distinct_table(NEW.schema_name, NEW.cluster_distinct_table_name);
RETURN NEW;
END
$BODY$
SET SEARCH_PATH = 'public';
BEGIN;
DROP TRIGGER IF EXISTS trigger_on_create_namespace
ON namespace;
CREATE TRIGGER trigger_on_create_namespace AFTER INSERT OR UPDATE OR DELETE ON namespace
FOR EACH ROW EXECUTE PROCEDURE _sysinternal.on_create_namespace();
COMMIT;
CREATE OR REPLACE FUNCTION _sysinternal.on_create_namespace_node()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
DECLARE
namespace_row namespace;
node_row node;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'Only inserts supported on namespace table'
USING ERRCODE = 'IO101';
END IF;
SELECT *
INTO STRICT namespace_row
FROM namespace AS ns
WHERE ns.name = NEW.namespace_name;
IF NEW.database_name = current_database() THEN
PERFORM create_master_table(namespace_row.schema_name, NEW.master_table_name, namespace_row.cluster_table_name);
PERFORM create_local_distinct_table(namespace_row.schema_name, NEW.distinct_local_table_name,
namespace_row.cluster_distinct_table_name);
ELSE
SELECT *
INTO STRICT node_row
FROM node AS n
WHERE n.database_name = NEW.database_name;
PERFORM create_remote_table(namespace_row.schema_name, NEW.remote_table_name, NEW.master_table_name,
namespace_row.cluster_table_name,
node_row.server_name);
PERFORM create_remote_distinct_table(namespace_row.schema_name, NEW.distinct_local_table_name,
NEW.distinct_remote_table_name,
namespace_row.cluster_distinct_table_name,
node_row.server_name);
END IF;
RETURN NEW;
END
$BODY$
SET SEARCH_PATH = 'public';
BEGIN;
DROP TRIGGER IF EXISTS trigger_on_create_namespace_node
ON namespace_node;
CREATE TRIGGER trigger_on_create_namespace_node AFTER INSERT OR UPDATE OR DELETE ON namespace_node
FOR EACH ROW EXECUTE PROCEDURE _sysinternal.on_create_namespace_node();
COMMIT;