\set VERBOSITY terse CREATE EXTENSION pg_pathman; CREATE SCHEMA subpartitions; /* Create two level partitioning structure */ CREATE TABLE subpartitions.abc(a INTEGER NOT NULL, b INTEGER NOT NULL); INSERT INTO subpartitions.abc SELECT i, i FROM generate_series(1, 200, 20) as i; SELECT create_range_partitions('subpartitions.abc', 'a', 0, 100, 2); SELECT create_hash_partitions('subpartitions.abc_1', 'a', 3); SELECT create_hash_partitions('subpartitions.abc_2', 'b', 2); SELECT * FROM pathman_partition_list; SELECT tableoid::regclass, * FROM subpartitions.abc ORDER BY a, b; /* Insert should result in creation of new subpartition */ SELECT append_range_partition('subpartitions.abc', 'subpartitions.abc_3'); SELECT create_range_partitions('subpartitions.abc_3', 'b', 200, 10, 2); SELECT * FROM pathman_partition_list WHERE parent = 'subpartitions.abc_3'::regclass; INSERT INTO subpartitions.abc VALUES (215, 215); SELECT * FROM pathman_partition_list WHERE parent = 'subpartitions.abc_3'::regclass; SELECT tableoid::regclass, * FROM subpartitions.abc WHERE a = 215 AND b = 215 ORDER BY a, b; /* Pruning tests */ EXPLAIN (COSTS OFF) SELECT * FROM subpartitions.abc WHERE a < 150; EXPLAIN (COSTS OFF) SELECT * FROM subpartitions.abc WHERE b = 215; EXPLAIN (COSTS OFF) SELECT * FROM subpartitions.abc WHERE a = 215 AND b = 215; EXPLAIN (COSTS OFF) SELECT * FROM subpartitions.abc WHERE a >= 210 AND b >= 210; CREATE OR REPLACE FUNCTION check_multilevel_queries() RETURNS VOID AS $$ BEGIN IF NOT EXISTS(SELECT * FROM (SELECT tableoid::regclass, * FROM subpartitions.abc WHERE a = 215 AND b = 215 ORDER BY a, b) t1) THEN RAISE EXCEPTION 'should be at least one record in result'; END IF; END $$ LANGUAGE plpgsql; SELECT check_multilevel_queries(); DROP FUNCTION check_multilevel_queries(); /* Multilevel partitioning with updates */ CREATE OR REPLACE FUNCTION subpartitions.partitions_tree( rel REGCLASS, level TEXT DEFAULT ' ' ) RETURNS SETOF TEXT AS $$ DECLARE partition REGCLASS; subpartition TEXT; BEGIN IF rel IS NULL THEN RETURN; END IF; RETURN NEXT rel::TEXT; FOR partition IN (SELECT l.partition FROM pathman_partition_list l WHERE parent = rel) LOOP FOR subpartition IN (SELECT subpartitions.partitions_tree(partition, level || ' ')) LOOP RETURN NEXT level || subpartition::TEXT; END LOOP; END LOOP; END $$ LANGUAGE plpgsql; SELECT append_range_partition('subpartitions.abc', 'subpartitions.abc_4'); SELECT create_hash_partitions('subpartitions.abc_4', 'b', 2); SELECT subpartitions.partitions_tree('subpartitions.abc'); DROP TABLE subpartitions.abc CASCADE; /* Test that update works correctly */ SET pg_pathman.enable_partitionrouter = ON; CREATE TABLE subpartitions.abc(a INTEGER NOT NULL, b INTEGER NOT NULL); SELECT create_range_partitions('subpartitions.abc', 'a', 0, 100, 2); SELECT create_range_partitions('subpartitions.abc_1', 'b', 0, 50, 2); /* 0 - 100 */ SELECT create_range_partitions('subpartitions.abc_2', 'b', 0, 50, 2); /* 100 - 200 */ INSERT INTO subpartitions.abc SELECT 25, 25 FROM generate_series(1, 10); SELECT tableoid::regclass, * FROM subpartitions.abc; /* subpartitions.abc_1_1 */ UPDATE subpartitions.abc SET a = 125 WHERE a = 25 and b = 25; SELECT tableoid::regclass, * FROM subpartitions.abc; /* subpartitions.abc_2_1 */ UPDATE subpartitions.abc SET b = 75 WHERE a = 125 and b = 25; SELECT tableoid::regclass, * FROM subpartitions.abc; /* subpartitions.abc_2_2 */ UPDATE subpartitions.abc SET b = 125 WHERE a = 125 and b = 75; SELECT tableoid::regclass, * FROM subpartitions.abc; /* subpartitions.abc_2_3 */ /* split_range_partition */ SELECT split_range_partition('subpartitions.abc_2', 150); /* FAIL */ SELECT split_range_partition('subpartitions.abc_2_2', 75); /* OK */ SELECT subpartitions.partitions_tree('subpartitions.abc'); /* merge_range_partitions */ TRUNCATE subpartitions.abc; INSERT INTO subpartitions.abc VALUES (150, 0); SELECT append_range_partition('subpartitions.abc', 'subpartitions.abc_3'); /* 200 - 300 */ INSERT INTO subpartitions.abc VALUES (250, 50); SELECT merge_range_partitions('subpartitions.abc_2', 'subpartitions.abc_3'); /* OK */ SELECT tableoid::regclass, * FROM subpartitions.abc ORDER BY a, b; SELECT merge_range_partitions('subpartitions.abc_2_1', 'subpartitions.abc_2_2'); /* OK */ SELECT tableoid::regclass, * FROM subpartitions.abc ORDER BY a, b; DROP TABLE subpartitions.abc CASCADE; /* Check insert & update with dropped columns */ CREATE TABLE subpartitions.abc(a int, b int, c int, id1 int not null, id2 int not null, val serial); SELECT create_range_partitions('subpartitions.abc', 'id1', 0, 100, 2); ALTER TABLE subpartitions.abc DROP COLUMN c; SELECT prepend_range_partition('subpartitions.abc'); ALTER TABLE subpartitions.abc DROP COLUMN b; SELECT create_range_partitions('subpartitions.abc_3', 'id2', 0, 10, 3); ALTER TABLE subpartitions.abc DROP COLUMN a; SELECT prepend_range_partition('subpartitions.abc_3'); SELECT * FROM pathman_partition_list ORDER BY parent, partition; INSERT INTO subpartitions.abc VALUES (10, 0), (110, 0), (-1, 0), (-1, -1); SELECT tableoid::regclass, * FROM subpartitions.abc ORDER BY id1, id2, val; SET pg_pathman.enable_partitionrouter = ON; UPDATE subpartitions.abc SET id1 = -1, id2 = -1 RETURNING tableoid::regclass, *; DROP TABLE subpartitions.abc CASCADE; DROP SCHEMA subpartitions CASCADE; DROP EXTENSION pg_pathman;