timescaledb/sql/main/insert.sql
Matvey Arye 42ee7c8586 starting refactor of clustering and naming logic
This fix allows more flexible placement of tables on a node; better
and more flexible logic for remote placement of chunks on nodes.
2016-11-22 16:41:27 -05:00

149 lines
4.6 KiB
PL/PgSQL

CREATE OR REPLACE FUNCTION get_fields_from_json(
hypertable_name NAME
)
RETURNS TEXT [] LANGUAGE SQL STABLE AS
$BODY$
SELECT ARRAY(
SELECT format($$((value->>'%s')::%s)$$, field_name, data_type)
FROM (
SELECT
f.name AS field_name,
f.data_type
FROM field AS f
WHERE f.hypertable_name = get_fields_from_json.hypertable_name
ORDER BY f.name
) AS info
);
$BODY$;
CREATE OR REPLACE FUNCTION get_field_list(
hypertable_name NAME
)
RETURNS TEXT LANGUAGE SQL STABLE AS
$BODY$
SELECT array_to_string(get_quoted_field_names(hypertable_name), ', ')
$BODY$;
CREATE OR REPLACE FUNCTION get_field_from_json_list(
hypertable_name NAME
)
RETURNS TEXT LANGUAGE SQL STABLE AS
$BODY$
SELECT array_to_string(get_fields_from_json(hypertable_name), ', ')
$BODY$;
CREATE OR REPLACE FUNCTION create_temp_copy_table_one_partition(
table_name TEXT,
partition_number SMALLINT,
total_partitions SMALLINT
)
RETURNS TEXT LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
BEGIN
EXECUTE format(
$$
CREATE TEMP TABLE "%s" (
hypertable_name name NOT NULL,
time BIGINT NOT NULL,
value jsonb
) ON COMMIT DROP
$$, table_name);
RETURN table_name;
END
$BODY$;
--creates fields from project_series, not namespaces
CREATE OR REPLACE FUNCTION insert_data_one_partition(
copy_table_oid REGCLASS,
partition_number SMALLINT,
total_partitions SMALLINT
)
RETURNS VOID LANGUAGE PLPGSQL VOLATILE AS
$BODY$
DECLARE
chunk_replica_node_row chunk_replica;
distinct_table_oid REGCLASS;
time_point BIGINT;
hypertable_point NAME;
BEGIN
time_point := 1;
EXECUTE format(
$$
SELECT "time", hypertable_name FROM %s ORDER BY hypertable_name LIMIT 1
$$,
copy_table_oid)
INTO time_point, hypertable_point;
WHILE time_point IS NOT NULL LOOP
SELECT *
INTO distinct_table_oid
FROM get_distinct_local_table_oid(hypertable_point);
SELECT *
INTO data_table_row
FROM get_or_create_data_table(time_point, hypertable_point,
partition_number, total_partitions);
BEGIN
EXECUTE format(
$$
WITH selected AS
(
DELETE FROM %2$s
WHERE ("time" >= %3$L OR %3$L IS NULL) and ("time" <= %4$L OR %4$L IS NULL)
AND hypertable_name = %5$L
RETURNING *
),
distinct_field AS (
SELECT name
FROM field
WHERE hypertable_name = %5$L AND is_distinct = TRUE
),
insert_distinct AS (
INSERT INTO %6$s as distinct_table
SELECT distinct_field.name, value->>distinct_field.name, max(time)
FROM distinct_field
CROSS JOIN selected
WHERE value ? distinct_field.name
GROUP BY distinct_field.name, (value->>distinct_field.name)
ON CONFLICT (field, value)
--DO NOTHING
DO UPDATE
SET last_time_approx = EXCLUDED.last_time_approx + (1e9::bigint * 60*60*24::bigint)
WHERE EXCLUDED.last_time_approx > distinct_table.last_time_approx
--DO UPDATE SET last_time_approx = EXCLUDED.last_time_approx
)
INSERT INTO %1$s (time, %7$s) SELECT time, %8$s FROM selected;
$$, data_table_row.table_oid, copy_table_oid, data_table_row.start_time,
data_table_row.end_time, hypertable_point, distinct_table_oid,
get_field_list(hypertable_point),
get_field_from_json_list(hypertable_point))
USING data_table_row;
EXECUTE format(
$$
SELECT "time", hypertable_name FROM %s ORDER BY hypertable_name LIMIT 1
$$,
copy_table_oid)
INTO time_point, hypertable_point;
EXCEPTION WHEN deadlock_detected THEN
--do nothing, rerun loop (deadlock can be caused by concurrent updates to distinct table)
--TODO: try to get rid of this by ordering the insert
END;
END LOOP;
END
$BODY$;