diff --git a/extension/sql/common/tables.sql b/extension/sql/common/tables.sql index e99b83c68..e73819508 100644 --- a/extension/sql/common/tables.sql +++ b/extension/sql/common/tables.sql @@ -67,6 +67,12 @@ CREATE TABLE IF NOT EXISTS hypertable ( UNIQUE (root_schema_name, root_table_name) ); +-- deleted_hypertable is used to avoid deadlocks when doing multinode drops. +CREATE TABLE IF NOT EXISTS deleted_hypertable ( + LIKE hypertable, + deleted_on NAME +); + -- hypertable_replica contains information on how a hypertable's data replicas -- are stored. A replica of the data is across all partitions and time. -- diff --git a/extension/sql/main/ddl_triggers.sql b/extension/sql/main/ddl_triggers.sql index 926b2a0d7..b5eedfccb 100644 --- a/extension/sql/main/ddl_triggers.sql +++ b/extension/sql/main/ddl_triggers.sql @@ -254,6 +254,16 @@ BEGIN END $BODY$; +CREATE OR REPLACE FUNCTION _sysinternal.is_hypertable( + schema_name NAME, + table_name NAME +) + RETURNS BOOLEAN LANGUAGE PLPGSQL VOLATILE AS +$BODY$ +BEGIN + return exists(select 1 from hypertable where main_schema_name = schema_name and main_table_name=table_name); +END +$BODY$; --Handles drop table command CREATE OR REPLACE FUNCTION _sysinternal.ddl_process_drop_table() @@ -261,13 +271,16 @@ CREATE OR REPLACE FUNCTION _sysinternal.ddl_process_drop_table() DECLARE obj record; BEGIN + IF current_setting('io.ignore_ddl_in_trigger', true) = 'true' THEN + RETURN; + END IF; + FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects() LOOP - IF tg_tag = 'DROP TABLE' AND obj.object_name IS NOT NULL THEN + IF tg_tag = 'DROP TABLE' AND _sysinternal.is_hypertable(obj.schema_name, obj.object_name) THEN PERFORM _sysinternal.drop_hypertable(obj.schema_name, obj.object_name); END IF; END LOOP; - END $BODY$; diff --git a/extension/sql/main/hypertable_index_triggers.sql b/extension/sql/main/hypertable_index_triggers.sql index 8f0e123b3..c8b43606e 100644 --- a/extension/sql/main/hypertable_index_triggers.sql +++ b/extension/sql/main/hypertable_index_triggers.sql @@ -108,12 +108,10 @@ BEGIN IF new.deleted_on <> current_database() THEN PERFORM set_config('io.ignore_ddl_in_trigger', 'true', true); - EXECUTE format('DROP INDEX %I.%I', NEW.main_schema_name, NEW.main_index_name); + EXECUTE format('DROP INDEX IF EXISTS %I.%I', NEW.main_schema_name, NEW.main_index_name); END IF; RETURN NEW; END $BODY$ SET SEARCH_PATH = 'public'; - - diff --git a/extension/sql/main/hypertable_triggers.sql b/extension/sql/main/hypertable_triggers.sql index 7bfb7a605..2805cc42f 100644 --- a/extension/sql/main/hypertable_triggers.sql +++ b/extension/sql/main/hypertable_triggers.sql @@ -73,15 +73,6 @@ BEGIN END IF; IF TG_OP = 'DELETE' THEN - - PERFORM _sysinternal.drop_root_table(OLD.root_schema_name, OLD.root_table_name); - PERFORM _sysinternal.drop_root_distinct_table(OLD.distinct_schema_name, OLD.distinct_table_name); - - if current_setting('io.iobeam_drop', true) <> 'true' THEN - PERFORM set_config('io.iobeam_drop', 'true', true); - PERFORM _sysinternal.drop_table(OLD.main_schema_name, OLD.main_table_name); - END IF; - RETURN OLD; END IF; @@ -91,3 +82,32 @@ BEGIN END $BODY$ SET SEARCH_PATH = 'public'; + + +/* + Drops public hypertable when hypertable rows deleted (row created in deleted_hypertable table). +*/ +CREATE OR REPLACE FUNCTION _sysinternal.on_deleted_hypertable() + RETURNS TRIGGER LANGUAGE PLPGSQL AS +$BODY$ +DECLARE + hypertable_row hypertable; +BEGIN + IF TG_OP <> 'INSERT' THEN + RAISE EXCEPTION 'Only inserts supported on % table', TG_TABLE_NAME + USING ERRCODE = 'IO101'; + END IF; + --drop index on all chunks + + PERFORM _sysinternal.drop_root_table(NEW.root_schema_name, NEW.root_table_name); + PERFORM _sysinternal.drop_root_distinct_table(NEW.distinct_schema_name, NEW.distinct_table_name); + + IF new.deleted_on <> current_database() THEN + PERFORM set_config('io.ignore_ddl_in_trigger', 'true', true); + EXECUTE format('DROP TABLE %I.%I', NEW.main_schema_name, NEW.main_table_name); + END IF; + + RETURN NEW; +END +$BODY$ +SET SEARCH_PATH = 'public'; diff --git a/extension/sql/main/setup_main.sql b/extension/sql/main/setup_main.sql index 2a12f8c2f..ff7d4c405 100644 --- a/extension/sql/main/setup_main.sql +++ b/extension/sql/main/setup_main.sql @@ -75,6 +75,11 @@ BEGIN CREATE TRIGGER trigger_on_deleted_hypertable_index AFTER INSERT OR UPDATE OR DELETE ON deleted_hypertable_index FOR EACH ROW EXECUTE PROCEDURE _sysinternal.on_deleted_hypertable_index(); + DROP TRIGGER IF EXISTS trigger_on_deleted_hypertable + ON deleted_hypertable; + CREATE TRIGGER trigger_on_deleted_hypertable AFTER INSERT OR UPDATE OR DELETE ON deleted_hypertable + FOR EACH ROW EXECUTE PROCEDURE _sysinternal.on_deleted_hypertable(); + CREATE EVENT TRIGGER ddl_create_index ON ddl_command_end WHEN tag IN ('create index') EXECUTE PROCEDURE _sysinternal.ddl_process_create_index(); diff --git a/extension/sql/meta/setup_meta.sql b/extension/sql/meta/setup_meta.sql index 76b7dd351..93ad26068 100644 --- a/extension/sql/meta/setup_meta.sql +++ b/extension/sql/meta/setup_meta.sql @@ -36,8 +36,7 @@ BEGIN CREATE TRIGGER trigger_create_partition AFTER INSERT OR UPDATE OR DELETE ON partition FOR EACH ROW EXECUTE PROCEDURE _meta.on_create_partition(); - - FOREACH table_name IN ARRAY ARRAY ['cluster_user', 'hypertable', 'hypertable_index', 'deleted_hypertable_index', 'hypertable_replica', + FOREACH table_name IN ARRAY ARRAY ['cluster_user', 'hypertable', 'deleted_hypertable', 'hypertable_index', 'deleted_hypertable_index', 'hypertable_replica', 'distinct_replica_node', 'partition_epoch', 'partition', 'partition_replica', 'chunk_replica_node', 'field', 'deleted_field', 'meta', 'default_replica_node'] :: NAME [] LOOP EXECUTE format( @@ -59,7 +58,7 @@ BEGIN table_name); END LOOP; - FOREACH table_name IN ARRAY ARRAY ['field', 'hypertable_index'] :: NAME [] LOOP + FOREACH table_name IN ARRAY ARRAY ['field', 'hypertable_index', 'hypertable'] :: NAME [] LOOP EXECUTE format( $$ DROP TRIGGER IF EXISTS trigger_0_deleted_%1$s ON %1$s diff --git a/extension/sql/tests/regression/drop_hypertable.sql b/extension/sql/tests/regression/drop_hypertable.sql index 8e273f102..8820bc249 100644 --- a/extension/sql/tests/regression/drop_hypertable.sql +++ b/extension/sql/tests/regression/drop_hypertable.sql @@ -15,9 +15,12 @@ FROM "_sysinternal"._hyper_1_0_distinct; SELECT * FROM hypertable; DROP TABLE "testNs"; + SELECT * FROM hypertable; +\dt "public".* \dt+ "_sysinternal".* \c Test1 - +SELECT * FROM hypertable; +\dt "public".* \dt+ "_sysinternal".* \ No newline at end of file diff --git a/extension/sql/tests/regression/expected/drop_hypertable.out b/extension/sql/tests/regression/expected/drop_hypertable.out index b1fd22e02..1e77cc79b 100644 --- a/extension/sql/tests/regression/expected/drop_hypertable.out +++ b/extension/sql/tests/regression/expected/drop_hypertable.out @@ -410,6 +410,34 @@ SELECT * FROM hypertable; public.chunk_closing_test | public | chunk_closing_test | _sysinternal | _hyper_2 | _sysinternal | _hyper_2_root | _sysinternal | _hyper_2_distinct | 1 | STICKY | time | bigint | Test1 | 10000 (1 row) +\dt "public".* + List of relations + Schema | Name | Type | Owner +--------+--------------------------+-------+---------- + public | chunk | table | postgres + public | chunk_closing_test | table | postgres + public | chunk_replica_node | table | postgres + public | chunk_replica_node_index | table | postgres + public | cluster_user | table | postgres + public | default_replica_node | table | postgres + public | deleted_field | table | postgres + public | deleted_hypertable | table | postgres + public | deleted_hypertable_index | table | postgres + public | distinct_replica_node | table | postgres + public | field | table | postgres + public | hypertable | table | postgres + public | hypertable_index | table | postgres + public | hypertable_replica | table | postgres + public | kafka_offset_cluster | table | postgres + public | kafka_offset_local | table | postgres + public | kafka_offset_node | table | postgres + public | meta | table | postgres + public | node | table | postgres + public | partition | table | postgres + public | partition_epoch | table | postgres + public | partition_replica | table | postgres +(22 rows) + \dt+ "_sysinternal".* List of relations Schema | Name | Type | Owner | Size | Description @@ -423,6 +451,40 @@ SELECT * FROM hypertable; (6 rows) \c Test1 +SELECT * FROM hypertable; + name | main_schema_name | main_table_name | associated_schema_name | associated_table_prefix | root_schema_name | root_table_name | distinct_schema_name | distinct_table_name | replication_factor | placement | time_field_name | time_field_type | created_on | chunk_size_bytes +---------------------------+------------------+--------------------+------------------------+-------------------------+------------------+-----------------+----------------------+---------------------+--------------------+-----------+-----------------+-----------------+------------+------------------ + public.chunk_closing_test | public | chunk_closing_test | _sysinternal | _hyper_2 | _sysinternal | _hyper_2_root | _sysinternal | _hyper_2_distinct | 1 | STICKY | time | bigint | Test1 | 10000 +(1 row) + +\dt "public".* + List of relations + Schema | Name | Type | Owner +--------+--------------------------+-------+---------- + public | chunk | table | postgres + public | chunk_closing_test | table | postgres + public | chunk_replica_node | table | postgres + public | chunk_replica_node_index | table | postgres + public | cluster_user | table | postgres + public | default_replica_node | table | postgres + public | deleted_field | table | postgres + public | deleted_hypertable | table | postgres + public | deleted_hypertable_index | table | postgres + public | distinct_replica_node | table | postgres + public | field | table | postgres + public | hypertable | table | postgres + public | hypertable_index | table | postgres + public | hypertable_replica | table | postgres + public | kafka_offset_cluster | table | postgres + public | kafka_offset_local | table | postgres + public | kafka_offset_node | table | postgres + public | meta | table | postgres + public | node | table | postgres + public | partition | table | postgres + public | partition_epoch | table | postgres + public | partition_replica | table | postgres +(22 rows) + \dt+ "_sysinternal".* List of relations Schema | Name | Type | Owner | Size | Description diff --git a/extension/sql/tests/regression/expected/kafka.out b/extension/sql/tests/regression/expected/kafka.out index cdc8d58ff..3950ed9cf 100644 --- a/extension/sql/tests/regression/expected/kafka.out +++ b/extension/sql/tests/regression/expected/kafka.out @@ -38,6 +38,7 @@ SELECT add_node('test2' :: NAME, 'localhost'); public | cluster_user | table | postgres public | default_replica_node | table | postgres public | deleted_field | table | postgres + public | deleted_hypertable | table | postgres public | deleted_hypertable_index | table | postgres public | distinct_replica_node | table | postgres public | field | table | postgres @@ -52,7 +53,7 @@ SELECT add_node('test2' :: NAME, 'localhost'); public | partition | table | postgres public | partition_epoch | table | postgres public | partition_replica | table | postgres -(20 rows) +(21 rows) \det+ public.* List of foreign tables