Upgrade Sql Ts & Timescale improvements (#2495)
* psql & timescale ts upgrade improved * fix typo * fix typo 2 * removed tenant_id from timescale db schema & upgade scipt logic
This commit is contained in:
parent
aabc22d7d2
commit
188c3e5b63
@ -14,33 +14,27 @@
|
||||
-- limitations under the License.
|
||||
--
|
||||
|
||||
-- select check_version();
|
||||
-- call check_version();
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_version() RETURNS boolean AS $$
|
||||
CREATE OR REPLACE PROCEDURE check_version(INOUT valid_version boolean) LANGUAGE plpgsql AS $BODY$
|
||||
DECLARE
|
||||
current_version integer;
|
||||
valid_version boolean;
|
||||
BEGIN
|
||||
RAISE NOTICE 'Check the current installed PostgreSQL version...';
|
||||
SELECT current_setting('server_version_num') INTO current_version;
|
||||
IF current_version < 100000 THEN
|
||||
valid_version := FALSE;
|
||||
ELSE
|
||||
valid_version := TRUE;
|
||||
END IF;
|
||||
IF valid_version = FALSE THEN
|
||||
RAISE NOTICE 'Postgres version should be at least more than 10!';
|
||||
ELSE
|
||||
IF current_version > 110000 THEN
|
||||
RAISE NOTICE 'PostgreSQL version is valid!';
|
||||
RAISE NOTICE 'Schema update started...';
|
||||
SELECT true INTO valid_version;
|
||||
ELSE
|
||||
RAISE NOTICE 'Postgres version should be at least more than 10!';
|
||||
END IF;
|
||||
RETURN valid_version;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$BODY$;
|
||||
|
||||
-- select create_partition_ts_kv_table();
|
||||
-- call create_partition_ts_kv_table();
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_partition_ts_kv_table() RETURNS VOID AS $$
|
||||
CREATE OR REPLACE PROCEDURE create_partition_ts_kv_table() LANGUAGE plpgsql AS $$
|
||||
|
||||
BEGIN
|
||||
ALTER TABLE ts_kv
|
||||
@ -57,11 +51,11 @@ BEGIN
|
||||
ALTER TABLE ts_kv
|
||||
ALTER COLUMN key TYPE integer USING key::integer;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select create_new_ts_kv_latest_table();
|
||||
-- call create_new_ts_kv_latest_table();
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_new_ts_kv_latest_table() RETURNS VOID AS $$
|
||||
CREATE OR REPLACE PROCEDURE create_new_ts_kv_latest_table() LANGUAGE plpgsql AS $$
|
||||
|
||||
BEGIN
|
||||
ALTER TABLE ts_kv_latest
|
||||
@ -81,13 +75,13 @@ BEGIN
|
||||
ALTER TABLE ts_kv_latest
|
||||
ADD CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_id, key);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
|
||||
-- select create_partitions();
|
||||
-- call create_partitions();
|
||||
|
||||
CREATE OR REPLACE PROCEDURE create_partitions() LANGUAGE plpgsql AS $$
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_partitions() RETURNS VOID AS
|
||||
$$
|
||||
DECLARE
|
||||
partition_date varchar;
|
||||
from_ts bigint;
|
||||
@ -111,11 +105,11 @@ BEGIN
|
||||
|
||||
CLOSE key_cursor;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select create_ts_kv_dictionary_table();
|
||||
-- call create_ts_kv_dictionary_table();
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_ts_kv_dictionary_table() RETURNS VOID AS $$
|
||||
CREATE OR REPLACE PROCEDURE create_ts_kv_dictionary_table() LANGUAGE plpgsql AS $$
|
||||
|
||||
BEGIN
|
||||
CREATE TABLE IF NOT EXISTS ts_kv_dictionary
|
||||
@ -125,12 +119,12 @@ BEGIN
|
||||
CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select insert_into_dictionary();
|
||||
-- call insert_into_dictionary();
|
||||
|
||||
CREATE OR REPLACE PROCEDURE insert_into_dictionary() LANGUAGE plpgsql AS $$
|
||||
|
||||
CREATE OR REPLACE FUNCTION insert_into_dictionary() RETURNS VOID AS
|
||||
$$
|
||||
DECLARE
|
||||
insert_record RECORD;
|
||||
key_cursor CURSOR FOR SELECT DISTINCT key
|
||||
@ -150,28 +144,27 @@ BEGIN
|
||||
END LOOP;
|
||||
CLOSE key_cursor;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select insert_into_ts_kv();
|
||||
-- call insert_into_ts_kv();
|
||||
|
||||
CREATE OR REPLACE FUNCTION insert_into_ts_kv() RETURNS void AS
|
||||
$$
|
||||
CREATE OR REPLACE PROCEDURE insert_into_ts_kv() LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
insert_size CONSTANT integer := 10000;
|
||||
insert_counter integer DEFAULT 0;
|
||||
insert_record RECORD;
|
||||
insert_cursor CURSOR FOR SELECT CONCAT(first_part_uuid, '-', second_part_uuid, '-1', third_part_uuid, '-', fourth_part_uuid, '-', fifth_part_uuid)::uuid AS entity_id,
|
||||
insert_cursor CURSOR FOR SELECT CONCAT(entity_id_uuid_first_part, '-', entity_id_uuid_second_part, '-1', entity_id_uuid_third_part, '-', entity_id_uuid_fourth_part, '-', entity_id_uuid_fifth_part)::uuid AS entity_id,
|
||||
ts_kv_records.key AS key,
|
||||
ts_kv_records.ts AS ts,
|
||||
ts_kv_records.bool_v AS bool_v,
|
||||
ts_kv_records.str_v AS str_v,
|
||||
ts_kv_records.long_v AS long_v,
|
||||
ts_kv_records.dbl_v AS dbl_v
|
||||
FROM (SELECT SUBSTRING(entity_id, 8, 8) AS first_part_uuid,
|
||||
SUBSTRING(entity_id, 4, 4) AS second_part_uuid,
|
||||
SUBSTRING(entity_id, 1, 3) AS third_part_uuid,
|
||||
SUBSTRING(entity_id, 16, 4) AS fourth_part_uuid,
|
||||
SUBSTRING(entity_id, 20) AS fifth_part_uuid,
|
||||
FROM (SELECT SUBSTRING(entity_id, 8, 8) AS entity_id_uuid_first_part,
|
||||
SUBSTRING(entity_id, 4, 4) AS entity_id_uuid_second_part,
|
||||
SUBSTRING(entity_id, 1, 3) AS entity_id_uuid_third_part,
|
||||
SUBSTRING(entity_id, 16, 4) AS entity_id_uuid_fourth_part,
|
||||
SUBSTRING(entity_id, 20) AS entity_id_uuid_fifth_part,
|
||||
key_id AS key,
|
||||
ts,
|
||||
bool_v,
|
||||
@ -198,28 +191,27 @@ BEGIN
|
||||
END LOOP;
|
||||
CLOSE insert_cursor;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select insert_into_ts_kv_latest();
|
||||
-- call insert_into_ts_kv_latest();
|
||||
|
||||
CREATE OR REPLACE FUNCTION insert_into_ts_kv_latest() RETURNS void AS
|
||||
$$
|
||||
CREATE OR REPLACE PROCEDURE insert_into_ts_kv_latest() LANGUAGE plpgsql AS $$
|
||||
DECLARE
|
||||
insert_size CONSTANT integer := 10000;
|
||||
insert_counter integer DEFAULT 0;
|
||||
insert_record RECORD;
|
||||
insert_cursor CURSOR FOR SELECT CONCAT(first_part_uuid, '-', second_part_uuid, '-1', third_part_uuid, '-', fourth_part_uuid, '-', fifth_part_uuid)::uuid AS entity_id,
|
||||
insert_cursor CURSOR FOR SELECT CONCAT(entity_id_uuid_first_part, '-', entity_id_uuid_second_part, '-1', entity_id_uuid_third_part, '-', entity_id_uuid_fourth_part, '-', entity_id_uuid_fifth_part)::uuid AS entity_id,
|
||||
ts_kv_latest_records.key AS key,
|
||||
ts_kv_latest_records.ts AS ts,
|
||||
ts_kv_latest_records.bool_v AS bool_v,
|
||||
ts_kv_latest_records.str_v AS str_v,
|
||||
ts_kv_latest_records.long_v AS long_v,
|
||||
ts_kv_latest_records.dbl_v AS dbl_v
|
||||
FROM (SELECT SUBSTRING(entity_id, 8, 8) AS first_part_uuid,
|
||||
SUBSTRING(entity_id, 4, 4) AS second_part_uuid,
|
||||
SUBSTRING(entity_id, 1, 3) AS third_part_uuid,
|
||||
SUBSTRING(entity_id, 16, 4) AS fourth_part_uuid,
|
||||
SUBSTRING(entity_id, 20) AS fifth_part_uuid,
|
||||
FROM (SELECT SUBSTRING(entity_id, 8, 8) AS entity_id_uuid_first_part,
|
||||
SUBSTRING(entity_id, 4, 4) AS entity_id_uuid_second_part,
|
||||
SUBSTRING(entity_id, 1, 3) AS entity_id_uuid_third_part,
|
||||
SUBSTRING(entity_id, 16, 4) AS entity_id_uuid_fourth_part,
|
||||
SUBSTRING(entity_id, 20) AS entity_id_uuid_fifth_part,
|
||||
key_id AS key,
|
||||
ts,
|
||||
bool_v,
|
||||
@ -246,6 +238,6 @@ BEGIN
|
||||
END LOOP;
|
||||
CLOSE insert_cursor;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
|
||||
|
||||
@ -14,60 +14,51 @@
|
||||
-- limitations under the License.
|
||||
--
|
||||
|
||||
-- select check_version();
|
||||
-- call check_version();
|
||||
|
||||
CREATE OR REPLACE PROCEDURE check_version(INOUT valid_version boolean) LANGUAGE plpgsql AS $BODY$
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_version() RETURNS boolean AS $$
|
||||
DECLARE
|
||||
current_version integer;
|
||||
valid_version boolean;
|
||||
BEGIN
|
||||
RAISE NOTICE 'Check the current installed PostgreSQL version...';
|
||||
SELECT current_setting('server_version_num') INTO current_version;
|
||||
IF current_version < 90600 THEN
|
||||
valid_version := FALSE;
|
||||
ELSE
|
||||
valid_version := TRUE;
|
||||
END IF;
|
||||
IF valid_version = FALSE THEN
|
||||
RAISE NOTICE 'Postgres version should be at least more than 9.6!';
|
||||
ELSE
|
||||
IF current_version > 110000 THEN
|
||||
RAISE NOTICE 'PostgreSQL version is valid!';
|
||||
RAISE NOTICE 'Schema update started...';
|
||||
SELECT true INTO valid_version;
|
||||
ELSE
|
||||
RAISE NOTICE 'Postgres version should be at least more than 10!';
|
||||
END IF;
|
||||
RETURN valid_version;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$BODY$;
|
||||
|
||||
-- select create_new_tenant_ts_kv_table();
|
||||
-- call create_new_ts_kv_table();
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_new_tenant_ts_kv_table() RETURNS VOID AS $$
|
||||
CREATE OR REPLACE PROCEDURE create_new_ts_kv_table() LANGUAGE plpgsql AS $$
|
||||
|
||||
BEGIN
|
||||
ALTER TABLE tenant_ts_kv
|
||||
RENAME TO tenant_ts_kv_old;
|
||||
CREATE TABLE IF NOT EXISTS tenant_ts_kv
|
||||
CREATE TABLE IF NOT EXISTS ts_kv
|
||||
(
|
||||
LIKE tenant_ts_kv_old
|
||||
);
|
||||
ALTER TABLE tenant_ts_kv
|
||||
ALTER COLUMN tenant_id TYPE uuid USING tenant_id::uuid;
|
||||
ALTER TABLE tenant_ts_kv
|
||||
ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid;
|
||||
ALTER TABLE tenant_ts_kv
|
||||
ALTER COLUMN key TYPE integer USING key::integer;
|
||||
ALTER TABLE tenant_ts_kv
|
||||
ADD CONSTRAINT tenant_ts_kv_pkey PRIMARY KEY(tenant_id, entity_id, key, ts);
|
||||
ALTER TABLE ts_kv ALTER COLUMN entity_id TYPE uuid USING entity_id::uuid;
|
||||
ALTER TABLE ts_kv ALTER COLUMN key TYPE integer USING key::integer;
|
||||
ALTER INDEX ts_kv_pkey RENAME TO tenant_ts_kv_pkey_old;
|
||||
ALTER INDEX idx_tenant_ts_kv RENAME TO idx_tenant_ts_kv_old;
|
||||
ALTER INDEX tenant_ts_kv_ts_idx RENAME TO tenant_ts_kv_ts_idx_old;
|
||||
-- PERFORM create_hypertable('tenant_ts_kv', 'ts', chunk_time_interval => 86400000, if_not_exists => true);
|
||||
CREATE INDEX IF NOT EXISTS idx_tenant_ts_kv ON tenant_ts_kv(tenant_id, entity_id, key, ts);
|
||||
ALTER TABLE ts_kv ADD CONSTRAINT ts_kv_pkey PRIMARY KEY(entity_id, key, ts);
|
||||
-- CREATE INDEX IF NOT EXISTS ts_kv_ts_idx ON ts_kv(ts DESC);
|
||||
ALTER TABLE ts_kv DROP COLUMN IF EXISTS tenant_id;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
|
||||
-- select create_ts_kv_latest_table();
|
||||
-- call create_ts_kv_latest_table();
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_ts_kv_latest_table() RETURNS VOID AS $$
|
||||
CREATE OR REPLACE PROCEDURE create_ts_kv_latest_table() LANGUAGE plpgsql AS $$
|
||||
|
||||
BEGIN
|
||||
CREATE TABLE IF NOT EXISTS ts_kv_latest
|
||||
@ -82,12 +73,12 @@ BEGIN
|
||||
CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_id, key)
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
|
||||
-- select create_ts_kv_dictionary_table();
|
||||
-- call create_ts_kv_dictionary_table();
|
||||
|
||||
CREATE OR REPLACE FUNCTION create_ts_kv_dictionary_table() RETURNS VOID AS $$
|
||||
CREATE OR REPLACE PROCEDURE create_ts_kv_dictionary_table() LANGUAGE plpgsql AS $$
|
||||
|
||||
BEGIN
|
||||
CREATE TABLE IF NOT EXISTS ts_kv_dictionary
|
||||
@ -97,12 +88,12 @@ BEGIN
|
||||
CONSTRAINT ts_key_id_pkey PRIMARY KEY (key)
|
||||
);
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select insert_into_dictionary();
|
||||
-- call insert_into_dictionary();
|
||||
|
||||
CREATE OR REPLACE PROCEDURE insert_into_dictionary() LANGUAGE plpgsql AS $$
|
||||
|
||||
CREATE OR REPLACE FUNCTION insert_into_dictionary() RETURNS VOID AS
|
||||
$$
|
||||
DECLARE
|
||||
insert_record RECORD;
|
||||
key_cursor CURSOR FOR SELECT DISTINCT key
|
||||
@ -122,34 +113,28 @@ BEGIN
|
||||
END LOOP;
|
||||
CLOSE key_cursor;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select insert_into_tenant_ts_kv();
|
||||
-- call insert_into_ts_kv();
|
||||
|
||||
CREATE OR REPLACE PROCEDURE insert_into_ts_kv() LANGUAGE plpgsql AS $$
|
||||
|
||||
CREATE OR REPLACE FUNCTION insert_into_tenant_ts_kv() RETURNS void AS
|
||||
$$
|
||||
DECLARE
|
||||
insert_size CONSTANT integer := 10000;
|
||||
insert_counter integer DEFAULT 0;
|
||||
insert_record RECORD;
|
||||
insert_cursor CURSOR FOR SELECT CONCAT(tenant_id_first_part_uuid, '-', tenant_id_second_part_uuid, '-1', tenant_id_third_part_uuid, '-', tenant_id_fourth_part_uuid, '-', tenant_id_fifth_part_uuid)::uuid AS tenant_id,
|
||||
CONCAT(entity_id_first_part_uuid, '-', entity_id_second_part_uuid, '-1', entity_id_third_part_uuid, '-', entity_id_fourth_part_uuid, '-', entity_id_fifth_part_uuid)::uuid AS entity_id,
|
||||
tenant_ts_kv_records.key AS key,
|
||||
tenant_ts_kv_records.ts AS ts,
|
||||
tenant_ts_kv_records.bool_v AS bool_v,
|
||||
tenant_ts_kv_records.str_v AS str_v,
|
||||
tenant_ts_kv_records.long_v AS long_v,
|
||||
tenant_ts_kv_records.dbl_v AS dbl_v
|
||||
FROM (SELECT SUBSTRING(tenant_id, 8, 8) AS tenant_id_first_part_uuid,
|
||||
SUBSTRING(tenant_id, 4, 4) AS tenant_id_second_part_uuid,
|
||||
SUBSTRING(tenant_id, 1, 3) AS tenant_id_third_part_uuid,
|
||||
SUBSTRING(tenant_id, 16, 4) AS tenant_id_fourth_part_uuid,
|
||||
SUBSTRING(tenant_id, 20) AS tenant_id_fifth_part_uuid,
|
||||
SUBSTRING(entity_id, 8, 8) AS entity_id_first_part_uuid,
|
||||
SUBSTRING(entity_id, 4, 4) AS entity_id_second_part_uuid,
|
||||
SUBSTRING(entity_id, 1, 3) AS entity_id_third_part_uuid,
|
||||
SUBSTRING(entity_id, 16, 4) AS entity_id_fourth_part_uuid,
|
||||
SUBSTRING(entity_id, 20) AS entity_id_fifth_part_uuid,
|
||||
insert_cursor CURSOR FOR SELECT CONCAT(entity_id_uuid_first_part, '-', entity_id_uuid_second_part, '-1', entity_id_uuid_third_part, '-', entity_id_uuid_fourth_part, '-', entity_id_uuid_fifth_part)::uuid AS entity_id,
|
||||
new_ts_kv_records.key AS key,
|
||||
new_ts_kv_records.ts AS ts,
|
||||
new_ts_kv_records.bool_v AS bool_v,
|
||||
new_ts_kv_records.str_v AS str_v,
|
||||
new_ts_kv_records.long_v AS long_v,
|
||||
new_ts_kv_records.dbl_v AS dbl_v
|
||||
FROM (SELECT SUBSTRING(entity_id, 8, 8) AS entity_id_uuid_first_part,
|
||||
SUBSTRING(entity_id, 4, 4) AS entity_id_uuid_second_part,
|
||||
SUBSTRING(entity_id, 1, 3) AS entity_id_uuid_third_part,
|
||||
SUBSTRING(entity_id, 16, 4) AS entity_id_uuid_fourth_part,
|
||||
SUBSTRING(entity_id, 20) AS entity_id_uuid_fifth_part,
|
||||
key_id AS key,
|
||||
ts,
|
||||
bool_v,
|
||||
@ -157,31 +142,31 @@ DECLARE
|
||||
long_v,
|
||||
dbl_v
|
||||
FROM tenant_ts_kv_old
|
||||
INNER JOIN ts_kv_dictionary ON (tenant_ts_kv_old.key = ts_kv_dictionary.key)) AS tenant_ts_kv_records;
|
||||
INNER JOIN ts_kv_dictionary ON (tenant_ts_kv_old.key = ts_kv_dictionary.key)) AS new_ts_kv_records;
|
||||
BEGIN
|
||||
OPEN insert_cursor;
|
||||
LOOP
|
||||
insert_counter := insert_counter + 1;
|
||||
FETCH insert_cursor INTO insert_record;
|
||||
IF NOT FOUND THEN
|
||||
RAISE NOTICE '% records have been inserted into the new tenant_ts_kv table!',insert_counter - 1;
|
||||
RAISE NOTICE '% records have been inserted into the new ts_kv table!',insert_counter - 1;
|
||||
EXIT;
|
||||
END IF;
|
||||
INSERT INTO tenant_ts_kv(tenant_id, entity_id, key, ts, bool_v, str_v, long_v, dbl_v)
|
||||
VALUES (insert_record.tenant_id, insert_record.entity_id, insert_record.key, insert_record.ts, insert_record.bool_v, insert_record.str_v,
|
||||
INSERT INTO ts_kv(entity_id, key, ts, bool_v, str_v, long_v, dbl_v)
|
||||
VALUES (insert_record.entity_id, insert_record.key, insert_record.ts, insert_record.bool_v, insert_record.str_v,
|
||||
insert_record.long_v, insert_record.dbl_v);
|
||||
IF MOD(insert_counter, insert_size) = 0 THEN
|
||||
RAISE NOTICE '% records have been inserted into the new tenant_ts_kv table!',insert_counter;
|
||||
RAISE NOTICE '% records have been inserted into the new ts_kv table!',insert_counter;
|
||||
END IF;
|
||||
END LOOP;
|
||||
CLOSE insert_cursor;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
-- select insert_into_ts_kv_latest();
|
||||
-- call insert_into_ts_kv_latest();
|
||||
|
||||
CREATE OR REPLACE PROCEDURE insert_into_ts_kv_latest() LANGUAGE plpgsql AS $$
|
||||
|
||||
CREATE OR REPLACE FUNCTION insert_into_ts_kv_latest() RETURNS void AS
|
||||
$$
|
||||
DECLARE
|
||||
insert_size CONSTANT integer := 10000;
|
||||
insert_counter integer DEFAULT 0;
|
||||
@ -191,7 +176,7 @@ DECLARE
|
||||
latest_records.key AS key,
|
||||
latest_records.entity_id AS entity_id,
|
||||
latest_records.ts AS ts
|
||||
FROM (SELECT DISTINCT key AS key, entity_id AS entity_id, MAX(ts) AS ts FROM tenant_ts_kv GROUP BY key, entity_id) AS latest_records;
|
||||
FROM (SELECT DISTINCT key AS key, entity_id AS entity_id, MAX(ts) AS ts FROM ts_kv GROUP BY key, entity_id) AS latest_records;
|
||||
BEGIN
|
||||
OPEN insert_cursor;
|
||||
LOOP
|
||||
@ -201,7 +186,7 @@ BEGIN
|
||||
RAISE NOTICE '% records have been inserted into the ts_kv_latest table!',insert_counter - 1;
|
||||
EXIT;
|
||||
END IF;
|
||||
SELECT entity_id AS entity_id, key AS key, ts AS ts, bool_v AS bool_v, str_v AS str_v, long_v AS long_v, dbl_v AS dbl_v INTO insert_record FROM tenant_ts_kv WHERE entity_id = latest_record.entity_id AND key = latest_record.key AND ts = latest_record.ts;
|
||||
SELECT entity_id AS entity_id, key AS key, ts AS ts, bool_v AS bool_v, str_v AS str_v, long_v AS long_v, dbl_v AS dbl_v INTO insert_record FROM ts_kv WHERE entity_id = latest_record.entity_id AND key = latest_record.key AND ts = latest_record.ts;
|
||||
INSERT INTO ts_kv_latest(entity_id, key, ts, bool_v, str_v, long_v, dbl_v)
|
||||
VALUES (insert_record.entity_id, insert_record.key, insert_record.ts, insert_record.bool_v, insert_record.str_v, insert_record.long_v, insert_record.dbl_v);
|
||||
IF MOD(insert_counter, insert_size) = 0 THEN
|
||||
@ -210,4 +195,4 @@ BEGIN
|
||||
END LOOP;
|
||||
CLOSE insert_cursor;
|
||||
END;
|
||||
$$ LANGUAGE 'plpgsql';
|
||||
$$;
|
||||
|
||||
@ -22,38 +22,21 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Types;
|
||||
import java.sql.Statement;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractSqlTsDatabaseUpgradeService {
|
||||
|
||||
protected static final String CALL_REGEX = "call ";
|
||||
protected static final String CHECK_VERSION = "check_version()";
|
||||
protected static final String CHECK_VERSION = "check_version(false)";
|
||||
protected static final String CHECK_VERSION_TO_DELETE = "check_version(INOUT valid_version boolean)";
|
||||
protected static final String DROP_TABLE = "DROP TABLE ";
|
||||
protected static final String DROP_FUNCTION_IF_EXISTS = "DROP FUNCTION IF EXISTS ";
|
||||
|
||||
private static final String CALL_CHECK_VERSION = CALL_REGEX + CHECK_VERSION;
|
||||
|
||||
|
||||
private static final String FUNCTION = "function: {}";
|
||||
private static final String DROP_STATEMENT = "drop statement: {}";
|
||||
private static final String QUERY = "query: {}";
|
||||
private static final String SUCCESSFULLY_EXECUTED = "Successfully executed ";
|
||||
private static final String FAILED_TO_EXECUTE = "Failed to execute ";
|
||||
private static final String FAILED_DUE_TO = " due to: {}";
|
||||
|
||||
protected static final String SUCCESSFULLY_EXECUTED_FUNCTION = SUCCESSFULLY_EXECUTED + FUNCTION;
|
||||
protected static final String FAILED_TO_EXECUTE_FUNCTION_DUE_TO = FAILED_TO_EXECUTE + FUNCTION + FAILED_DUE_TO;
|
||||
|
||||
protected static final String SUCCESSFULLY_EXECUTED_DROP_STATEMENT = SUCCESSFULLY_EXECUTED + DROP_STATEMENT;
|
||||
protected static final String FAILED_TO_EXECUTE_DROP_STATEMENT = FAILED_TO_EXECUTE + DROP_STATEMENT + FAILED_DUE_TO;
|
||||
|
||||
protected static final String SUCCESSFULLY_EXECUTED_QUERY = SUCCESSFULLY_EXECUTED + QUERY;
|
||||
protected static final String FAILED_TO_EXECUTE_QUERY = FAILED_TO_EXECUTE + QUERY + FAILED_DUE_TO;
|
||||
protected static final String DROP_PROCEDURE_IF_EXISTS = "DROP PROCEDURE IF EXISTS ";
|
||||
protected static final String DROP_PROCEDURE_CHECK_VERSION = DROP_PROCEDURE_IF_EXISTS + CHECK_VERSION_TO_DELETE;
|
||||
|
||||
@Value("${spring.datasource.url}")
|
||||
protected String dbUrl;
|
||||
@ -78,23 +61,22 @@ public abstract class AbstractSqlTsDatabaseUpgradeService {
|
||||
log.info("Check the current PostgreSQL version...");
|
||||
boolean versionValid = false;
|
||||
try {
|
||||
CallableStatement callableStatement = conn.prepareCall("{? = " + CALL_CHECK_VERSION + " }");
|
||||
callableStatement.registerOutParameter(1, Types.BOOLEAN);
|
||||
callableStatement.execute();
|
||||
versionValid = callableStatement.getBoolean(1);
|
||||
callableStatement.close();
|
||||
Statement statement = conn.createStatement();
|
||||
ResultSet resultSet = statement.executeQuery(CALL_REGEX + CHECK_VERSION);
|
||||
resultSet.next();
|
||||
versionValid = resultSet.getBoolean(1);
|
||||
statement.close();
|
||||
} catch (Exception e) {
|
||||
log.info("Failed to check current PostgreSQL version due to: {}", e.getMessage());
|
||||
}
|
||||
return versionValid;
|
||||
}
|
||||
|
||||
protected void executeFunction(Connection conn, String query) {
|
||||
log.info("{} ... ", query);
|
||||
protected void executeQuery(Connection conn, String query) {
|
||||
try {
|
||||
CallableStatement callableStatement = conn.prepareCall("{" + query + "}");
|
||||
callableStatement.execute();
|
||||
SQLWarning warnings = callableStatement.getWarnings();
|
||||
Statement statement = conn.createStatement();
|
||||
statement.execute(query); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
|
||||
SQLWarning warnings = statement.getWarnings();
|
||||
if (warnings != null) {
|
||||
log.info("{}", warnings.getMessage());
|
||||
SQLWarning nextWarning = warnings.getNextWarning();
|
||||
@ -103,31 +85,10 @@ public abstract class AbstractSqlTsDatabaseUpgradeService {
|
||||
nextWarning = nextWarning.getNextWarning();
|
||||
}
|
||||
}
|
||||
callableStatement.close();
|
||||
log.info(SUCCESSFULLY_EXECUTED_FUNCTION, query.replace(CALL_REGEX, ""));
|
||||
Thread.sleep(2000);
|
||||
} catch (Exception e) {
|
||||
log.info(FAILED_TO_EXECUTE_FUNCTION_DUE_TO, query, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void executeDropStatement(Connection conn, String query) {
|
||||
try {
|
||||
conn.createStatement().execute(query); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
|
||||
log.info(SUCCESSFULLY_EXECUTED_DROP_STATEMENT, query);
|
||||
Thread.sleep(5000);
|
||||
log.info("Successfully executed query: {}", query);
|
||||
} catch (InterruptedException | SQLException e) {
|
||||
log.info(FAILED_TO_EXECUTE_DROP_STATEMENT, query, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected void executeQuery(Connection conn, String query) {
|
||||
try {
|
||||
conn.createStatement().execute(query); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
|
||||
log.info(SUCCESSFULLY_EXECUTED_QUERY, query);
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException | SQLException e) {
|
||||
log.info(FAILED_TO_EXECUTE_QUERY, query, e.getMessage());
|
||||
log.info("Failed to execute query: {} due to: {}", query, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -57,14 +57,13 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
|
||||
private static final String DROP_TABLE_TS_KV_OLD = DROP_TABLE + TS_KV_OLD;
|
||||
private static final String DROP_TABLE_TS_KV_LATEST_OLD = DROP_TABLE + TS_KV_LATEST_OLD;
|
||||
|
||||
private static final String DROP_FUNCTION_CHECK_VERSION = DROP_FUNCTION_IF_EXISTS + CHECK_VERSION;
|
||||
private static final String DROP_FUNCTION_CREATE_PARTITION_TS_KV_TABLE = DROP_FUNCTION_IF_EXISTS + CREATE_PARTITION_TS_KV_TABLE;
|
||||
private static final String DROP_FUNCTION_CREATE_NEW_TS_KV_LATEST_TABLE = DROP_FUNCTION_IF_EXISTS + CREATE_NEW_TS_KV_LATEST_TABLE;
|
||||
private static final String DROP_FUNCTION_CREATE_PARTITIONS = DROP_FUNCTION_IF_EXISTS + CREATE_PARTITIONS;
|
||||
private static final String DROP_FUNCTION_CREATE_TS_KV_DICTIONARY_TABLE = DROP_FUNCTION_IF_EXISTS + CREATE_TS_KV_DICTIONARY_TABLE;
|
||||
private static final String DROP_FUNCTION_INSERT_INTO_DICTIONARY = DROP_FUNCTION_IF_EXISTS + INSERT_INTO_DICTIONARY;
|
||||
private static final String DROP_FUNCTION_INSERT_INTO_TS_KV = DROP_FUNCTION_IF_EXISTS + INSERT_INTO_TS_KV;
|
||||
private static final String DROP_FUNCTION_INSERT_INTO_TS_KV_LATEST = DROP_FUNCTION_IF_EXISTS + INSERT_INTO_TS_KV_LATEST;
|
||||
private static final String DROP_PROCEDURE_CREATE_PARTITION_TS_KV_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_PARTITION_TS_KV_TABLE;
|
||||
private static final String DROP_PROCEDURE_CREATE_NEW_TS_KV_LATEST_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_NEW_TS_KV_LATEST_TABLE;
|
||||
private static final String DROP_PROCEDURE_CREATE_PARTITIONS = DROP_PROCEDURE_IF_EXISTS + CREATE_PARTITIONS;
|
||||
private static final String DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_TS_KV_DICTIONARY_TABLE;
|
||||
private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY;
|
||||
private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV;
|
||||
private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST;
|
||||
|
||||
@Override
|
||||
public void upgradeDatabase(String fromVersion) throws Exception {
|
||||
@ -76,30 +75,30 @@ public class PsqlTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgradeSe
|
||||
loadSql(conn);
|
||||
boolean versionValid = checkVersion(conn);
|
||||
if (!versionValid) {
|
||||
log.info("PostgreSQL version should be at least more than 10!");
|
||||
log.info("PostgreSQL version should be at least more than 11!");
|
||||
log.info("Please upgrade your PostgreSQL and restart the script!");
|
||||
} else {
|
||||
log.info("PostgreSQL version is valid!");
|
||||
log.info("Updating schema ...");
|
||||
executeFunction(conn, CALL_CREATE_PARTITION_TS_KV_TABLE);
|
||||
executeFunction(conn, CALL_CREATE_PARTITIONS);
|
||||
executeFunction(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeFunction(conn, CALL_INSERT_INTO_DICTIONARY);
|
||||
executeFunction(conn, CALL_INSERT_INTO_TS_KV);
|
||||
executeFunction(conn, CALL_CREATE_NEW_TS_KV_LATEST_TABLE);
|
||||
executeFunction(conn, CALL_INSERT_INTO_TS_KV_LATEST);
|
||||
executeQuery(conn, CALL_CREATE_PARTITION_TS_KV_TABLE);
|
||||
executeQuery(conn, CALL_CREATE_PARTITIONS);
|
||||
executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeQuery(conn, CALL_INSERT_INTO_DICTIONARY);
|
||||
executeQuery(conn, CALL_INSERT_INTO_TS_KV);
|
||||
executeQuery(conn, CALL_CREATE_NEW_TS_KV_LATEST_TABLE);
|
||||
executeQuery(conn, CALL_INSERT_INTO_TS_KV_LATEST);
|
||||
|
||||
executeDropStatement(conn, DROP_TABLE_TS_KV_OLD);
|
||||
executeDropStatement(conn, DROP_TABLE_TS_KV_LATEST_OLD);
|
||||
executeQuery(conn, DROP_TABLE_TS_KV_OLD);
|
||||
executeQuery(conn, DROP_TABLE_TS_KV_LATEST_OLD);
|
||||
|
||||
executeDropStatement(conn, DROP_FUNCTION_CHECK_VERSION);
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_PARTITION_TS_KV_TABLE);
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_PARTITIONS);
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeDropStatement(conn, DROP_FUNCTION_INSERT_INTO_DICTIONARY);
|
||||
executeDropStatement(conn, DROP_FUNCTION_INSERT_INTO_TS_KV);
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_NEW_TS_KV_LATEST_TABLE);
|
||||
executeDropStatement(conn, DROP_FUNCTION_INSERT_INTO_TS_KV_LATEST);
|
||||
executeQuery(conn, DROP_PROCEDURE_CHECK_VERSION);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_PARTITION_TS_KV_TABLE);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_PARTITIONS);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_DICTIONARY);
|
||||
executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_NEW_TS_KV_LATEST_TABLE);
|
||||
executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST);
|
||||
|
||||
executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN json_v json;");
|
||||
executeQuery(conn, "ALTER TABLE ts_kv_latest ADD COLUMN json_v json;");
|
||||
|
||||
@ -45,13 +45,13 @@ public class TimescaleTsDatabaseSchemaService extends SqlAbstractDatabaseSchemaS
|
||||
private long chunkTimeInterval;
|
||||
|
||||
public TimescaleTsDatabaseSchemaService() {
|
||||
super("schema-timescale.sql", "schema-timescale-idx.sql");
|
||||
super("schema-timescale.sql", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createDatabaseSchema() throws Exception {
|
||||
super.createDatabaseSchema();
|
||||
executeQuery("SELECT create_hypertable('tenant_ts_kv', 'ts', chunk_time_interval => " + chunkTimeInterval + ", if_not_exists => true);");
|
||||
executeQuery("SELECT create_hypertable('ts_kv', 'ts', chunk_time_interval => " + chunkTimeInterval + ", if_not_exists => true);");
|
||||
}
|
||||
|
||||
private void executeQuery(String query) {
|
||||
|
||||
@ -43,27 +43,27 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr
|
||||
private static final String TENANT_TS_KV_OLD_TABLE = "tenant_ts_kv_old;";
|
||||
|
||||
private static final String CREATE_TS_KV_LATEST_TABLE = "create_ts_kv_latest_table()";
|
||||
private static final String CREATE_NEW_TENANT_TS_KV_TABLE = "create_new_tenant_ts_kv_table()";
|
||||
private static final String CREATE_NEW_TS_KV_TABLE = "create_new_ts_kv_table()";
|
||||
private static final String CREATE_TS_KV_DICTIONARY_TABLE = "create_ts_kv_dictionary_table()";
|
||||
private static final String INSERT_INTO_DICTIONARY = "insert_into_dictionary()";
|
||||
private static final String INSERT_INTO_TENANT_TS_KV = "insert_into_tenant_ts_kv()";
|
||||
private static final String INSERT_INTO_TS_KV = "insert_into_ts_kv()";
|
||||
private static final String INSERT_INTO_TS_KV_LATEST = "insert_into_ts_kv_latest()";
|
||||
|
||||
private static final String CALL_CREATE_TS_KV_LATEST_TABLE = CALL_REGEX + CREATE_TS_KV_LATEST_TABLE;
|
||||
private static final String CALL_CREATE_NEW_TENANT_TS_KV_TABLE = CALL_REGEX + CREATE_NEW_TENANT_TS_KV_TABLE;
|
||||
private static final String CALL_CREATE_NEW_TENANT_TS_KV_TABLE = CALL_REGEX + CREATE_NEW_TS_KV_TABLE;
|
||||
private static final String CALL_CREATE_TS_KV_DICTIONARY_TABLE = CALL_REGEX + CREATE_TS_KV_DICTIONARY_TABLE;
|
||||
private static final String CALL_INSERT_INTO_DICTIONARY = CALL_REGEX + INSERT_INTO_DICTIONARY;
|
||||
private static final String CALL_INSERT_INTO_TS_KV = CALL_REGEX + INSERT_INTO_TENANT_TS_KV;
|
||||
private static final String CALL_INSERT_INTO_TS_KV = CALL_REGEX + INSERT_INTO_TS_KV;
|
||||
private static final String CALL_INSERT_INTO_TS_KV_LATEST = CALL_REGEX + INSERT_INTO_TS_KV_LATEST;
|
||||
|
||||
private static final String DROP_OLD_TENANT_TS_KV_TABLE = DROP_TABLE + TENANT_TS_KV_OLD_TABLE;
|
||||
|
||||
private static final String DROP_FUNCTION_CREATE_TS_KV_LATEST_TABLE = DROP_FUNCTION_IF_EXISTS + CREATE_TS_KV_LATEST_TABLE;
|
||||
private static final String DROP_FUNCTION_CREATE_TENANT_TS_KV_TABLE_COPY = DROP_FUNCTION_IF_EXISTS + CREATE_NEW_TENANT_TS_KV_TABLE;
|
||||
private static final String DROP_FUNCTION_CREATE_TS_KV_DICTIONARY_TABLE = DROP_FUNCTION_IF_EXISTS + CREATE_TS_KV_DICTIONARY_TABLE;
|
||||
private static final String DROP_FUNCTION_INSERT_INTO_DICTIONARY = DROP_FUNCTION_IF_EXISTS + INSERT_INTO_DICTIONARY;
|
||||
private static final String DROP_FUNCTION_INSERT_INTO_TENANT_TS_KV = DROP_FUNCTION_IF_EXISTS + INSERT_INTO_TENANT_TS_KV;
|
||||
private static final String DROP_FUNCTION_INSERT_INTO_TS_KV_LATEST = DROP_FUNCTION_IF_EXISTS + INSERT_INTO_TS_KV_LATEST;
|
||||
private static final String DROP_PROCEDURE_CREATE_TS_KV_LATEST_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_TS_KV_LATEST_TABLE;
|
||||
private static final String DROP_PROCEDURE_CREATE_TENANT_TS_KV_TABLE_COPY = DROP_PROCEDURE_IF_EXISTS + CREATE_NEW_TS_KV_TABLE;
|
||||
private static final String DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE = DROP_PROCEDURE_IF_EXISTS + CREATE_TS_KV_DICTIONARY_TABLE;
|
||||
private static final String DROP_PROCEDURE_INSERT_INTO_DICTIONARY = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_DICTIONARY;
|
||||
private static final String DROP_PROCEDURE_INSERT_INTO_TENANT_TS_KV = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV;
|
||||
private static final String DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST = DROP_PROCEDURE_IF_EXISTS + INSERT_INTO_TS_KV_LATEST;
|
||||
|
||||
@Autowired
|
||||
private InstallScripts installScripts;
|
||||
@ -78,33 +78,31 @@ public class TimescaleTsDatabaseUpgradeService extends AbstractSqlTsDatabaseUpgr
|
||||
loadSql(conn);
|
||||
boolean versionValid = checkVersion(conn);
|
||||
if (!versionValid) {
|
||||
log.info("PostgreSQL version should be at least more than 9.6!");
|
||||
log.info("PostgreSQL version should be at least more than 11!");
|
||||
log.info("Please upgrade your PostgreSQL and restart the script!");
|
||||
} else {
|
||||
log.info("PostgreSQL version is valid!");
|
||||
log.info("Updating schema ...");
|
||||
executeFunction(conn, CALL_CREATE_TS_KV_LATEST_TABLE);
|
||||
executeFunction(conn, CALL_CREATE_NEW_TENANT_TS_KV_TABLE);
|
||||
executeQuery(conn, CALL_CREATE_TS_KV_LATEST_TABLE);
|
||||
executeQuery(conn, CALL_CREATE_NEW_TENANT_TS_KV_TABLE);
|
||||
|
||||
executeQuery(conn, "SELECT create_hypertable('tenant_ts_kv', 'ts', chunk_time_interval => " + chunkTimeInterval + ", if_not_exists => true);");
|
||||
executeQuery(conn, "SELECT create_hypertable('ts_kv', 'ts', chunk_time_interval => " + chunkTimeInterval + ", if_not_exists => true);");
|
||||
|
||||
executeFunction(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeFunction(conn, CALL_INSERT_INTO_DICTIONARY);
|
||||
executeFunction(conn, CALL_INSERT_INTO_TS_KV);
|
||||
executeFunction(conn, CALL_INSERT_INTO_TS_KV_LATEST);
|
||||
executeQuery(conn, CALL_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeQuery(conn, CALL_INSERT_INTO_DICTIONARY);
|
||||
executeQuery(conn, CALL_INSERT_INTO_TS_KV);
|
||||
executeQuery(conn, CALL_INSERT_INTO_TS_KV_LATEST);
|
||||
|
||||
//executeQuery(conn, "SELECT set_chunk_time_interval('tenant_ts_kv', " + chunkTimeInterval +");");
|
||||
executeQuery(conn, DROP_OLD_TENANT_TS_KV_TABLE);
|
||||
|
||||
executeDropStatement(conn, DROP_OLD_TENANT_TS_KV_TABLE);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_TS_KV_LATEST_TABLE);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_TENANT_TS_KV_TABLE_COPY);
|
||||
executeQuery(conn, DROP_PROCEDURE_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_DICTIONARY);
|
||||
executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TENANT_TS_KV);
|
||||
executeQuery(conn, DROP_PROCEDURE_INSERT_INTO_TS_KV_LATEST);
|
||||
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_TS_KV_LATEST_TABLE);
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_TENANT_TS_KV_TABLE_COPY);
|
||||
executeDropStatement(conn, DROP_FUNCTION_CREATE_TS_KV_DICTIONARY_TABLE);
|
||||
executeDropStatement(conn, DROP_FUNCTION_INSERT_INTO_DICTIONARY);
|
||||
executeDropStatement(conn, DROP_FUNCTION_INSERT_INTO_TENANT_TS_KV);
|
||||
executeDropStatement(conn, DROP_FUNCTION_INSERT_INTO_TS_KV_LATEST);
|
||||
|
||||
executeQuery(conn, "ALTER TABLE tenant_ts_kv ADD COLUMN json_v json;");
|
||||
executeQuery(conn, "ALTER TABLE ts_kv ADD COLUMN json_v json;");
|
||||
executeQuery(conn, "ALTER TABLE ts_kv_latest ADD COLUMN json_v json;");
|
||||
|
||||
log.info("schema timeseries updated!");
|
||||
|
||||
@ -36,6 +36,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.BOOLEAN_VALUE_COLU
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.DOUBLE_VALUE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.ENTITY_ID_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.JSON_VALUE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.LONG_VALUE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.STRING_VALUE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.TS_COLUMN;
|
||||
@ -53,6 +54,10 @@ public abstract class AbstractTsKvEntity implements ToData<TsKvEntry> {
|
||||
@Column(name = ENTITY_ID_COLUMN, columnDefinition = "uuid")
|
||||
protected UUID entityId;
|
||||
|
||||
@Id
|
||||
@Column(name = KEY_COLUMN)
|
||||
protected int key;
|
||||
|
||||
@Id
|
||||
@Column(name = TS_COLUMN)
|
||||
protected Long ts;
|
||||
|
||||
@ -69,10 +69,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN;
|
||||
})
|
||||
public final class TsKvLatestEntity extends AbstractTsKvEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = KEY_COLUMN)
|
||||
private int key;
|
||||
|
||||
@Override
|
||||
public boolean isNotEmpty() {
|
||||
return strValue != null || longValue != null || doubleValue != null || booleanValue != null || jsonValue != null;
|
||||
|
||||
@ -31,7 +31,6 @@ public class TimescaleTsKvCompositeKey implements Serializable {
|
||||
@Transient
|
||||
private static final long serialVersionUID = -4089175869616037523L;
|
||||
|
||||
private UUID tenantId;
|
||||
private UUID entityId;
|
||||
private int key;
|
||||
private long ts;
|
||||
|
||||
@ -18,25 +18,18 @@ package org.thingsboard.server.dao.model.sqlts.timescale.ts;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||
import org.thingsboard.server.dao.model.ToData;
|
||||
import org.thingsboard.server.dao.model.sql.AbstractTsKvEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ColumnResult;
|
||||
import javax.persistence.ConstructorResult;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.NamedNativeQueries;
|
||||
import javax.persistence.NamedNativeQuery;
|
||||
import javax.persistence.SqlResultSetMapping;
|
||||
import javax.persistence.SqlResultSetMappings;
|
||||
import javax.persistence.Table;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.TENANT_ID_COLUMN;
|
||||
import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.FIND_AVG;
|
||||
import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.FIND_AVG_QUERY;
|
||||
import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.FIND_COUNT;
|
||||
@ -52,7 +45,7 @@ import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.F
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Entity
|
||||
@Table(name = "tenant_ts_kv")
|
||||
@Table(name = "ts_kv")
|
||||
@IdClass(TimescaleTsKvCompositeKey.class)
|
||||
@SqlResultSetMappings({
|
||||
@SqlResultSetMapping(
|
||||
@ -116,15 +109,7 @@ import static org.thingsboard.server.dao.sqlts.timescale.AggregationRepository.F
|
||||
resultSetMapping = "timescaleCountMapping"
|
||||
)
|
||||
})
|
||||
public final class TimescaleTsKvEntity extends AbstractTsKvEntity implements ToData<TsKvEntry> {
|
||||
|
||||
@Id
|
||||
@Column(name = TENANT_ID_COLUMN, columnDefinition = "uuid")
|
||||
private UUID tenantId;
|
||||
|
||||
@Id
|
||||
@Column(name = KEY_COLUMN)
|
||||
private int key;
|
||||
public final class TimescaleTsKvEntity extends AbstractTsKvEntity {
|
||||
|
||||
public TimescaleTsKvEntity() {
|
||||
}
|
||||
|
||||
@ -32,10 +32,6 @@ import static org.thingsboard.server.dao.model.ModelConstants.KEY_COLUMN;
|
||||
@IdClass(TsKvCompositeKey.class)
|
||||
public final class TsKvEntity extends AbstractTsKvEntity {
|
||||
|
||||
@Id
|
||||
@Column(name = KEY_COLUMN)
|
||||
private int key;
|
||||
|
||||
public TsKvEntity() {
|
||||
}
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> removeLatest(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
||||
return getRemoveLatestFuture(tenantId, entityId, query);
|
||||
return getRemoveLatestFuture(entityId, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -125,9 +125,9 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsync(TenantId tenantId, EntityId entityId, ReadTsKvQuery query) {
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsync(EntityId entityId, ReadTsKvQuery query) {
|
||||
if (query.getAggregation() == Aggregation.NONE) {
|
||||
return findAllAsyncWithLimit(tenantId, entityId, query);
|
||||
return findAllAsyncWithLimit(entityId, query);
|
||||
} else {
|
||||
long stepTs = query.getStartTs();
|
||||
List<ListenableFuture<Optional<TsKvEntry>>> futures = new ArrayList<>();
|
||||
@ -135,7 +135,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
long startTs = stepTs;
|
||||
long endTs = stepTs + query.getInterval();
|
||||
long ts = startTs + (endTs - startTs) / 2;
|
||||
futures.add(findAndAggregateAsync(tenantId, entityId, query.getKey(), startTs, endTs, ts, query.getAggregation()));
|
||||
futures.add(findAndAggregateAsync(entityId, query.getKey(), startTs, endTs, ts, query.getAggregation()));
|
||||
stepTs = endTs;
|
||||
}
|
||||
return getTskvEntriesFuture(Futures.allAsList(futures));
|
||||
@ -143,7 +143,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(TenantId tenantId, EntityId entityId, ReadTsKvQuery query) {
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(EntityId entityId, ReadTsKvQuery query) {
|
||||
Integer keyId = getOrSaveKeyId(query.getKey());
|
||||
List<TsKvEntity> tsKvEntities = tsKvRepository.findAllWithLimit(
|
||||
entityId.getId(),
|
||||
@ -157,9 +157,9 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
return Futures.immediateFuture(DaoUtil.convertDataList(tsKvEntities));
|
||||
}
|
||||
|
||||
protected ListenableFuture<Optional<TsKvEntry>> findAndAggregateAsync(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) {
|
||||
private ListenableFuture<Optional<TsKvEntry>> findAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long ts, Aggregation aggregation) {
|
||||
List<CompletableFuture<TsKvEntity>> entitiesFutures = new ArrayList<>();
|
||||
switchAggregation(tenantId, entityId, key, startTs, endTs, aggregation, entitiesFutures);
|
||||
switchAggregation(entityId, key, startTs, endTs, aggregation, entitiesFutures);
|
||||
return Futures.transform(setFutures(entitiesFutures), entity -> {
|
||||
if (entity != null && entity.isNotEmpty()) {
|
||||
entity.setEntityId(entityId.getId());
|
||||
@ -172,29 +172,29 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
protected void switchAggregation(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, Aggregation aggregation, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
protected void switchAggregation(EntityId entityId, String key, long startTs, long endTs, Aggregation aggregation, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
switch (aggregation) {
|
||||
case AVG:
|
||||
findAvg(tenantId, entityId, key, startTs, endTs, entitiesFutures);
|
||||
findAvg(entityId, key, startTs, endTs, entitiesFutures);
|
||||
break;
|
||||
case MAX:
|
||||
findMax(tenantId, entityId, key, startTs, endTs, entitiesFutures);
|
||||
findMax(entityId, key, startTs, endTs, entitiesFutures);
|
||||
break;
|
||||
case MIN:
|
||||
findMin(tenantId, entityId, key, startTs, endTs, entitiesFutures);
|
||||
findMin(entityId, key, startTs, endTs, entitiesFutures);
|
||||
break;
|
||||
case SUM:
|
||||
findSum(tenantId, entityId, key, startTs, endTs, entitiesFutures);
|
||||
findSum(entityId, key, startTs, endTs, entitiesFutures);
|
||||
break;
|
||||
case COUNT:
|
||||
findCount(tenantId, entityId, key, startTs, endTs, entitiesFutures);
|
||||
findCount(entityId, key, startTs, endTs, entitiesFutures);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Not supported aggregation type: " + aggregation);
|
||||
}
|
||||
}
|
||||
|
||||
protected void findCount(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
protected void findCount(EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
entitiesFutures.add(tsKvRepository.findCount(
|
||||
entityId.getId(),
|
||||
@ -203,7 +203,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
endTs));
|
||||
}
|
||||
|
||||
protected void findSum(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
protected void findSum(EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
entitiesFutures.add(tsKvRepository.findSum(
|
||||
entityId.getId(),
|
||||
@ -212,7 +212,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
endTs));
|
||||
}
|
||||
|
||||
protected void findMin(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
protected void findMin(EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
entitiesFutures.add(tsKvRepository.findStringMin(
|
||||
entityId.getId(),
|
||||
@ -226,7 +226,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
endTs));
|
||||
}
|
||||
|
||||
protected void findMax(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
protected void findMax(EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
entitiesFutures.add(tsKvRepository.findStringMax(
|
||||
entityId.getId(),
|
||||
@ -240,7 +240,7 @@ public abstract class AbstractChunkedAggregationTimeseriesDao extends AbstractSq
|
||||
endTs));
|
||||
}
|
||||
|
||||
protected void findAvg(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
protected void findAvg(EntityId entityId, String key, long startTs, long endTs, List<CompletableFuture<TsKvEntity>> entitiesFutures) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
entitiesFutures.add(tsKvRepository.findAvg(
|
||||
entityId.getId(),
|
||||
|
||||
@ -127,7 +127,7 @@ public abstract class AbstractSqlTimeseriesDao extends JpaAbstractDaoListeningEx
|
||||
protected ListenableFuture<List<TsKvEntry>> processFindAllAsync(TenantId tenantId, EntityId entityId, List<ReadTsKvQuery> queries) {
|
||||
List<ListenableFuture<List<TsKvEntry>>> futures = queries
|
||||
.stream()
|
||||
.map(query -> findAllAsync(tenantId, entityId, query))
|
||||
.map(query -> findAllAsync(entityId, query))
|
||||
.collect(Collectors.toList());
|
||||
return Futures.transform(Futures.allAsList(futures), new Function<List<List<TsKvEntry>>, List<TsKvEntry>>() {
|
||||
@Nullable
|
||||
@ -144,9 +144,9 @@ public abstract class AbstractSqlTimeseriesDao extends JpaAbstractDaoListeningEx
|
||||
}, service);
|
||||
}
|
||||
|
||||
protected abstract ListenableFuture<List<TsKvEntry>> findAllAsync(TenantId tenantId, EntityId entityId, ReadTsKvQuery query);
|
||||
protected abstract ListenableFuture<List<TsKvEntry>> findAllAsync(EntityId entityId, ReadTsKvQuery query);
|
||||
|
||||
protected abstract ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(TenantId tenantId, EntityId entityId, ReadTsKvQuery query);
|
||||
protected abstract ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(EntityId entityId, ReadTsKvQuery query);
|
||||
|
||||
protected ListenableFuture<List<TsKvEntry>> getTskvEntriesFuture(ListenableFuture<List<Optional<TsKvEntry>>> future) {
|
||||
return Futures.transform(future, new Function<List<Optional<TsKvEntry>>, List<TsKvEntry>>() {
|
||||
@ -164,12 +164,12 @@ public abstract class AbstractSqlTimeseriesDao extends JpaAbstractDaoListeningEx
|
||||
}, service);
|
||||
}
|
||||
|
||||
protected ListenableFuture<List<TsKvEntry>> findNewLatestEntryFuture(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
||||
protected ListenableFuture<List<TsKvEntry>> findNewLatestEntryFuture(EntityId entityId, DeleteTsKvQuery query) {
|
||||
long startTs = 0;
|
||||
long endTs = query.getStartTs() - 1;
|
||||
ReadTsKvQuery findNewLatestQuery = new BaseReadTsKvQuery(query.getKey(), startTs, endTs, endTs - startTs, 1,
|
||||
Aggregation.NONE, DESC_ORDER);
|
||||
return findAllAsync(tenantId, entityId, findNewLatestQuery);
|
||||
return findAllAsync(entityId, findNewLatestQuery);
|
||||
}
|
||||
|
||||
protected ListenableFuture<TsKvEntry> getFindLatestFuture(EntityId entityId, String key) {
|
||||
@ -189,7 +189,7 @@ public abstract class AbstractSqlTimeseriesDao extends JpaAbstractDaoListeningEx
|
||||
return Futures.immediateFuture(result);
|
||||
}
|
||||
|
||||
protected ListenableFuture<Void> getRemoveLatestFuture(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
||||
protected ListenableFuture<Void> getRemoveLatestFuture(EntityId entityId, DeleteTsKvQuery query) {
|
||||
ListenableFuture<TsKvEntry> latestFuture = getFindLatestFuture(entityId, query.getKey());
|
||||
|
||||
ListenableFuture<Boolean> booleanFuture = Futures.transform(latestFuture, tsKvEntry -> {
|
||||
@ -217,7 +217,7 @@ public abstract class AbstractSqlTimeseriesDao extends JpaAbstractDaoListeningEx
|
||||
if (query.getRewriteLatestIfDeleted()) {
|
||||
ListenableFuture<Void> savedLatestFuture = Futures.transformAsync(booleanFuture, isRemove -> {
|
||||
if (isRemove) {
|
||||
return getNewLatestEntryFuture(tenantId, entityId, query);
|
||||
return getNewLatestEntryFuture(entityId, query);
|
||||
}
|
||||
return Futures.immediateFuture(null);
|
||||
}, service);
|
||||
@ -296,8 +296,8 @@ public abstract class AbstractSqlTimeseriesDao extends JpaAbstractDaoListeningEx
|
||||
return keyId;
|
||||
}
|
||||
|
||||
private ListenableFuture<Void> getNewLatestEntryFuture(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
||||
ListenableFuture<List<TsKvEntry>> future = findNewLatestEntryFuture(tenantId, entityId, query);
|
||||
private ListenableFuture<Void> getNewLatestEntryFuture(EntityId entityId, DeleteTsKvQuery query) {
|
||||
ListenableFuture<List<TsKvEntry>> future = findNewLatestEntryFuture(entityId, query);
|
||||
return Futures.transformAsync(future, entryList -> {
|
||||
if (entryList.size() == 1) {
|
||||
return getSaveLatestFuture(entityId, entryList.get(0));
|
||||
|
||||
@ -37,8 +37,8 @@ import java.util.List;
|
||||
public class TimescaleInsertTsRepository extends AbstractInsertRepository implements InsertTsRepository<TimescaleTsKvEntity> {
|
||||
|
||||
private static final String INSERT_OR_UPDATE =
|
||||
"INSERT INTO tenant_ts_kv (tenant_id, entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) VALUES(?, ?, ?, ?, ?, ?, ?, ?, cast(? AS json)) " +
|
||||
"ON CONFLICT (tenant_id, entity_id, key, ts) DO UPDATE SET bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json);";
|
||||
"INSERT INTO ts_kv (entity_id, key, ts, bool_v, str_v, long_v, dbl_v, json_v) VALUES(?, ?, ?, ?, ?, ?, ?, cast(? AS json)) " +
|
||||
"ON CONFLICT (entity_id, key, ts) DO UPDATE SET bool_v = ?, str_v = ?, long_v = ?, dbl_v = ?, json_v = cast(? AS json);";
|
||||
|
||||
@Override
|
||||
public void saveOrUpdate(List<EntityContainer<TimescaleTsKvEntity>> entities) {
|
||||
@ -46,41 +46,40 @@ public class TimescaleInsertTsRepository extends AbstractInsertRepository implem
|
||||
@Override
|
||||
public void setValues(PreparedStatement ps, int i) throws SQLException {
|
||||
TimescaleTsKvEntity tsKvEntity = entities.get(i).getEntity();
|
||||
ps.setObject(1, tsKvEntity.getTenantId());
|
||||
ps.setObject(2, tsKvEntity.getEntityId());
|
||||
ps.setInt(3, tsKvEntity.getKey());
|
||||
ps.setLong(4, tsKvEntity.getTs());
|
||||
ps.setObject(1, tsKvEntity.getEntityId());
|
||||
ps.setInt(2, tsKvEntity.getKey());
|
||||
ps.setLong(3, tsKvEntity.getTs());
|
||||
|
||||
if (tsKvEntity.getBooleanValue() != null) {
|
||||
ps.setBoolean(5, tsKvEntity.getBooleanValue());
|
||||
ps.setBoolean(10, tsKvEntity.getBooleanValue());
|
||||
ps.setBoolean(4, tsKvEntity.getBooleanValue());
|
||||
ps.setBoolean(9, tsKvEntity.getBooleanValue());
|
||||
} else {
|
||||
ps.setNull(5, Types.BOOLEAN);
|
||||
ps.setNull(10, Types.BOOLEAN);
|
||||
ps.setNull(4, Types.BOOLEAN);
|
||||
ps.setNull(9, Types.BOOLEAN);
|
||||
}
|
||||
|
||||
ps.setString(6, replaceNullChars(tsKvEntity.getStrValue()));
|
||||
ps.setString(11, replaceNullChars(tsKvEntity.getStrValue()));
|
||||
ps.setString(5, replaceNullChars(tsKvEntity.getStrValue()));
|
||||
ps.setString(10, replaceNullChars(tsKvEntity.getStrValue()));
|
||||
|
||||
|
||||
if (tsKvEntity.getLongValue() != null) {
|
||||
ps.setLong(7, tsKvEntity.getLongValue());
|
||||
ps.setLong(12, tsKvEntity.getLongValue());
|
||||
ps.setLong(6, tsKvEntity.getLongValue());
|
||||
ps.setLong(11, tsKvEntity.getLongValue());
|
||||
} else {
|
||||
ps.setNull(7, Types.BIGINT);
|
||||
ps.setNull(12, Types.BIGINT);
|
||||
ps.setNull(6, Types.BIGINT);
|
||||
ps.setNull(11, Types.BIGINT);
|
||||
}
|
||||
|
||||
if (tsKvEntity.getDoubleValue() != null) {
|
||||
ps.setDouble(8, tsKvEntity.getDoubleValue());
|
||||
ps.setDouble(13, tsKvEntity.getDoubleValue());
|
||||
ps.setDouble(7, tsKvEntity.getDoubleValue());
|
||||
ps.setDouble(12, tsKvEntity.getDoubleValue());
|
||||
} else {
|
||||
ps.setNull(8, Types.DOUBLE);
|
||||
ps.setNull(13, Types.DOUBLE);
|
||||
ps.setNull(7, Types.DOUBLE);
|
||||
ps.setNull(12, Types.DOUBLE);
|
||||
}
|
||||
|
||||
ps.setString(9, replaceNullChars(tsKvEntity.getJsonValue()));
|
||||
ps.setString(14, replaceNullChars(tsKvEntity.getJsonValue()));
|
||||
ps.setString(8, replaceNullChars(tsKvEntity.getJsonValue()));
|
||||
ps.setString(13, replaceNullChars(tsKvEntity.getJsonValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -36,7 +36,7 @@ public class AggregationRepository {
|
||||
public static final String FIND_SUM = "findSum";
|
||||
public static final String FIND_COUNT = "findCount";
|
||||
|
||||
public static final String FROM_WHERE_CLAUSE = "FROM tenant_ts_kv tskv WHERE tskv.tenant_id = cast(:tenantId AS uuid) AND tskv.entity_id = cast(:entityId AS uuid) AND tskv.key= cast(:entityKey AS int) AND tskv.ts > :startTs AND tskv.ts <= :endTs GROUP BY tskv.tenant_id, tskv.entity_id, tskv.key, tsBucket ORDER BY tskv.tenant_id, tskv.entity_id, tskv.key, tsBucket";
|
||||
public static final String FROM_WHERE_CLAUSE = "FROM ts_kv tskv WHERE tskv.entity_id = cast(:entityId AS uuid) AND tskv.key= cast(:entityKey AS int) AND tskv.ts > :startTs AND tskv.ts <= :endTs GROUP BY tskv.entity_id, tskv.key, tsBucket ORDER BY tskv.entity_id, tskv.key, tsBucket";
|
||||
|
||||
public static final String FIND_AVG_QUERY = "SELECT time_bucket(:timeBucket, tskv.ts) AS tsBucket, :timeBucket AS interval, SUM(COALESCE(tskv.long_v, 0)) AS longValue, SUM(COALESCE(tskv.dbl_v, 0.0)) AS doubleValue, SUM(CASE WHEN tskv.long_v IS NULL THEN 0 ELSE 1 END) AS longCountValue, SUM(CASE WHEN tskv.dbl_v IS NULL THEN 0 ELSE 1 END) AS doubleCountValue, null AS strValue, 'AVG' AS aggType ";
|
||||
|
||||
@ -52,43 +52,42 @@ public class AggregationRepository {
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findAvg(UUID tenantId, UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findAvg(UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(tenantId, entityId, entityKey, timeBucket, startTs, endTs, FIND_AVG);
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(entityId, entityKey, timeBucket, startTs, endTs, FIND_AVG);
|
||||
return CompletableFuture.supplyAsync(() -> resultList);
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findMax(UUID tenantId, UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findMax(UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(tenantId, entityId, entityKey, timeBucket, startTs, endTs, FIND_MAX);
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(entityId, entityKey, timeBucket, startTs, endTs, FIND_MAX);
|
||||
return CompletableFuture.supplyAsync(() -> resultList);
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findMin(UUID tenantId, UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findMin(UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(tenantId, entityId, entityKey, timeBucket, startTs, endTs, FIND_MIN);
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(entityId, entityKey, timeBucket, startTs, endTs, FIND_MIN);
|
||||
return CompletableFuture.supplyAsync(() -> resultList);
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findSum(UUID tenantId, UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findSum(UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(tenantId, entityId, entityKey, timeBucket, startTs, endTs, FIND_SUM);
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(entityId, entityKey, timeBucket, startTs, endTs, FIND_SUM);
|
||||
return CompletableFuture.supplyAsync(() -> resultList);
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findCount(UUID tenantId, UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
public CompletableFuture<List<TimescaleTsKvEntity>> findCount(UUID entityId, int entityKey, long timeBucket, long startTs, long endTs) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(tenantId, entityId, entityKey, timeBucket, startTs, endTs, FIND_COUNT);
|
||||
List<TimescaleTsKvEntity> resultList = getResultList(entityId, entityKey, timeBucket, startTs, endTs, FIND_COUNT);
|
||||
return CompletableFuture.supplyAsync(() -> resultList);
|
||||
}
|
||||
|
||||
private List getResultList(UUID tenantId, UUID entityId, int entityKey, long timeBucket, long startTs, long endTs, String query) {
|
||||
private List getResultList(UUID entityId, int entityKey, long timeBucket, long startTs, long endTs, String query) {
|
||||
return entityManager.createNamedQuery(query)
|
||||
.setParameter("tenantId", tenantId)
|
||||
.setParameter("entityId", entityId)
|
||||
.setParameter("entityKey", entityKey)
|
||||
.setParameter("timeBucket", timeBucket)
|
||||
|
||||
@ -88,24 +88,23 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsync(TenantId tenantId, EntityId entityId, ReadTsKvQuery query) {
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsync(EntityId entityId, ReadTsKvQuery query) {
|
||||
if (query.getAggregation() == Aggregation.NONE) {
|
||||
return findAllAsyncWithLimit(tenantId, entityId, query);
|
||||
return findAllAsyncWithLimit(entityId, query);
|
||||
} else {
|
||||
long startTs = query.getStartTs();
|
||||
long endTs = query.getEndTs();
|
||||
long timeBucket = query.getInterval();
|
||||
ListenableFuture<List<Optional<TsKvEntry>>> future = findAllAndAggregateAsync(tenantId, entityId, query.getKey(), startTs, endTs, timeBucket, query.getAggregation());
|
||||
ListenableFuture<List<Optional<TsKvEntry>>> future = findAllAndAggregateAsync(entityId, query.getKey(), startTs, endTs, timeBucket, query.getAggregation());
|
||||
return getTskvEntriesFuture(future);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(TenantId tenantId, EntityId entityId, ReadTsKvQuery query) {
|
||||
protected ListenableFuture<List<TsKvEntry>> findAllAsyncWithLimit(EntityId entityId, ReadTsKvQuery query) {
|
||||
String strKey = query.getKey();
|
||||
Integer keyId = getOrSaveKeyId(strKey);
|
||||
List<TimescaleTsKvEntity> timescaleTsKvEntities = tsKvRepository.findAllWithLimit(
|
||||
tenantId.getId(),
|
||||
entityId.getId(),
|
||||
keyId,
|
||||
query.getStartTs(),
|
||||
@ -117,8 +116,8 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
return Futures.immediateFuture(DaoUtil.convertDataList(timescaleTsKvEntities));
|
||||
}
|
||||
|
||||
private ListenableFuture<List<Optional<TsKvEntry>>> findAllAndAggregateAsync(TenantId tenantId, EntityId entityId, String key, long startTs, long endTs, long timeBucket, Aggregation aggregation) {
|
||||
CompletableFuture<List<TimescaleTsKvEntity>> listCompletableFuture = switchAggregation(key, startTs, endTs, timeBucket, aggregation, entityId.getId(), tenantId.getId());
|
||||
private ListenableFuture<List<Optional<TsKvEntry>>> findAllAndAggregateAsync(EntityId entityId, String key, long startTs, long endTs, long timeBucket, Aggregation aggregation) {
|
||||
CompletableFuture<List<TimescaleTsKvEntity>> listCompletableFuture = switchAggregation(key, startTs, endTs, timeBucket, aggregation, entityId.getId());
|
||||
SettableFuture<List<TimescaleTsKvEntity>> listenableFuture = SettableFuture.create();
|
||||
listCompletableFuture.whenComplete((timescaleTsKvEntities, throwable) -> {
|
||||
if (throwable != null) {
|
||||
@ -133,7 +132,6 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
timescaleTsKvEntities.forEach(entity -> {
|
||||
if (entity != null && entity.isNotEmpty()) {
|
||||
entity.setEntityId(entityId.getId());
|
||||
entity.setTenantId(tenantId.getId());
|
||||
entity.setStrKey(key);
|
||||
result.add(Optional.of(DaoUtil.getData(entity)));
|
||||
} else {
|
||||
@ -167,7 +165,6 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
String strKey = tsKvEntry.getKey();
|
||||
Integer keyId = getOrSaveKeyId(strKey);
|
||||
TimescaleTsKvEntity entity = new TimescaleTsKvEntity();
|
||||
entity.setTenantId(tenantId.getId());
|
||||
entity.setEntityId(entityId.getId());
|
||||
entity.setTs(tsKvEntry.getTs());
|
||||
entity.setKey(keyId);
|
||||
@ -197,7 +194,6 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
Integer keyId = getOrSaveKeyId(strKey);
|
||||
return service.submit(() -> {
|
||||
tsKvRepository.delete(
|
||||
tenantId.getId(),
|
||||
entityId.getId(),
|
||||
keyId,
|
||||
query.getStartTs(),
|
||||
@ -208,7 +204,7 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
|
||||
@Override
|
||||
public ListenableFuture<Void> removeLatest(TenantId tenantId, EntityId entityId, DeleteTsKvQuery query) {
|
||||
return getRemoveLatestFuture(tenantId, entityId, query);
|
||||
return getRemoveLatestFuture(entityId, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -216,27 +212,26 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
return service.submit(() -> null);
|
||||
}
|
||||
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> switchAggregation(String key, long startTs, long endTs, long timeBucket, Aggregation aggregation, UUID entityId, UUID tenantId) {
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> switchAggregation(String key, long startTs, long endTs, long timeBucket, Aggregation aggregation, UUID entityId) {
|
||||
switch (aggregation) {
|
||||
case AVG:
|
||||
return findAvg(key, startTs, endTs, timeBucket, entityId, tenantId);
|
||||
return findAvg(key, startTs, endTs, timeBucket, entityId);
|
||||
case MAX:
|
||||
return findMax(key, startTs, endTs, timeBucket, entityId, tenantId);
|
||||
return findMax(key, startTs, endTs, timeBucket, entityId);
|
||||
case MIN:
|
||||
return findMin(key, startTs, endTs, timeBucket, entityId, tenantId);
|
||||
return findMin(key, startTs, endTs, timeBucket, entityId);
|
||||
case SUM:
|
||||
return findSum(key, startTs, endTs, timeBucket, entityId, tenantId);
|
||||
return findSum(key, startTs, endTs, timeBucket, entityId);
|
||||
case COUNT:
|
||||
return findCount(key, startTs, endTs, timeBucket, entityId, tenantId);
|
||||
return findCount(key, startTs, endTs, timeBucket, entityId);
|
||||
default:
|
||||
throw new IllegalArgumentException("Not supported aggregation type: " + aggregation);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findCount(String key, long startTs, long endTs, long timeBucket, UUID entityId, UUID tenantId) {
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findCount(String key, long startTs, long endTs, long timeBucket, UUID entityId) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
return aggregationRepository.findCount(
|
||||
tenantId,
|
||||
entityId,
|
||||
keyId,
|
||||
timeBucket,
|
||||
@ -244,10 +239,9 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
endTs);
|
||||
}
|
||||
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findSum(String key, long startTs, long endTs, long timeBucket, UUID entityId, UUID tenantId) {
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findSum(String key, long startTs, long endTs, long timeBucket, UUID entityId) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
return aggregationRepository.findSum(
|
||||
tenantId,
|
||||
entityId,
|
||||
keyId,
|
||||
timeBucket,
|
||||
@ -255,10 +249,9 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
endTs);
|
||||
}
|
||||
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findMin(String key, long startTs, long endTs, long timeBucket, UUID entityId, UUID tenantId) {
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findMin(String key, long startTs, long endTs, long timeBucket, UUID entityId) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
return aggregationRepository.findMin(
|
||||
tenantId,
|
||||
entityId,
|
||||
keyId,
|
||||
timeBucket,
|
||||
@ -266,10 +259,9 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
endTs);
|
||||
}
|
||||
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findMax(String key, long startTs, long endTs, long timeBucket, UUID entityId, UUID tenantId) {
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findMax(String key, long startTs, long endTs, long timeBucket, UUID entityId) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
return aggregationRepository.findMax(
|
||||
tenantId,
|
||||
entityId,
|
||||
keyId,
|
||||
timeBucket,
|
||||
@ -277,10 +269,9 @@ public class TimescaleTimeseriesDao extends AbstractSqlTimeseriesDao implements
|
||||
endTs);
|
||||
}
|
||||
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findAvg(String key, long startTs, long endTs, long timeBucket, UUID entityId, UUID tenantId) {
|
||||
private CompletableFuture<List<TimescaleTsKvEntity>> findAvg(String key, long startTs, long endTs, long timeBucket, UUID entityId) {
|
||||
Integer keyId = getOrSaveKeyId(key);
|
||||
return aggregationRepository.findAvg(
|
||||
tenantId,
|
||||
entityId,
|
||||
keyId,
|
||||
timeBucket,
|
||||
|
||||
@ -31,12 +31,10 @@ import java.util.UUID;
|
||||
@TimescaleDBTsDao
|
||||
public interface TsKvTimescaleRepository extends CrudRepository<TimescaleTsKvEntity, TimescaleTsKvCompositeKey> {
|
||||
|
||||
@Query("SELECT tskv FROM TimescaleTsKvEntity tskv WHERE tskv.tenantId = :tenantId " +
|
||||
"AND tskv.entityId = :entityId " +
|
||||
@Query("SELECT tskv FROM TimescaleTsKvEntity tskv WHERE tskv.entityId = :entityId " +
|
||||
"AND tskv.key = :entityKey " +
|
||||
"AND tskv.ts > :startTs AND tskv.ts <= :endTs")
|
||||
List<TimescaleTsKvEntity> findAllWithLimit(
|
||||
@Param("tenantId") UUID tenantId,
|
||||
@Param("entityId") UUID entityId,
|
||||
@Param("entityKey") int key,
|
||||
@Param("startTs") long startTs,
|
||||
@ -44,12 +42,10 @@ public interface TsKvTimescaleRepository extends CrudRepository<TimescaleTsKvEnt
|
||||
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query("DELETE FROM TimescaleTsKvEntity tskv WHERE tskv.tenantId = :tenantId " +
|
||||
"AND tskv.entityId = :entityId " +
|
||||
@Query("DELETE FROM TimescaleTsKvEntity tskv WHERE tskv.entityId = :entityId " +
|
||||
"AND tskv.key = :entityKey " +
|
||||
"AND tskv.ts > :startTs AND tskv.ts <= :endTs")
|
||||
void delete(@Param("tenantId") UUID tenantId,
|
||||
@Param("entityId") UUID entityId,
|
||||
void delete(@Param("entityId") UUID entityId,
|
||||
@Param("entityKey") int key,
|
||||
@Param("startTs") long startTs,
|
||||
@Param("endTs") long endTs);
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
--
|
||||
-- Copyright © 2016-2020 The Thingsboard Authors
|
||||
--
|
||||
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-- you may not use this file except in compliance with the License.
|
||||
-- You may obtain a copy of the License at
|
||||
--
|
||||
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||
--
|
||||
-- Unless required by applicable law or agreed to in writing, software
|
||||
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-- See the License for the specific language governing permissions and
|
||||
-- limitations under the License.
|
||||
--
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_tenant_ts_kv ON tenant_ts_kv(tenant_id, entity_id, key, ts);
|
||||
@ -16,8 +16,7 @@
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tenant_ts_kv (
|
||||
tenant_id uuid NOT NULL,
|
||||
CREATE TABLE IF NOT EXISTS ts_kv (
|
||||
entity_id uuid NOT NULL,
|
||||
key int NOT NULL,
|
||||
ts bigint NOT NULL,
|
||||
@ -26,7 +25,7 @@ CREATE TABLE IF NOT EXISTS tenant_ts_kv (
|
||||
long_v bigint,
|
||||
dbl_v double precision,
|
||||
json_v json,
|
||||
CONSTRAINT tenant_ts_kv_pkey PRIMARY KEY (tenant_id, entity_id, key, ts)
|
||||
CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_id, key, ts)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ts_kv_dictionary (
|
||||
|
||||
@ -44,7 +44,7 @@ public class SqlDaoServiceTestSuite {
|
||||
|
||||
// @ClassRule
|
||||
// public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
|
||||
// Arrays.asList("sql/schema-timescale.sql", "sql/schema-timescale-idx.sql", "sql/schema-entities.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"),
|
||||
// Arrays.asList("sql/schema-timescale.sql", "sql/schema-entities.sql", "sql/schema-entities-idx.sql", "sql/system-data.sql", "sql/system-test.sql"),
|
||||
// "sql/timescale/drop-all-tables.sql",
|
||||
// "sql-test.properties"
|
||||
// );
|
||||
|
||||
@ -12,7 +12,7 @@ DROP TABLE IF EXISTS event;
|
||||
DROP TABLE IF EXISTS relation;
|
||||
DROP TABLE IF EXISTS tb_user;
|
||||
DROP TABLE IF EXISTS tenant;
|
||||
DROP TABLE IF EXISTS tenant_ts_kv;
|
||||
DROP TABLE IF EXISTS ts_kv;
|
||||
DROP TABLE IF EXISTS ts_kv_latest;
|
||||
DROP TABLE IF EXISTS user_credentials;
|
||||
DROP TABLE IF EXISTS widget_type;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user