\set VERBOSITY terse SET search_path = 'public'; CREATE EXTENSION pg_pathman; CREATE SCHEMA test_bgw; /* * Tests for SpawnPartitionsWorker */ /* int4, size of Datum == 4 */ CREATE TABLE test_bgw.test_1(val INT4 NOT NULL); SELECT create_range_partitions('test_bgw.test_1', 'val', 1, 5, 2); create_range_partitions ------------------------- 2 (1 row) SELECT set_spawn_using_bgw('test_bgw.test_1', true); set_spawn_using_bgw --------------------- (1 row) INSERT INTO test_bgw.test_1 VALUES (11); SELECT * FROM pathman_partition_list ORDER BY partition; /* should contain 3 partitions */ parent | partition | parttype | expr | range_min | range_max -----------------+-------------------+----------+------+-----------+----------- test_bgw.test_1 | test_bgw.test_1_1 | 2 | val | 1 | 6 test_bgw.test_1 | test_bgw.test_1_2 | 2 | val | 6 | 11 test_bgw.test_1 | test_bgw.test_1_3 | 2 | val | 11 | 16 (3 rows) DROP TABLE test_bgw.test_1 CASCADE; NOTICE: drop cascades to 4 other objects /* int8, size of Datum == 8 */ CREATE TABLE test_bgw.test_2(val INT8 NOT NULL); SELECT create_range_partitions('test_bgw.test_2', 'val', 1, 5, 2); create_range_partitions ------------------------- 2 (1 row) SELECT set_spawn_using_bgw('test_bgw.test_2', true); set_spawn_using_bgw --------------------- (1 row) INSERT INTO test_bgw.test_2 VALUES (11); SELECT * FROM pathman_partition_list ORDER BY partition; /* should contain 3 partitions */ parent | partition | parttype | expr | range_min | range_max -----------------+-------------------+----------+------+-----------+----------- test_bgw.test_2 | test_bgw.test_2_1 | 2 | val | 1 | 6 test_bgw.test_2 | test_bgw.test_2_2 | 2 | val | 6 | 11 test_bgw.test_2 | test_bgw.test_2_3 | 2 | val | 11 | 16 (3 rows) DROP TABLE test_bgw.test_2 CASCADE; NOTICE: drop cascades to 4 other objects /* numeric, size of Datum == var */ CREATE TABLE test_bgw.test_3(val NUMERIC NOT NULL); SELECT create_range_partitions('test_bgw.test_3', 'val', 1, 5, 2); create_range_partitions ------------------------- 2 (1 row) SELECT set_spawn_using_bgw('test_bgw.test_3', true); set_spawn_using_bgw --------------------- (1 row) INSERT INTO test_bgw.test_3 VALUES (11); SELECT * FROM pathman_partition_list ORDER BY partition; /* should contain 3 partitions */ parent | partition | parttype | expr | range_min | range_max -----------------+-------------------+----------+------+-----------+----------- test_bgw.test_3 | test_bgw.test_3_1 | 2 | val | 1 | 6 test_bgw.test_3 | test_bgw.test_3_2 | 2 | val | 6 | 11 test_bgw.test_3 | test_bgw.test_3_3 | 2 | val | 11 | 16 (3 rows) DROP TABLE test_bgw.test_3 CASCADE; NOTICE: drop cascades to 4 other objects /* date, size of Datum == var */ CREATE TABLE test_bgw.test_4(val DATE NOT NULL); SELECT create_range_partitions('test_bgw.test_4', 'val', '20170213'::date, '1 day'::interval, 2); create_range_partitions ------------------------- 2 (1 row) SELECT set_spawn_using_bgw('test_bgw.test_4', true); set_spawn_using_bgw --------------------- (1 row) INSERT INTO test_bgw.test_4 VALUES ('20170215'); SELECT * FROM pathman_partition_list ORDER BY partition; /* should contain 3 partitions */ parent | partition | parttype | expr | range_min | range_max -----------------+-------------------+----------+------+------------+------------ test_bgw.test_4 | test_bgw.test_4_1 | 2 | val | 02-13-2017 | 02-14-2017 test_bgw.test_4 | test_bgw.test_4_2 | 2 | val | 02-14-2017 | 02-15-2017 test_bgw.test_4 | test_bgw.test_4_3 | 2 | val | 02-15-2017 | 02-16-2017 (3 rows) DROP TABLE test_bgw.test_4 CASCADE; NOTICE: drop cascades to 4 other objects /* test error handling in BGW */ CREATE TABLE test_bgw.test_5(val INT4 NOT NULL); SELECT create_range_partitions('test_bgw.test_5', 'val', 1, 10, 2); create_range_partitions ------------------------- 2 (1 row) CREATE OR REPLACE FUNCTION test_bgw.abort_xact(args JSONB) RETURNS VOID AS $$ BEGIN RAISE EXCEPTION 'aborting xact!'; END $$ language plpgsql; SELECT set_spawn_using_bgw('test_bgw.test_5', true); set_spawn_using_bgw --------------------- (1 row) SELECT set_init_callback('test_bgw.test_5', 'test_bgw.abort_xact(jsonb)'); set_init_callback ------------------- (1 row) INSERT INTO test_bgw.test_5 VALUES (-100); ERROR: attempt to spawn new partitions of relation "test_5" failed SELECT * FROM pathman_partition_list ORDER BY partition; /* should contain 3 partitions */ parent | partition | parttype | expr | range_min | range_max -----------------+-------------------+----------+------+-----------+----------- test_bgw.test_5 | test_bgw.test_5_1 | 2 | val | 1 | 11 test_bgw.test_5 | test_bgw.test_5_2 | 2 | val | 11 | 21 (2 rows) DROP FUNCTION test_bgw.abort_xact(args JSONB); DROP TABLE test_bgw.test_5 CASCADE; NOTICE: drop cascades to 3 other objects /* * Tests for ConcurrentPartWorker */ CREATE TABLE test_bgw.conc_part(id INT4 NOT NULL); INSERT INTO test_bgw.conc_part SELECT generate_series(1, 500); SELECT create_hash_partitions('test_bgw.conc_part', 'id', 5, false); create_hash_partitions ------------------------ 5 (1 row) BEGIN; /* Also test FOR SHARE/UPDATE conflicts in BGW */ SELECT * FROM test_bgw.conc_part ORDER BY id LIMIT 1 FOR SHARE; id ---- 1 (1 row) /* Run partitioning bgworker */ SELECT partition_table_concurrently('test_bgw.conc_part', 10, 1); NOTICE: worker started, you can stop it with the following command: select public.stop_concurrent_part_task('conc_part'); partition_table_concurrently ------------------------------ (1 row) /* Wait until bgworker starts */ SELECT pg_sleep(1); pg_sleep ---------- (1 row) ROLLBACK; /* Wait until it finises */ DO $$ DECLARE ops int8; rows int8; rows_old int8 := 0; i int4 := 0; -- protect from endless loop BEGIN LOOP -- get total number of processed rows SELECT processed FROM pathman_concurrent_part_tasks WHERE relid = 'test_bgw.conc_part'::regclass INTO rows; -- get number of partitioning tasks GET DIAGNOSTICS ops = ROW_COUNT; IF ops > 0 THEN PERFORM pg_sleep(0.2); ASSERT rows IS NOT NULL; IF rows_old = rows THEN i = i + 1; ELSIF rows < rows_old THEN RAISE EXCEPTION 'rows is decreasing: new %, old %', rows, rows_old; ELSIF rows > 500 THEN RAISE EXCEPTION 'processed % rows', rows; END IF; ELSE EXIT; -- exit loop END IF; IF i > 50 THEN RAISE WARNING 'looks like partitioning bgw is stuck!'; EXIT; -- exit loop END IF; rows_old = rows; END LOOP; END $$ LANGUAGE plpgsql; /* Check amount of tasks and rows in parent and partitions */ SELECT count(*) FROM pathman_concurrent_part_tasks; count ------- 0 (1 row) SELECT count(*) FROM ONLY test_bgw.conc_part; count ------- 0 (1 row) SELECT count(*) FROM test_bgw.conc_part; count ------- 500 (1 row) DROP TABLE test_bgw.conc_part CASCADE; NOTICE: drop cascades to 5 other objects DROP SCHEMA test_bgw CASCADE; DROP EXTENSION pg_pathman;