Skip to content

Commit 5de8506

Browse files
committed
improve README.md, create_hash_partitions(): rename 'relnames' to 'partition_names', more tests
1 parent a69f782 commit 5de8506

10 files changed

+90
-72
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +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_data BOOLEAN DEFAULT TRUE)
87+
partition_data BOOLEAN DEFAULT TRUE,
88+
partition_names TEXT[] DEFAULT NULL,
89+
tablespaces TEXT[] DEFAULT NULL)
8890
```
8991
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()`).
9092

@@ -148,9 +150,9 @@ Same as above, but for a RANGE-partitioned table.
148150

149151
### Post-creation partition management
150152
```plpgsql
151-
replace_hash_partition(old_partition REGCLASS,
152-
new_partition REGCLASS,
153-
lock_parent BOOL DEFAULT TRUE)
153+
replace_hash_partition(old_partition REGCLASS,
154+
new_partition REGCLASS,
155+
lock_parent BOOL DEFAULT TRUE)
154156
```
155157
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.
156158

@@ -168,7 +170,7 @@ merge_range_partitions(partition1 REGCLASS, partition2 REGCLASS)
168170
Merge two adjacent RANGE partitions. First, data from `partition2` is copied to `partition1`, then `partition2` is removed.
169171

170172
```plpgsql
171-
merge_range_partitions(partitions REGCLASS[])
173+
merge_range_partitions(partitions REGCLASS[])
172174
```
173175
Merge several adjacent RANGE partitions (partitions must be specified in ascending or descending order). All the data will be accumulated in the first partition.
174176

expected/pathman_basic.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,11 +2175,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.index_on_childs WHERE c1 > 100 AND c1 < 2
21752175
Filter: (c1 < 2500)
21762176
(12 rows)
21772177

2178-
/* Test create_range_partitions() + relnames */
2178+
/* Test create_range_partitions() + partition_names */
21792179
CREATE TABLE test.provided_part_names(id INT NOT NULL);
21802180
INSERT INTO test.provided_part_names SELECT generate_series(1, 10);
21812181
SELECT create_hash_partitions('test.provided_part_names', 'id', 2,
2182-
relnames := ARRAY['p1', 'p2']::TEXT[]); /* ok */
2182+
partition_names := ARRAY['p1', 'p2']::TEXT[]); /* ok */
21832183
create_hash_partitions
21842184
------------------------
21852185
2

expected/pathman_calamity.out

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,43 @@ SELECT count(*) FROM calamity.part_test;
102102
DELETE FROM calamity.part_test;
103103
/* test function create_hash_partitions() */
104104
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
105-
relnames := ARRAY[]::TEXT[]); /* not ok */
106-
ERROR: 'relnames' and 'tablespaces' may not be empty
105+
partition_names := ARRAY[]::TEXT[]); /* not ok */
106+
ERROR: 'partition_names' and 'tablespaces' may not be empty
107107
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
108-
relnames := ARRAY[ 'p1', NULL ]::TEXT[]); /* not ok */
109-
ERROR: 'relnames' and 'tablespaces' may not contain NULLs
108+
partition_names := ARRAY[ 'p1', NULL ]::TEXT[]); /* not ok */
109+
ERROR: 'partition_names' and 'tablespaces' may not contain NULLs
110110
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
111-
relnames := ARRAY[ ['p1'], ['p2'] ]::TEXT[]); /* not ok */
112-
ERROR: 'relnames' and 'tablespaces' may contain only 1 dimension
111+
partition_names := ARRAY[ ['p1'], ['p2'] ]::TEXT[]); /* not ok */
112+
ERROR: 'partition_names' and 'tablespaces' may contain only 1 dimension
113113
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
114-
relnames := ARRAY['calamity.p1']::TEXT[]); /* not ok */
115-
ERROR: size of 'relnames' must be equal to 'partitions_count'
114+
partition_names := ARRAY['calamity.p1']::TEXT[]); /* not ok */
115+
ERROR: size of 'partition_names' must be equal to 'partitions_count'
116116
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
117117
tablespaces := ARRAY['abcd']::TEXT[]); /* not ok */
118118
ERROR: size of 'tablespaces' must be equal to 'partitions_count'
119+
/* test case when naming sequence does not exist */
120+
CREATE TABLE calamity.no_naming_seq(val INT4 NOT NULL);
121+
SELECT add_to_pathman_config('calamity.no_naming_seq', 'val', '100');
122+
add_to_pathman_config
123+
-----------------------
124+
t
125+
(1 row)
126+
127+
select add_range_partition(' calamity.no_naming_seq', 10, 20);
128+
ERROR: auto naming sequence "no_naming_seq_seq" does not exist
129+
DROP TABLE calamity.no_naming_seq CASCADE;
130+
/* test (-inf, +inf) partition creation */
131+
CREATE TABLE calamity.double_inf(val INT4 NOT NULL);
132+
SELECT add_to_pathman_config('calamity.double_inf', 'val', '10');
133+
add_to_pathman_config
134+
-----------------------
135+
t
136+
(1 row)
137+
138+
select add_range_partition('calamity.double_inf', NULL::INT4, NULL::INT4,
139+
partition_name := 'double_inf_part');
140+
ERROR: cannot create partition with range (-inf, +inf)
141+
DROP TABLE calamity.double_inf CASCADE;
119142
/* test stub 'enable_parent' value for PATHMAN_CONFIG_PARAMS */
120143
INSERT INTO calamity.part_test SELECT generate_series(1, 30);
121144
SELECT create_range_partitions('calamity.part_test', 'val', 1, 10);

