Skip to content

Commit 063c111

Browse files
committed
Merge branch 'master' into rel_1_3_beta
2 parents 4586e55 + 5f455c1 commit 063c111

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4701
-373
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ regression.out
88
*.pyc
99
*.gcda
1010
*.gcno
11-
pg_pathman--1.1.sql
11+
pg_pathman--1.2.sql

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ OBJS = src/init.o src/relation_info.o src/utils.o src/partition_filter.o \
99
src/partition_creation.o $(WIN32RES)
1010

1111
EXTENSION = pg_pathman
12-
EXTVERSION = 1.1
12+
EXTVERSION = 1.2
1313
DATA_built = pg_pathman--$(EXTVERSION).sql
14-
DATA = pg_pathman--1.0.sql pg_pathman--1.0--1.1.sql
14+
DATA = pg_pathman--1.0.sql \
15+
pg_pathman--1.0--1.1.sql \
16+
pg_pathman--1.1.sql \
17+
pg_pathman--1.1--1.2.sql
1518
PGFILEDESC = "pg_pathman - partitioning tool"
1619

1720
REGRESS = pathman_basic \

README.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,9 @@ Done! Now it's time to setup your partitioning schemes.
8484
create_hash_partitions(relation REGCLASS,
8585
attribute TEXT,
8686
partitions_count INTEGER,
87-
partition_name TEXT DEFAULT NULL,
8887
partition_data BOOLEAN DEFAULT TRUE)
8988
```
90-
Performs HASH partitioning for `relation` by integer key `attribute`. The `partitions_count` parameter specifies the number of partitions to create; it cannot be changed afterwards. If `partition_data` is `true` then all the data will be automatically copied from the parent table to partitions. Note that data migration may took a while to finish and the table will be locked until transaction commits. See `partition_table_concurrently()` for a lock-free way to migrate data. Partition creation callback is invoked for each partition if set beforehand (see `set_part_init_callback()`).
89+
Performs HASH partitioning for `relation` by integer key `attribute`. The `partitions_count` parameter specifies the number of partitions to create; it cannot be changed afterwards. If `partition_data` is `true` then all the data will be automatically copied from the parent table to partitions. Note that data migration may took a while to finish and the table will be locked until transaction commits. See `partition_table_concurrently()` for a lock-free way to migrate data. Partition creation callback is invoked for each partition if set beforehand (see `set_init_callback()`).
9190

9291
```plpgsql
9392
create_range_partitions(relation REGCLASS,
@@ -148,6 +147,14 @@ create_range_update_trigger(parent REGCLASS)
148147
Same as above, but for a RANGE-partitioned table.
149148

150149
### Post-creation partition management
150+
```plpgsql
151+
replace_hash_partition(old_partition REGCLASS,
152+
new_partition REGCLASS,
153+
lock_parent BOOL DEFAULT TRUE)
154+
```
155+
Replaces specified partition of HASH-partitioned table with another table. The `lock_parent` parameter will prevent any INSERT/UPDATE/ALTER TABLE queries to parent table.
156+
157+
151158
```plpgsql
152159
split_range_partition(partition REGCLASS,
153160
split_value ANYELEMENT,
@@ -247,6 +254,11 @@ Set partition creation callback to be invoked for each attached or created parti
247254
}
248255
```
249256

257+
```plpgsql
258+
set_set_spawn_using_bgw(relation REGCLASS, value BOOLEAN)
259+
```
260+
When INSERTing new data beyond the partitioning range, use SpawnPartitionsWorker to create new partitions in a separate transaction.
261+
250262
## Views and tables
251263

252264
#### `pathman_config` --- main config storage
@@ -255,19 +267,18 @@ CREATE TABLE IF NOT EXISTS pathman_config (
255267
partrel REGCLASS NOT NULL PRIMARY KEY,
256268
attname TEXT NOT NULL,
257269
parttype INTEGER NOT NULL,
258-
range_interval TEXT,
259-
260-
CHECK (parttype IN (1, 2)) /* check for allowed part types */ );
270+
range_interval TEXT);
261271
```
262272
This table stores a list of partitioned tables.
263273

264274
#### `pathman_config_params` --- optional parameters
265275
```plpgsql
266276
CREATE TABLE IF NOT EXISTS pathman_config_params (
267-
partrel REGCLASS NOT NULL PRIMARY KEY,
268-
enable_parent BOOLEAN NOT NULL DEFAULT TRUE,
269-
auto BOOLEAN NOT NULL DEFAULT TRUE,
270-
init_callback REGPROCEDURE NOT NULL DEFAULT 0);
277+
partrel REGCLASS NOT NULL PRIMARY KEY,
278+
enable_parent BOOLEAN NOT NULL DEFAULT TRUE,
279+
auto BOOLEAN NOT NULL DEFAULT TRUE,
280+
init_callback REGPROCEDURE NOT NULL DEFAULT 0,
281+
spawn_using_bgw BOOLEAN NOT NULL DEFAULT FALSE);
271282
```
272283
This table stores optional parameters which override standard behavior.
273284

expected/pathman_basic.out

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,8 @@ NOTICE: drop cascades to 9 other objects
17281728
/* Test automatic partition creation */
17291729
CREATE TABLE test.range_rel (
17301730
id SERIAL PRIMARY KEY,
1731-
dt TIMESTAMP NOT NULL);
1731+
dt TIMESTAMP NOT NULL,
1732+
data TEXT);
17321733
SELECT pathman.create_range_partitions('test.range_rel', 'dt', '2015-01-01'::DATE, '10 days'::INTERVAL, 1);
17331734
create_range_partitions
17341735
-------------------------
@@ -1748,9 +1749,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt = '2014-12-15';
17481749
(3 rows)
17491750

17501751
SELECT * FROM test.range_rel WHERE dt = '2014-12-15';
1751-
id | dt
1752-
-----+--------------------------
1753-
137 | Mon Dec 15 00:00:00 2014
1752+
id | dt | data
1753+
-----+--------------------------+------
1754+
137 | Mon Dec 15 00:00:00 2014 |
17541755
(1 row)
17551756

17561757
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt = '2015-03-15';
@@ -1762,9 +1763,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt = '2015-03-15';
17621763
(3 rows)
17631764

17641765
SELECT * FROM test.range_rel WHERE dt = '2015-03-15';
1765-
id | dt
1766-
----+--------------------------
1767-
74 | Sun Mar 15 00:00:00 2015
1766+
id | dt | data
1767+
----+--------------------------+------
1768+
74 | Sun Mar 15 00:00:00 2015 |
17681769
(1 row)
17691770

17701771
SELECT pathman.set_auto('test.range_rel', false);
@@ -1782,6 +1783,17 @@ SELECT pathman.set_auto('test.range_rel', true);
17821783
(1 row)
17831784

17841785
INSERT INTO test.range_rel (dt) VALUES ('2015-06-01');
1786+
/*
1787+
* Test auto removing record from config on table DROP (but not on column drop
1788+
* as it used to be before version 1.2)
1789+
*/
1790+
ALTER TABLE test.range_rel DROP COLUMN data;
1791+
SELECT * FROM pathman.pathman_config;
1792+
partrel | attname | parttype | range_interval
1793+
----------------+---------+----------+----------------
1794+
test.range_rel | dt | 2 | @ 10 days
1795+
(1 row)
1796+
17851797
DROP TABLE test.range_rel CASCADE;
17861798
NOTICE: drop cascades to 20 other objects
17871799
SELECT * FROM pathman.pathman_config;

expected/pathman_calamity.out

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,50 @@ SELECT debug_capture();
1212
set client_min_messages = NOTICE;
1313
/* create table to be partitioned */
1414
CREATE TABLE calamity.part_test(val serial);
15+
/* check function build_hash_condition() */
16+
SELECT build_hash_condition('int4', 'val', 10, 1);
17+
build_hash_condition
18+
-------------------------------------------------
19+
public.get_hash_part_idx(hashint4(val), 10) = 1
20+
(1 row)
21+
22+
SELECT build_hash_condition('text', 'val', 10, 1);
23+
build_hash_condition
24+
-------------------------------------------------
25+
public.get_hash_part_idx(hashtext(val), 10) = 1
26+
(1 row)
27+
28+
SELECT build_hash_condition('int4', 'val', 1, 1);
29+
ERROR: 'partition_index' must be lower than 'partitions_count'
30+
SELECT build_hash_condition('int4', 'val', 10, 20);
31+
ERROR: 'partition_index' must be lower than 'partitions_count'
32+
SELECT build_hash_condition('text', 'val', 10, NULL) IS NULL;
33+
?column?
34+
----------
35+
t
36+
(1 row)
37+
38+
SELECT build_hash_condition('calamity.part_test', 'val', 10, 1);
39+
ERROR: no hash function for type calamity.part_test
40+
/* check function build_range_condition() */
41+
SELECT build_range_condition('calamity.part_test', 'val', 10, 20);
42+
build_range_condition
43+
------------------------------
44+
((val >= 10) AND (val < 20))
45+
(1 row)
46+
47+
SELECT build_range_condition('calamity.part_test', 'val', 10, NULL);
48+
build_range_condition
49+
-----------------------
50+
((val >= 10))
51+
(1 row)
52+
53+
SELECT build_range_condition('calamity.part_test', 'val', NULL, 10);
54+
build_range_condition
55+
-----------------------
56+
((val < 10))
57+
(1 row)
58+
1559
/* check function validate_relname() */
1660
SELECT validate_relname('calamity.part_test');
1761
validate_relname

expected/pathman_callbacks.out

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,39 +26,66 @@ SELECT set_init_callback('callbacks.abc',
2626
(1 row)
2727

2828
INSERT INTO callbacks.abc VALUES (123, 1);
29-
INSERT INTO callbacks.abc VALUES (223, 1);
29+
INSERT INTO callbacks.abc VALUES (223, 1); /* show warning */
30+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_3", "range_max": "301", "range_min": "201"}
31+
SELECT set_spawn_using_bgw('callbacks.abc', true);
32+
set_spawn_using_bgw
33+
---------------------
34+
35+
(1 row)
36+
37+
SELECT get_number_of_partitions('callbacks.abc');
38+
get_number_of_partitions
39+
--------------------------
40+
3
41+
(1 row)
42+
43+
INSERT INTO callbacks.abc VALUES (323, 1);
44+
SELECT get_number_of_partitions('callbacks.abc'); /* +1 partition (created by BGW) */
45+
get_number_of_partitions
46+
--------------------------
47+
4
48+
(1 row)
49+
50+
SELECT set_spawn_using_bgw('callbacks.abc', false);
51+
set_spawn_using_bgw
52+
---------------------
53+
54+
(1 row)
55+
3056
SELECT append_range_partition('callbacks.abc');
31-
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_4", "range_max": "401", "range_min": "301"}
57+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_5", "range_max": "501", "range_min": "401"}
3258
append_range_partition
3359
------------------------
34-
callbacks.abc_4
60+
callbacks.abc_5
3561
(1 row)
3662

3763
SELECT prepend_range_partition('callbacks.abc');
38-
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_5", "range_max": "1", "range_min": "-99"}
64+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_6", "range_max": "1", "range_min": "-99"}
3965
prepend_range_partition
4066
-------------------------
41-
callbacks.abc_5
67+
callbacks.abc_6
4268
(1 row)
4369

44-
SELECT add_range_partition('callbacks.abc', 401, 502);
45-
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_6", "range_max": "502", "range_min": "401"}
70+
SELECT add_range_partition('callbacks.abc', 501, 602);
71+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_7", "range_max": "602", "range_min": "501"}
4672
add_range_partition
4773
---------------------
48-
callbacks.abc_6
74+
callbacks.abc_7
4975
(1 row)
5076

5177
SELECT drop_partitions('callbacks.abc');
5278
NOTICE: function callbacks.abc_upd_trig_func() does not exist, skipping
5379
NOTICE: 0 rows copied from callbacks.abc_1
5480
NOTICE: 1 rows copied from callbacks.abc_2
5581
NOTICE: 1 rows copied from callbacks.abc_3
56-
NOTICE: 0 rows copied from callbacks.abc_4
82+
NOTICE: 1 rows copied from callbacks.abc_4
5783
NOTICE: 0 rows copied from callbacks.abc_5
5884
NOTICE: 0 rows copied from callbacks.abc_6
85+
NOTICE: 0 rows copied from callbacks.abc_7
5986
drop_partitions
6087
-----------------
61-
6
88+
7
6289
(1 row)
6390

6491
/* set callback to be called on HASH partitions */

expected/pathman_permissions.out

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@ CREATE ROLE user1 LOGIN;
55
CREATE ROLE user2 LOGIN;
66
GRANT USAGE, CREATE ON SCHEMA permissions TO user1;
77
GRANT USAGE, CREATE ON SCHEMA permissions TO user2;
8-
ALTER DEFAULT PRIVILEGES FOR ROLE user1
9-
IN SCHEMA permissions
10-
GRANT SELECT, INSERT ON TABLES
11-
TO user2;
128
/* Switch to #1 */
139
SET ROLE user1;
1410
CREATE TABLE permissions.user1_table(id serial, a int);
1511
INSERT INTO permissions.user1_table SELECT g, g FROM generate_series(1, 20) as g;
16-
/* Should fail */
12+
/* Should fail (can't SELECT) */
13+
SET ROLE user2;
14+
SELECT create_range_partitions('permissions.user1_table', 'id', 1, 10, 2);
15+
ERROR: permission denied for relation user1_table
16+
/* Grant SELECT to user2 */
17+
SET ROLE user1;
18+
GRANT SELECT ON permissions.user1_table TO user2;
19+
/* Should fail (don't own parent) */
1720
SET ROLE user2;
1821
SELECT create_range_partitions('permissions.user1_table', 'id', 1, 10, 2);
19-
NOTICE: sequence "user1_table_seq" does not exist, skipping
2022
WARNING: only the owner or superuser can change partitioning configuration of table "user1_table"
2123
ERROR: new row violates row-level security policy for table "pathman_config"
2224
/* Should be ok */
@@ -37,9 +39,9 @@ SELECT * FROM pathman_config;
3739
(1 row)
3840

3941
SELECT * FROM pathman_config_params;
40-
partrel | enable_parent | auto | init_callback
41-
-------------------------+---------------+------+---------------
42-
permissions.user1_table | f | t | -
42+
partrel | enable_parent | auto | init_callback | spawn_using_bgw
43+
-------------------------+---------------+------+---------------+-----------------
44+
permissions.user1_table | f | t | - | f
4345
(1 row)
4446

4547
/* Should fail */
@@ -58,21 +60,61 @@ WARNING: only the owner or superuser can change partitioning configuration of t
5860
/* No rights to insert, should fail */
5961
SET ROLE user2;
6062
INSERT INTO permissions.user1_table (id, a) VALUES (35, 0);
61-
/* Have rights, should be ok (bgw connects as user1) */
63+
ERROR: permission denied for relation user1_table
64+
/* No rights to create partitions (need INSERT privilege) */
65+
SET ROLE user2;
66+
SELECT prepend_range_partition('permissions.user1_table');
67+
ERROR: permission denied for parent relation "user1_table"
68+
/* Allow user2 to create partitions */
6269
SET ROLE user1;
6370
GRANT INSERT ON permissions.user1_table TO user2;
71+
GRANT UPDATE(a) ON permissions.user1_table TO user2; /* per-column ACL */
72+
/* Should be able to prepend a partition */
73+
SET ROLE user2;
74+
SELECT prepend_range_partition('permissions.user1_table');
75+
prepend_range_partition
76+
---------------------------
77+
permissions.user1_table_4
78+
(1 row)
79+
80+
SELECT attname, attacl from pg_attribute
81+
WHERE attrelid = (SELECT partition FROM pathman_partition_list
82+
WHERE parent = 'permissions.user1_table'::REGCLASS
83+
ORDER BY range_min::int ASC /* prepend */
84+
LIMIT 1)
85+
ORDER BY attname; /* check ACL for each column */
86+
attname | attacl
87+
----------+-----------------
88+
a | {user2=w/user1}
89+
cmax |
90+
cmin |
91+
ctid |
92+
id |
93+
tableoid |
94+
xmax |
95+
xmin |
96+
(8 rows)
97+
98+
/* Have rights, should be ok (parent's ACL is shared by new children) */
6499
SET ROLE user2;
65100
INSERT INTO permissions.user1_table (id, a) VALUES (35, 0) RETURNING *;
66101
id | a
67102
----+---
68103
35 | 0
69104
(1 row)
70105

71-
SELECT relacl FROM pg_class WHERE oid = 'permissions.user1_table_4'::regclass;
72-
relacl
73-
--------------------------------------
74-
{user1=arwdDxt/user1,user2=ar/user1}
75-
(1 row)
106+
SELECT relname, relacl FROM pg_class
107+
WHERE oid = ANY (SELECT partition FROM pathman_partition_list
108+
WHERE parent = 'permissions.user1_table'::REGCLASS
109+
ORDER BY range_max::int DESC /* append */
110+
LIMIT 3)
111+
ORDER BY relname; /* we also check ACL for "user1_table_2" */
112+
relname | relacl
113+
---------------+--------------------------------------
114+
user1_table_2 | {user1=arwdDxt/user1,user2=r/user1}
115+
user1_table_5 | {user1=arwdDxt/user1,user2=ar/user1}
116+
user1_table_6 | {user1=arwdDxt/user1,user2=ar/user1}
117+
(3 rows)
76118

77119
/* Try to drop partition, should fail */
78120
SELECT drop_range_partition('permissions.user1_table_4');
@@ -95,11 +137,12 @@ SELECT drop_partitions('permissions.user1_table');
95137
NOTICE: function permissions.user1_table_upd_trig_func() does not exist, skipping
96138
NOTICE: 10 rows copied from permissions.user1_table_1
97139
NOTICE: 10 rows copied from permissions.user1_table_2
98-
NOTICE: 0 rows copied from permissions.user1_table_3
99-
NOTICE: 2 rows copied from permissions.user1_table_4
140+
NOTICE: 0 rows copied from permissions.user1_table_4
141+
NOTICE: 0 rows copied from permissions.user1_table_5
142+
NOTICE: 1 rows copied from permissions.user1_table_6
100143
drop_partitions
101144
-----------------
102-
4
145+
5
103146
(1 row)
104147

105148
/* Switch to #2 */

0 commit comments

Comments
 (0)