diff --git a/src/test/regress/expected/multi_truncate.out b/src/test/regress/expected/multi_truncate.out index 7a77dee23..c21a65fee 100644 --- a/src/test/regress/expected/multi_truncate.out +++ b/src/test/regress/expected/multi_truncate.out @@ -8,7 +8,7 @@ SET search_path TO multi_truncate; CREATE VIEW table_sizes AS SELECT c.relname as name, - pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as size + pg_catalog.pg_table_size(c.oid) > 0 as has_data FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' @@ -330,7 +330,7 @@ SELECT * FROM test_local_truncate; SELECT citus_drop_all_shards('test_local_truncate', 'public', 'test_local_truncate'); citus_drop_all_shards --------------------------------------------------------------------- - 4 + 4 (1 row) DELETE FROM pg_dist_partition WHERE logicalrelid = 'test_local_truncate'::regclass; @@ -369,7 +369,7 @@ SELECT * FROM test_local_truncate; SELECT citus_drop_all_shards('test_local_truncate', 'public', 'test_local_truncate'); citus_drop_all_shards --------------------------------------------------------------------- - 4 + 4 (1 row) DELETE FROM pg_dist_partition WHERE logicalrelid = 'test_local_truncate'::regclass; @@ -427,19 +427,19 @@ NOTICE: truncate cascades to table "referencing_table" (1 row) SELECT * FROM table_sizes; - name | size + name | has_data --------------------------------------------------------------------- - referenced_table | 0 bytes - referencing_table | 0 bytes + referenced_table | f + referencing_table | f (2 rows) ROLLBACK; -- observe that none of the tables are truncated SELECT * FROM table_sizes; - name | size + name | has_data --------------------------------------------------------------------- - referenced_table | 384 kB - referencing_table | 384 kB + referenced_table | t + referencing_table | t (2 rows) -- test that if we truncate the referencing table, only said table is affected @@ -451,10 +451,10 @@ SELECT truncate_local_data_after_distributing_table('referencing_table'); (1 row) SELECT * FROM table_sizes; - name | size + name | has_data --------------------------------------------------------------------- - referenced_table | 384 kB - referencing_table | 0 bytes + referenced_table | t + referencing_table | f (2 rows) ROLLBACK; @@ -470,10 +470,10 @@ NOTICE: truncate cascades to table "referencing_table" (1 row) SELECT * FROM table_sizes; - name | size + name | has_data --------------------------------------------------------------------- - referenced_table | 0 bytes - referencing_table | 0 bytes + referenced_table | f + referencing_table | f (2 rows) ROLLBACK; @@ -498,25 +498,56 @@ INSERT INTO dist SELECT x,x FROM generate_series(1,10000) x; SELECT truncate_local_data_after_distributing_table('ref'); ERROR: cannot truncate a table referenced in a foreign key constraint by a local table DETAIL: Table "dist" references "ref" --- distribute the table and start testing allowed truncation queries +-- test that we do not allow distributing tables that have foreign keys to reference tables SELECT create_distributed_table('dist','id'); ERROR: cannot distribute "dist" in sequential mode because it is not empty HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty. +SHOW citus.multi_shard_modify_mode; + citus.multi_shard_modify_mode +--------------------------------------------------------------------- + parallel +(1 row) + +-- distribute the table after a truncate +TRUNCATE dist; +SELECT create_distributed_table('dist','id'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + -- the following should truncate ref and dist BEGIN; SELECT truncate_local_data_after_distributing_table('ref'); -ERROR: cannot truncate a table referenced in a foreign key constraint by a local table -DETAIL: Table "dist" references "ref" +NOTICE: truncate cascades to table "dist" + truncate_local_data_after_distributing_table +--------------------------------------------------------------------- + +(1 row) + SELECT * FROM table_sizes; -ERROR: current transaction is aborted, commands ignored until end of transaction block + name | has_data +--------------------------------------------------------------------- + dist | f + ref | f +(2 rows) + ROLLBACK; -- the following should truncate dist table only BEGIN; SELECT truncate_local_data_after_distributing_table('dist'); -ERROR: supplied parameter is not a distributed relation -DETAIL: This UDF only truncates local records of distributed tables. + truncate_local_data_after_distributing_table +--------------------------------------------------------------------- + +(1 row) + SELECT * FROM table_sizes; -ERROR: current transaction is aborted, commands ignored until end of transaction block + name | has_data +--------------------------------------------------------------------- + dist | f + ref | t +(2 rows) + ROLLBACK; DROP TABLE ref, dist; -- tests for issue 1770 diff --git a/src/test/regress/expected/single_node_truncate.out b/src/test/regress/expected/single_node_truncate.out new file mode 100644 index 000000000..245e43774 --- /dev/null +++ b/src/test/regress/expected/single_node_truncate.out @@ -0,0 +1,147 @@ +CREATE SCHEMA single_node_truncate; +SET search_path TO single_node_truncate; +SET citus.shard_replication_factor TO 1; +-- helper view that prints out local table names and sizes in the schema +CREATE VIEW table_sizes AS +SELECT + c.relname as name, + pg_catalog.pg_table_size(c.oid) > 0 as has_data +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind = 'r' + AND n.nspname = 'single_node_truncate' +ORDER BY 1; +-- test truncating reference tables +CREATE TABLE ref(id int UNIQUE, data int); +INSERT INTO ref SELECT x,x FROM generate_series(1,10000) x; +SELECT create_reference_table('ref'); +NOTICE: Copying data from local table... +NOTICE: copying the data has completed +DETAIL: The local data in the table is no longer visible, but is still on disk. +HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$single_node_truncate.ref$$) + create_reference_table +--------------------------------------------------------------------- + +(1 row) + +CREATE TABLE citus_local(id int, ref_id int REFERENCES ref(id)); +INSERT INTO citus_local SELECT x,x FROM generate_series(1,10000) x; +-- verify that shell tables for citus local tables are empty +SELECT * FROM table_sizes; + name | has_data +--------------------------------------------------------------------- + citus_local | f + citus_local_102041 | t + ref | t + ref_102040 | t +(4 rows) + +-- verify that this UDF is noop on Citus local tables +SELECT truncate_local_data_after_distributing_table('citus_local'); + truncate_local_data_after_distributing_table +--------------------------------------------------------------------- + +(1 row) + +SELECT * FROM table_sizes; + name | has_data +--------------------------------------------------------------------- + citus_local | f + citus_local_102041 | t + ref | t + ref_102040 | t +(4 rows) + +-- test that we allow cascading truncates to citus local tables +BEGIN; +SELECT truncate_local_data_after_distributing_table('ref'); +NOTICE: truncate cascades to table "citus_local" + truncate_local_data_after_distributing_table +--------------------------------------------------------------------- + +(1 row) + +SELECT * FROM table_sizes; + name | has_data +--------------------------------------------------------------------- + citus_local | f + citus_local_102041 | t + ref | f + ref_102040 | t +(4 rows) + +ROLLBACK; +-- test that we allow distributing tables that have foreign keys to reference tables +CREATE TABLE dist(id int, ref_id int REFERENCES ref(id)); +INSERT INTO dist SELECT x,x FROM generate_series(1,10000) x; +SELECT create_distributed_table('dist','id'); +NOTICE: Copying data from local table... +NOTICE: copying the data has completed +DETAIL: The local data in the table is no longer visible, but is still on disk. +HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$single_node_truncate.dist$$) + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +-- the following should truncate ref, dist and citus_local +BEGIN; +SELECT truncate_local_data_after_distributing_table('ref'); +NOTICE: truncate cascades to table "citus_local" +NOTICE: truncate cascades to table "dist" + truncate_local_data_after_distributing_table +--------------------------------------------------------------------- + +(1 row) + +SELECT * FROM table_sizes; + name | has_data +--------------------------------------------------------------------- + citus_local | f + citus_local_102041 | t + dist | f + dist_102043 | t + dist_102044 | t + dist_102045 | t + dist_102046 | t + ref | f + ref_102040 | t +(9 rows) + +ROLLBACK; +-- the following should truncate dist table only +BEGIN; +SELECT truncate_local_data_after_distributing_table('dist'); + truncate_local_data_after_distributing_table +--------------------------------------------------------------------- + +(1 row) + +SELECT * FROM table_sizes; + name | has_data +--------------------------------------------------------------------- + citus_local | f + citus_local_102041 | t + dist | f + dist_102043 | t + dist_102044 | t + dist_102045 | t + dist_102046 | t + ref | t + ref_102040 | t +(9 rows) + +ROLLBACK; +DROP TABLE ref, dist, citus_local; +DROP VIEW table_sizes; +DROP SCHEMA single_node_truncate CASCADE; +-- Remove the coordinator +SELECT 1 FROM master_remove_node('localhost', :master_port); + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + +-- restart nodeid sequence so that multi_cluster_management still has the same +-- nodeids +ALTER SEQUENCE pg_dist_node_nodeid_seq RESTART 1; diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index 359036af6..b66abb56e 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -17,6 +17,7 @@ # --- test: multi_extension test: single_node +test: single_node_truncate test: multi_cluster_management # below tests are placed right after multi_cluster_management as we do diff --git a/src/test/regress/sql/multi_truncate.sql b/src/test/regress/sql/multi_truncate.sql index f2153ce1c..25b582633 100644 --- a/src/test/regress/sql/multi_truncate.sql +++ b/src/test/regress/sql/multi_truncate.sql @@ -11,7 +11,7 @@ SET search_path TO multi_truncate; CREATE VIEW table_sizes AS SELECT c.relname as name, - pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as size + pg_catalog.pg_table_size(c.oid) > 0 as has_data FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' @@ -292,7 +292,12 @@ INSERT INTO dist SELECT x,x FROM generate_series(1,10000) x; -- test that we do not cascade truncates to local referencing tables SELECT truncate_local_data_after_distributing_table('ref'); --- distribute the table and start testing allowed truncation queries +-- test that we do not allow distributing tables that have foreign keys to reference tables +SELECT create_distributed_table('dist','id'); +SHOW citus.multi_shard_modify_mode; + +-- distribute the table after a truncate +TRUNCATE dist; SELECT create_distributed_table('dist','id'); -- the following should truncate ref and dist diff --git a/src/test/regress/sql/single_node_truncate.sql b/src/test/regress/sql/single_node_truncate.sql new file mode 100644 index 000000000..5b555ff91 --- /dev/null +++ b/src/test/regress/sql/single_node_truncate.sql @@ -0,0 +1,63 @@ +CREATE SCHEMA single_node_truncate; +SET search_path TO single_node_truncate; +SET citus.shard_replication_factor TO 1; + +-- helper view that prints out local table names and sizes in the schema +CREATE VIEW table_sizes AS +SELECT + c.relname as name, + pg_catalog.pg_table_size(c.oid) > 0 as has_data +FROM pg_catalog.pg_class c + LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace +WHERE c.relkind = 'r' + AND n.nspname = 'single_node_truncate' +ORDER BY 1; + + +-- test truncating reference tables +CREATE TABLE ref(id int UNIQUE, data int); +INSERT INTO ref SELECT x,x FROM generate_series(1,10000) x; +SELECT create_reference_table('ref'); + +CREATE TABLE citus_local(id int, ref_id int REFERENCES ref(id)); +INSERT INTO citus_local SELECT x,x FROM generate_series(1,10000) x; + +-- verify that shell tables for citus local tables are empty +SELECT * FROM table_sizes; + +-- verify that this UDF is noop on Citus local tables +SELECT truncate_local_data_after_distributing_table('citus_local'); +SELECT * FROM table_sizes; + +-- test that we allow cascading truncates to citus local tables +BEGIN; +SELECT truncate_local_data_after_distributing_table('ref'); +SELECT * FROM table_sizes; +ROLLBACK; + +-- test that we allow distributing tables that have foreign keys to reference tables +CREATE TABLE dist(id int, ref_id int REFERENCES ref(id)); +INSERT INTO dist SELECT x,x FROM generate_series(1,10000) x; +SELECT create_distributed_table('dist','id'); + +-- the following should truncate ref, dist and citus_local +BEGIN; +SELECT truncate_local_data_after_distributing_table('ref'); +SELECT * FROM table_sizes; +ROLLBACK; + +-- the following should truncate dist table only +BEGIN; +SELECT truncate_local_data_after_distributing_table('dist'); +SELECT * FROM table_sizes; +ROLLBACK; + +DROP TABLE ref, dist, citus_local; +DROP VIEW table_sizes; +DROP SCHEMA single_node_truncate CASCADE; + +-- Remove the coordinator +SELECT 1 FROM master_remove_node('localhost', :master_port); +-- restart nodeid sequence so that multi_cluster_management still has the same +-- nodeids +ALTER SEQUENCE pg_dist_node_nodeid_seq RESTART 1;