expected/pathman_callbacks.out

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -167,25 +167,6 @@ WARNING: callback arg: {"parent": "abc", "parttype": "1", "partition": "abc_4",
167167

168168
DROP TABLE callbacks.abc CASCADE;
169169
NOTICE: drop cascades to 5 other objects
170-
/* create table in public schema */
171-
CREATE TABLE callbacks.abc(a serial, b int);
172-
SELECT set_init_callback('callbacks.abc',
173-
'callbacks.abc_on_part_created_callback(jsonb)');
174-
set_init_callback
175-
-------------------
176-
177-
(1 row)
178-
179-
SELECT create_range_partitions('callbacks.abc', 'a', 1, 100, 2);
180-
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_1", "range_max": "101", "range_min": "1", "parent_schema": "callbacks", "partition_schema": "callbacks"}
181-
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_2", "range_max": "201", "range_min": "101", "parent_schema": "callbacks", "partition_schema": "callbacks"}
182-
create_range_partitions
183-
-------------------------
184-
2
185-
(1 row)
186-
187-
DROP TABLE callbacks.abc CASCADE;
188-
NOTICE: drop cascades to 2 other objects
189170
/* test the temprary deletion of callback function */
190171
CREATE TABLE callbacks.abc(a serial, b int);
191172
SELECT set_init_callback('callbacks.abc',

hash.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ CREATE OR REPLACE FUNCTION @extschema@.create_hash_partitions(
1616
attribute TEXT,
1717
partitions_count INTEGER,
1818
partition_data BOOLEAN DEFAULT TRUE,
19-
relnames TEXT[] DEFAULT NULL,
19+
partition_names TEXT[] DEFAULT NULL,
2020
tablespaces TEXT[] DEFAULT NULL)
2121
RETURNS INTEGER AS
2222
$$
@@ -42,7 +42,7 @@ BEGIN
4242
PERFORM @extschema@.create_hash_partitions_internal(parent_relid,
4343
attribute,
4444
partitions_count,
45-
relnames,
45+
partition_names,
4646
tablespaces);
4747

4848
/* Notify backend about changes */
@@ -281,7 +281,7 @@ CREATE OR REPLACE FUNCTION @extschema@.create_hash_partitions_internal(
281281
parent_relid REGCLASS,
282282
attribute TEXT,
283283
partitions_count INTEGER,
284-
relnames TEXT[] DEFAULT NULL,
284+
partition_names TEXT[] DEFAULT NULL,
285285
tablespaces TEXT[] DEFAULT NULL)
286286
RETURNS VOID AS 'pg_pathman', 'create_hash_partitions_internal'
287287
LANGUAGE C;

sql/pathman_basic.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,11 @@ SELECT set_enable_parent('test.index_on_childs', true);
584584
VACUUM ANALYZE test.index_on_childs;
585585
EXPLAIN (COSTS OFF) SELECT * FROM test.index_on_childs WHERE c1 > 100 AND c1 < 2500 AND c2 = 500;
586586

587-
/* Test create_range_partitions() + relnames */
587+
/* Test create_range_partitions() + partition_names */
588588
CREATE TABLE test.provided_part_names(id INT NOT NULL);
589589
INSERT INTO test.provided_part_names SELECT generate_series(1, 10);
590590
SELECT create_hash_partitions('test.provided_part_names', 'id', 2,
591-
relnames := ARRAY['p1', 'p2']::TEXT[]); /* ok */
591+
partition_names := ARRAY['p1', 'p2']::TEXT[]); /* ok */
592592
/* list partitions */
593593
SELECT partition FROM pathman_partition_list
594594
WHERE parent = 'test.provided_part_names'::REGCLASS

sql/pathman_calamity.sql

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,36 @@ DELETE FROM calamity.part_test;
3737

3838
/* test function create_hash_partitions() */
3939
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
40-
relnames := ARRAY[]::TEXT[]); /* not ok */
40+
partition_names := ARRAY[]::TEXT[]); /* not ok */
4141

