CREATE OR REPLACE FUNCTION _meta.place_chunks(chunk_row chunk, placement chunk_placement_type, replication_factor SMALLINT) RETURNS TABLE(replica_id SMALLINT, database_name NAME) LANGUAGE PLPGSQL AS $BODY$ DECLARE BEGIN PERFORM setseed(chunk_row.id::double precision/2147483647::double precision); IF placement = 'RANDOM' THEN RETURN QUERY SELECT pr.replica_id, dn.database_name FROM partition_replica pr INNER JOIN ( SELECT * FROM ( SELECT DISTINCT n.database_name FROM node n LIMIT replication_factor ) AS d ORDER BY random() ) AS dn ON TRUE WHERE pr.partition_id = chunk_row.partition_id; ELSIF placement = 'STICKY' THEN RETURN QUERY SELECT pr.replica_id, dn.database_name FROM partition_replica pr INNER JOIN LATERAL ( SELECT crn.database_name FROM chunk_replica_node crn INNER JOIN chunk c ON (c.id = crn.chunk_id) WHERE crn.partition_replica_id = pr.id ORDER BY GREATEST(chunk_row.start_time, chunk_row.end_time) - GREATEST(c.start_time, c.end_time) ASC NULLS LAST LIMIT 1 ) AS dn ON true WHERE pr.partition_id = chunk_row.partition_id; IF NOT FOUND THEN RETURN query SELECT * FROM _meta.place_chunks(chunk_row, 'RANDOM', replication_factor); END IF; END IF; END $BODY$; CREATE OR REPLACE FUNCTION _meta.on_create_chunk() RETURNS TRIGGER LANGUAGE PLPGSQL AS $BODY$ DECLARE field_row field; schema_name NAME; BEGIN IF TG_OP = 'DELETE' THEN RETURN OLD; END IF; IF TG_OP = 'UPDATE' THEN IF ( (OLD.start_time IS NULL AND new.start_time IS NOT NULL) OR (OLD.end_time IS NULL AND new.end_time IS NOT NULL) ) AND ( OLD.id = NEW.id AND OLD.partition_id = NEW.partition_id ) THEN NULL; ELSE RAISE EXCEPTION 'This type of update not allowed on % table', TG_TABLE_NAME USING ERRCODE = 'IO101'; END IF; ELSIF TG_OP <> 'INSERT' THEN RAISE EXCEPTION 'Only inserts and updates supported on % table', TG_TABLE_NAME USING ERRCODE = 'IO101'; END IF; --sync data on insert IF TG_OP = 'INSERT' THEN FOR schema_name IN SELECT n.schema_name FROM node AS n LOOP EXECUTE format( $$ INSERT INTO %I.%I SELECT $1.* $$, schema_name, TG_TABLE_NAME ) USING NEW; END LOOP; --do not sync data on update. synced by close_chunk logic. INSERT INTO chunk_replica_node (chunk_id, partition_replica_id, database_name, schema_name, table_name) SELECT NEW.id, pr.id, p.database_name, pr.schema_name, format('%s_%s_%s_%s_data', h.associated_table_prefix, pr.id, pr.replica_id, NEW.id) FROM partition_replica pr INNER JOIN hypertable h ON (h.name = pr.hypertable_name) INNER JOIN _meta.place_chunks(new, h.placement, h.replication_factor) p ON (p.replica_id = pr.replica_id) WHERE pr.partition_id = NEW.partition_id; END IF; RETURN NEW; END $BODY$;