- Notifications
You must be signed in to change notification settings - Fork 69
Infinite bounds
Release 1.3 introduced support for semi-infinite partition bounds, e.g. (-inf, 10) or (-100, +inf). NULL value of a corresponding type is used to specify infinite range bounds.
/* case #1 - 100% manual partition creation */ create table test_1 (val int8 not null); select add_to_pathman_config('test_1', 'val', NULL); /* don't set default interval */ /* case #2 - 95% manual (auto naming) */ create table test_2 (val int8 not null); select create_naming_sequence('test_2'); select add_to_pathman_config('test_2', 'val', '1000'); /* use default interval 1000 */ select add_range_partition('test_2', 1, 100); /* initial partition [1, 100) */ /* case #3 - create some partitions */ create table test_3 (val int8 not null); select create_range_partitions('test_3', 'val', 1, 1000, 10);As we can see, table test_1 has no partitions yet:
table pathman_partition_list; parent | partition | parttype | expr | range_min | range_max --------+-----------+----------+------+-----------+----------- test_2 | test_2_1 | 2 | val | 1 | 100 test_3 | test_3_1 | 2 | val | 1 | 1001 test_3 | test_3_2 | 2 | val | 1001 | 2001 test_3 | test_3_3 | 2 | val | 2001 | 3001 test_3 | test_3_4 | 2 | val | 3001 | 4001 test_3 | test_3_5 | 2 | val | 4001 | 5001 test_3 | test_3_6 | 2 | val | 5001 | 6001 test_3 | test_3_7 | 2 | val | 6001 | 7001 test_3 | test_3_8 | 2 | val | 7001 | 8001 test_3 | test_3_9 | 2 | val | 8001 | 9001 test_3 | test_3_10 | 2 | val | 9001 | 10001 (11 rows)Let's create a semi-infinite partition test_1_minus_inf:
select add_range_partition('test_1', NULL, 1, 'test_1_minus_inf'); add_range_partition --------------------- test_1_minus_inf (1 row)As we can see, its left bound is NULL:
select * from pathman_partition_list where parent = 'test_1'::regclass; parent | partition | parttype | expr | range_min | range_max --------+------------------+----------+------+-----------+----------- test_1 | test_1_minus_inf | 2 | val | | 1 (1 row) select range_min is null from pathman_partition_list where parent = 'test_1'::regclass; ?column? ---------- t (1 row)We can insert some data into it:
insert into test_1 values (0), (-10), (-100), (-1000) returning *, tableoid::regclass; val | tableoid -------+------------------ 0 | test_1_minus_inf -10 | test_1_minus_inf -100 | test_1_minus_inf -1000 | test_1_minus_inf (4 rows) INSERT 0 4Good, the data was successfully forwarded to the partition test_1_inf! Let's completely cover the range with a new partition test_1_plus_inf:
select add_range_partition('test_1', 1, NULL, 'test_1_plus_inf'); add_range_partition --------------------- test_1_plus_inf (1 row)Add a few more rows:
insert into test_1 select random() * 10000 - 5000 from generate_series(1, 6) returning *, tableoid::regclass; val | tableoid -------+------------------ 4525 | test_1_plus_inf 4912 | test_1_plus_inf -1878 | test_1_minus_inf -718 | test_1_minus_inf 2114 | test_1_plus_inf 2915 | test_1_plus_inf (6 rows) INSERT 0 6Note that we cannot append or prepend new partitions to table test_1:
select append_range_partition('test_1'); ERROR: Cannot append partition because last partition's range is half open select prepend_range_partition('test_1'); ERROR: Cannot prepend partition because first partition's range is half openWe can also add semi-infinite partitions to an existing set of finite children that we've created beforehand:
/* add new partition [100, +inf) */ select add_range_partition('test_2', 100, NULL); add_range_partition --------------------- test_2_2 /* prepend will still work! */ select prepend_range_partition('test_2'); prepend_range_partition ------------------------- test_2_3 (1 row) /* check the partitions of table 'test_2' */ select * from pathman_partition_list where parent = 'test_2'::regclass; parent | partition | parttype | expr | range_min | range_max --------+-----------+----------+------+-----------+----------- test_2 | test_2_3 | 2 | val | -999 | 1 test_2 | test_2_1 | 2 | val | 1 | 100 test_2 | test_2_2 | 2 | val | 100 | (3 rows)All semi-infinite partitions are 1st class citizens, which means that operations like merge, split, drop will work as expected:
select merge_range_partitions('test_2_1', 'test_2_2'); merge_range_partitions ------------------------ (1 row) select * from pathman_partition_list where parent = 'test_2'::regclass; parent | partition | parttype | expr | range_min | range_max --------+-----------+----------+------+-----------+----------- test_2 | test_2_3 | 2 | val | -999 | 1 test_2 | test_2_1 | 2 | val | 1 | (2 rows) select split_range_partition('test_2_1', 2000); split_range_partition ----------------------- {1,NULL} (1 row) select * from pathman_partition_list where parent = 'test_2'::regclass; parent | partition | parttype | expr | range_min | range_max --------+-----------+----------+------+-----------+----------- test_2 | test_2_3 | 2 | val | -999 | 1 test_2 | test_2_1 | 2 | val | 1 | 2000 test_2 | test_2_4 | 2 | val | 2000 | (3 rows) select drop_range_partition('test_2_4'); drop_range_partition ---------------------- test_2_4 (1 row) select * from pathman_partition_list where parent = 'test_2'::regclass; parent | partition | parttype | expr | range_min | range_max --------+-----------+----------+------+-----------+----------- test_2 | test_2_3 | 2 | val | -999 | 1 test_2 | test_2_1 | 2 | val | 1 | 2000 (2 rows)- Infinite bounds can only be used with RANGE partitioning;
- Only one bound (left or right) of a partition may be infinite (i.e.
(NULL, NULL)is prohibited);