4242
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
43-
relnames := ARRAY[ 'p1', NULL ]::TEXT[]); /* not ok */
43+
partition_names := ARRAY[ 'p1', NULL ]::TEXT[]); /* not ok */
4444

4545
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
46-
relnames := ARRAY[ ['p1'], ['p2'] ]::TEXT[]); /* not ok */
46+
partition_names := ARRAY[ ['p1'], ['p2'] ]::TEXT[]); /* not ok */
4747

4848
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
49-
relnames := ARRAY['calamity.p1']::TEXT[]); /* not ok */
49+
partition_names := ARRAY['calamity.p1']::TEXT[]); /* not ok */
5050

5151
SELECT create_hash_partitions('calamity.part_test', 'val', 2,
5252
tablespaces := ARRAY['abcd']::TEXT[]); /* not ok */
5353

5454

55+
/* test case when naming sequence does not exist */
56+
CREATE TABLE calamity.no_naming_seq(val INT4 NOT NULL);
57+
SELECT add_to_pathman_config('calamity.no_naming_seq', 'val', '100');
58+
select add_range_partition(' calamity.no_naming_seq', 10, 20);
59+
DROP TABLE calamity.no_naming_seq CASCADE;
60+
61+
62+
/* test (-inf, +inf) partition creation */
63+
CREATE TABLE calamity.double_inf(val INT4 NOT NULL);
64+
SELECT add_to_pathman_config('calamity.double_inf', 'val', '10');
65+
select add_range_partition('calamity.double_inf', NULL::INT4, NULL::INT4,
66+
partition_name := 'double_inf_part');
67+
DROP TABLE calamity.double_inf CASCADE;
68+
69+
5570
/* test stub 'enable_parent' value for PATHMAN_CONFIG_PARAMS */
5671
INSERT INTO calamity.part_test SELECT generate_series(1, 30);
5772
SELECT create_range_partitions('calamity.part_test', 'val', 1, 10);

sql/pathman_callbacks.sql

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,6 @@ SELECT create_hash_partitions('callbacks.abc', 'a', 5);
7878

7979
DROP TABLE callbacks.abc CASCADE;
8080

81-
/* create table in public schema */
82-
CREATE TABLE callbacks.abc(a serial, b int);
83-
SELECT set_init_callback('callbacks.abc',
84-
'callbacks.abc_on_part_created_callback(jsonb)');
85-
SELECT create_range_partitions('callbacks.abc', 'a', 1, 100, 2);
86-
87-
DROP TABLE callbacks.abc CASCADE;
88-
8981
/* test the temprary deletion of callback function */
9082
CREATE TABLE callbacks.abc(a serial, b int);
9183
SELECT set_init_callback('callbacks.abc',

src/partition_creation.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,14 +570,19 @@ choose_range_partition_name(Oid parent_relid, Oid parent_nsp)
570570
{
571571
Datum part_num;
572572
Oid part_seq_relid;
573+
char *part_seq_relname;
573574
Oid save_userid;
574575
int save_sec_context;
575576
bool need_priv_escalation = !superuser(); /* we might be a SU */
576577
char *relname;
577578
int attempts_cnt = 1000;
578579

579-
part_seq_relid = get_relname_relid(build_sequence_name_internal(parent_relid),
580-
parent_nsp);
580+
part_seq_relname = build_sequence_name_internal(parent_relid);
581+
part_seq_relid = get_relname_relid(part_seq_relname, parent_nsp);
582+
583+
/* Could not find part number generating sequence */
584+
if (!OidIsValid(part_seq_relid))
585+
elog(ERROR, "auto naming sequence \"%s\" does not exist", part_seq_relname);
581586

582587
/* Do we have to escalate privileges? */
583588
if (need_priv_escalation)
@@ -1161,7 +1166,7 @@ build_raw_range_check_tree(char *attname,
11611166

11621167
/* (-inf, +inf) */
11631168
if (and_oper->args == NIL)
1164-
elog(ERROR, "cannot create infinite range constraint");
1169+
elog(ERROR, "cannot create partition with range (-inf, +inf)");
11651170

11661171
return (Node *) and_oper;
11671172
}

src/pl_hash_funcs.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ create_hash_partitions_internal(PG_FUNCTION_ARGS)
5858
i;
5959

6060
/* Partition names and tablespaces */
61-
char **relnames = NULL,
62-
**tablespaces = NULL;
63-
int relnames_size = 0,
64-
tablespaces_size = 0;
65-
RangeVar **rangevars = NULL;
61+
char **partition_names = NULL,
62+
**tablespaces = NULL;
63+
int partition_names_size = 0,
64+
tablespaces_size = 0;
65+
RangeVar **rangevars = NULL;
6666

6767
/* Check that there's no partitions yet */
6868
if (get_pathman_relation_info(parent_relid))
@@ -74,27 +74,27 @@ create_hash_partitions_internal(PG_FUNCTION_ARGS)
7474

7575
/* Extract partition names */
7676
if (!PG_ARGISNULL(3))
77-
relnames = deconstruct_text_array(PG_GETARG_DATUM(3), &relnames_size);
77+
partition_names = deconstruct_text_array(PG_GETARG_DATUM(3), &partition_names_size);
7878

7979
/* Extract partition tablespaces */
8080
if (!PG_ARGISNULL(4))
8181
tablespaces = deconstruct_text_array(PG_GETARG_DATUM(4), &tablespaces_size);
8282

83-
/* Validate size of 'relnames' */
84-
if (relnames && relnames_size != partitions_count)
85-
elog(ERROR, "size of 'relnames' must be equal to 'partitions_count'");
83+
/* Validate size of 'partition_names' */
84+
if (partition_names && partition_names_size != partitions_count)
85+
elog(ERROR, "size of 'partition_names' must be equal to 'partitions_count'");
8686

8787
/* Validate size of 'tablespaces' */
8888
if (tablespaces && tablespaces_size != partitions_count)
8989
elog(ERROR, "size of 'tablespaces' must be equal to 'partitions_count'");
9090

9191
/* Convert partition names into RangeVars */
92-
if (relnames)
92+
if (partition_names)
9393
{
94-
rangevars = palloc(sizeof(RangeVar) * relnames_size);
95-
for (i = 0; i < relnames_size; i++)
94+
rangevars = palloc(sizeof(RangeVar) * partition_names_size);
95+
for (i = 0; i < partition_names_size; i++)
9696
{
97-
List *nl = stringToQualifiedNameList(relnames[i]);
97+
List *nl = stringToQualifiedNameList(partition_names[i]);
9898

9999
rangevars[i] = makeRangeVarFromNameList(nl);
100100
}
@@ -113,9 +113,9 @@ create_hash_partitions_internal(PG_FUNCTION_ARGS)
113113
}
114114

115115
/* Free arrays */
116-
DeepFreeArray(relnames, relnames_size);
116+
DeepFreeArray(partition_names, partition_names_size);
117117
DeepFreeArray(tablespaces, tablespaces_size);
118-
DeepFreeArray(rangevars, relnames_size);
118+
DeepFreeArray(rangevars, partition_names_size);
119119

120120
PG_RETURN_VOID();
121121
}
@@ -208,7 +208,7 @@ deconstruct_text_array(Datum array, int *array_size)
208208

209209
/* Check number of dimensions */
210210
if (ARR_NDIM(array_ptr) > 1)
211-
elog(ERROR, "'relnames' and 'tablespaces' may contain only 1 dimension");
211+
elog(ERROR, "'partition_names' and 'tablespaces' may contain only 1 dimension");
212212

213213
get_typlenbyvalalign(ARR_ELEMTYPE(array_ptr),
214214
&elemlen, &elembyval, &elemalign);
@@ -227,7 +227,7 @@ deconstruct_text_array(Datum array, int *array_size)
227227
for (i = 0; i < arr_size; i++)
228228
{
229229
if (elem_nulls[i])
230-
elog(ERROR, "'relnames' and 'tablespaces' may not contain NULLs");
230+
elog(ERROR, "'partition_names' and 'tablespaces' may not contain NULLs");
231231

232232
strings[i] = TextDatumGetCString(elem_values[i]);
233233
}
@@ -237,7 +237,7 @@ deconstruct_text_array(Datum array, int *array_size)
237237
return strings;
238238
}
239239
/* Else emit ERROR */
240-
else elog(ERROR, "'relnames' and 'tablespaces' may not be empty");
240+
else elog(ERROR, "'partition_names' and 'tablespaces' may not be empty");
241241

242242
/* Keep compiler happy */
243243
return NULL;

0 commit comments

Comments
 (0)