Skip to content

Commit f603e6c

Browse files
committedOct 19, 2016
fix args validation in invoke_on_partition_created_callback(), introduce pathman_calamity regression test
1 parent ba7b036 commit f603e6c

File tree

4 files changed

+416
-3
lines changed

4 files changed

+416
-3
lines changed
 

‎Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ REGRESS = pathman_basic \
2020
pathman_foreign_keys \
2121
pathman_permissions \
2222
pathman_rowmarks \
23-
pathman_copy_stmt_hooking
23+
pathman_copy_stmt_hooking \
24+
pathman_calamity
2425
EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
2526
EXTRA_CLEAN = pg_pathman--$(EXTVERSION).sql ./isolation_output
2627

‎expected/pathman_calamity.out

Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
\set VERBOSITY terse
2+
CREATE EXTENSION pg_pathman;
3+
CREATE SCHEMA calamity;
4+
/* call for coverage test */
5+
set client_min_messages = ERROR;
6+
SELECT debug_capture();
7+
debug_capture
8+
---------------
9+
10+
(1 row)
11+
12+
set client_min_messages = NOTICE;
13+
/* create table to be partitioned */
14+
CREATE TABLE calamity.part_test(val serial);
15+
/* check function validate_relname() */
16+
SELECT validate_relname('calamity.part_test');
17+
validate_relname
18+
--------------------
19+
calamity.part_test
20+
(1 row)
21+
22+
/* SELECT validate_relname(NULL); -- FIXME: %s */
23+
/* check function get_parent_of_partition() */
24+
SELECT get_parent_of_partition('calamity.part_test');
25+
ERROR: "part_test" is not a partition
26+
SELECT get_parent_of_partition(NULL) IS NULL;
27+
?column?
28+
----------
29+
t
30+
(1 row)
31+
32+
/* check function get_base_type() */
33+
CREATE DOMAIN calamity.test_domain AS INT4;
34+
SELECT get_base_type('int4'::regtype);
35+
get_base_type
36+
---------------
37+
integer
38+
(1 row)
39+
40+
SELECT get_base_type('calamity.test_domain'::regtype);
41+
get_base_type
42+
---------------
43+
integer
44+
(1 row)
45+
46+
SELECT get_base_type(NULL) IS NULL;
47+
?column?
48+
----------
49+
t
50+
(1 row)
51+
52+
/* check function get_attribute_type() */
53+
SELECT get_attribute_type('calamity.part_test', 'val');
54+
get_attribute_type
55+
--------------------
56+
integer
57+
(1 row)
58+
59+
SELECT get_attribute_type('calamity.part_test', NULL) IS NULL;
60+
?column?
61+
----------
62+
t
63+
(1 row)
64+
65+
SELECT get_attribute_type(NULL, 'val') IS NULL;
66+
?column?
67+
----------
68+
t
69+
(1 row)
70+
71+
SELECT get_attribute_type(NULL, NULL) IS NULL;
72+
?column?
73+
----------
74+
t
75+
(1 row)
76+
77+
/* check function build_check_constraint_name_attnum() */
78+
SELECT build_check_constraint_name('calamity.part_test', 1::int2);
79+
build_check_constraint_name
80+
-----------------------------
81+
pathman_part_test_1_check
82+
(1 row)
83+
84+
SELECT build_check_constraint_name('calamity.part_test', NULL::int2) IS NULL;
85+
?column?
86+
----------
87+
t
88+
(1 row)
89+
90+
SELECT build_check_constraint_name(NULL, 1::int2) IS NULL;
91+
?column?
92+
----------
93+
t
94+
(1 row)
95+
96+
SELECT build_check_constraint_name(NULL, NULL::int2) IS NULL;
97+
?column?
98+
----------
99+
t
100+
(1 row)
101+
102+
/* check function build_check_constraint_name_attname() */
103+
SELECT build_check_constraint_name('calamity.part_test', 'val');
104+
build_check_constraint_name
105+
-----------------------------
106+
pathman_part_test_1_check
107+
(1 row)
108+
109+
SELECT build_check_constraint_name('calamity.part_test', NULL::text) IS NULL;
110+
?column?
111+
----------
112+
t
113+
(1 row)
114+
115+
SELECT build_check_constraint_name(NULL, 'val') IS NULL;
116+
?column?
117+
----------
118+
t
119+
(1 row)
120+
121+
SELECT build_check_constraint_name(NULL, NULL::text) IS NULL;
122+
?column?
123+
----------
124+
t
125+
(1 row)
126+
127+
/* check function build_update_trigger_name() */
128+
SELECT build_update_trigger_name('calamity.part_test');
129+
build_update_trigger_name
130+
---------------------------
131+
part_test_upd_trig
132+
(1 row)
133+
134+
SELECT build_update_trigger_name(NULL) IS NULL;
135+
?column?
136+
----------
137+
t
138+
(1 row)
139+
140+
/* check function build_update_trigger_func_name() */
141+
SELECT build_update_trigger_func_name('calamity.part_test');
142+
build_update_trigger_func_name
143+
----------------------------------
144+
calamity.part_test_upd_trig_func
145+
(1 row)
146+
147+
SELECT build_update_trigger_func_name(NULL) IS NULL;
148+
?column?
149+
----------
150+
t
151+
(1 row)
152+
153+
/* check invoke_on_partition_created_callback() for RANGE */
154+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, NULL::int);
155+
ERROR: both bounds must be provided for RANGE partition
156+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, 1, NULL);
157+
ERROR: both bounds must be provided for RANGE partition
158+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, 1);
159+
ERROR: both bounds must be provided for RANGE partition
160+
/* check invoke_on_partition_created_callback() for HASH */
161+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', NULL);
162+
invoke_on_partition_created_callback
163+
--------------------------------------
164+
165+
(1 row)
166+
167+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 0);
168+
invoke_on_partition_created_callback
169+
--------------------------------------
170+
171+
(1 row)
172+
173+
SELECT invoke_on_partition_created_callback(NULL, 'calamity.part_test', 1);
174+
ERROR: parent_relid should not be null
175+
SELECT invoke_on_partition_created_callback('calamity.part_test', NULL, 1);
176+
ERROR: partition should not be null
177+
/* check function add_to_pathman_config() -- PHASE #1 */
178+
SELECT add_to_pathman_config('calamity.part_test', NULL);
179+
ERROR: attname should not be null
180+
SELECT add_to_pathman_config('calamity.part_test', 'val');
181+
add_to_pathman_config
182+
-----------------------
183+
t
184+
(1 row)
185+
186+
SELECT disable_pathman_for('calamity.part_test');
187+
NOTICE: function calamity.part_test_upd_trig_func() does not exist, skipping
188+
disable_pathman_for
189+
---------------------
190+
191+
(1 row)
192+
193+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
194+
add_to_pathman_config
195+
-----------------------
196+
t
197+
(1 row)
198+
199+
SELECT disable_pathman_for('calamity.part_test');
200+
NOTICE: function calamity.part_test_upd_trig_func() does not exist, skipping
201+
disable_pathman_for
202+
---------------------
203+
204+
(1 row)
205+
206+
/* check function add_to_pathman_config() -- PHASE #2 */
207+
CREATE TABLE calamity.part_ok(val serial);
208+
INSERT INTO calamity.part_ok SELECT generate_series(1, 2);
209+
SELECT create_hash_partitions('calamity.part_ok', 'val', 4);
210+
create_hash_partitions
211+
------------------------
212+
4
213+
(1 row)
214+
215+
CREATE TABLE calamity.wrong_partition (LIKE calamity.part_test) INHERITS (calamity.part_test); /* wrong partition w\o constraints */
216+
NOTICE: merging column "val" with inherited definition
217+
SELECT add_to_pathman_config('calamity.part_test', 'val');
218+
ERROR: constraint "pathman_wrong_partition_1_check" for partition "wrong_partition" does not exist
219+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
220+
QUERY PLAN
221+
-----------------------------
222+
Append
223+
-> Seq Scan on part_ok_0
224+
-> Seq Scan on part_ok_1
225+
-> Seq Scan on part_ok_2
226+
-> Seq Scan on part_ok_3
227+
(5 rows)
228+
229+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
230+
ERROR: constraint "pathman_wrong_partition_1_check" for partition "wrong_partition" does not exist
231+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
232+
QUERY PLAN
233+
-----------------------------
234+
Append
235+
-> Seq Scan on part_ok_0
236+
-> Seq Scan on part_ok_1
237+
-> Seq Scan on part_ok_2
238+
-> Seq Scan on part_ok_3
239+
(5 rows)
240+
241+
ALTER TABLE calamity.wrong_partition
242+
ADD CONSTRAINT pathman_wrong_partition_1_check
243+
CHECK (val < 10); /* wrong constraint */
244+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
245+
ERROR: Wrong constraint format for RANGE partition "wrong_partition"
246+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
247+
QUERY PLAN
248+
-----------------------------
249+
Append
250+
-> Seq Scan on part_ok_0
251+
-> Seq Scan on part_ok_1
252+
-> Seq Scan on part_ok_2
253+
-> Seq Scan on part_ok_3
254+
(5 rows)
255+
256+
ALTER TABLE calamity.wrong_partition DROP CONSTRAINT pathman_wrong_partition_1_check;
257+
ALTER TABLE calamity.wrong_partition
258+
ADD CONSTRAINT pathman_wrong_partition_1_check
259+
CHECK (val = 1 OR val = 2); /* wrong constraint */
260+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
261+
ERROR: Wrong constraint format for RANGE partition "wrong_partition"
262+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
263+
QUERY PLAN
264+
-----------------------------
265+
Append
266+
-> Seq Scan on part_ok_0
267+
-> Seq Scan on part_ok_1
268+
-> Seq Scan on part_ok_2
269+
-> Seq Scan on part_ok_3
270+
(5 rows)
271+
272+
ALTER TABLE calamity.wrong_partition DROP CONSTRAINT pathman_wrong_partition_1_check;
273+
ALTER TABLE calamity.wrong_partition
274+
ADD CONSTRAINT pathman_wrong_partition_1_check
275+
CHECK (val >= 10 AND val = 2); /* wrong constraint */
276+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
277+
ERROR: Wrong constraint format for RANGE partition "wrong_partition"
278+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
279+
QUERY PLAN
280+
-----------------------------
281+
Append
282+
-> Seq Scan on part_ok_0
283+
-> Seq Scan on part_ok_1
284+
-> Seq Scan on part_ok_2
285+
-> Seq Scan on part_ok_3
286+
(5 rows)
287+
288+
ALTER TABLE calamity.wrong_partition DROP CONSTRAINT pathman_wrong_partition_1_check;
289+
/* check GUC variable */
290+
SHOW pg_pathman.enable;
291+
pg_pathman.enable
292+
-------------------
293+
on
294+
(1 row)
295+
296+
DROP SCHEMA calamity CASCADE;
297+
NOTICE: drop cascades to 8 other objects
298+
DROP EXTENSION pg_pathman;

‎sql/pathman_calamity.sql

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
\set VERBOSITY terse
2+
3+
CREATE EXTENSION pg_pathman;
4+
CREATE SCHEMA calamity;
5+
6+
7+
/* call for coverage test */
8+
set client_min_messages = ERROR;
9+
SELECT debug_capture();
10+
set client_min_messages = NOTICE;
11+
12+
13+
/* create table to be partitioned */
14+
CREATE TABLE calamity.part_test(val serial);
15+
16+
17+
/* check function validate_relname() */
18+
SELECT validate_relname('calamity.part_test');
19+
/* SELECT validate_relname(NULL); -- FIXME: %s */
20+
21+
/* check function get_parent_of_partition() */
22+
SELECT get_parent_of_partition('calamity.part_test');
23+
SELECT get_parent_of_partition(NULL) IS NULL;
24+
25+
/* check function get_base_type() */
26+
CREATE DOMAIN calamity.test_domain AS INT4;
27+
SELECT get_base_type('int4'::regtype);
28+
SELECT get_base_type('calamity.test_domain'::regtype);
29+
SELECT get_base_type(NULL) IS NULL;
30+
31+
/* check function get_attribute_type() */
32+
SELECT get_attribute_type('calamity.part_test', 'val');
33+
SELECT get_attribute_type('calamity.part_test', NULL) IS NULL;
34+
SELECT get_attribute_type(NULL, 'val') IS NULL;
35+
SELECT get_attribute_type(NULL, NULL) IS NULL;
36+
37+
/* check function build_check_constraint_name_attnum() */
38+
SELECT build_check_constraint_name('calamity.part_test', 1::int2);
39+
SELECT build_check_constraint_name('calamity.part_test', NULL::int2) IS NULL;
40+
SELECT build_check_constraint_name(NULL, 1::int2) IS NULL;
41+
SELECT build_check_constraint_name(NULL, NULL::int2) IS NULL;
42+
43+
/* check function build_check_constraint_name_attname() */
44+
SELECT build_check_constraint_name('calamity.part_test', 'val');
45+
SELECT build_check_constraint_name('calamity.part_test', NULL::text) IS NULL;
46+
SELECT build_check_constraint_name(NULL, 'val') IS NULL;
47+
SELECT build_check_constraint_name(NULL, NULL::text) IS NULL;
48+
49+
/* check function build_update_trigger_name() */
50+
SELECT build_update_trigger_name('calamity.part_test');
51+
SELECT build_update_trigger_name(NULL) IS NULL;
52+
53+
/* check function build_update_trigger_func_name() */
54+
SELECT build_update_trigger_func_name('calamity.part_test');
55+
SELECT build_update_trigger_func_name(NULL) IS NULL;
56+
57+
/* check invoke_on_partition_created_callback() for RANGE */
58+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, NULL::int);
59+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, 1, NULL);
60+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, 1);
61+
62+
/* check invoke_on_partition_created_callback() for HASH */
63+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', NULL);
64+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 0);
65+
SELECT invoke_on_partition_created_callback(NULL, 'calamity.part_test', 1);
66+
SELECT invoke_on_partition_created_callback('calamity.part_test', NULL, 1);
67+
68+
/* check function add_to_pathman_config() -- PHASE #1 */
69+
SELECT add_to_pathman_config('calamity.part_test', NULL);
70+
SELECT add_to_pathman_config('calamity.part_test', 'val');
71+
SELECT disable_pathman_for('calamity.part_test');
72+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
73+
SELECT disable_pathman_for('calamity.part_test');
74+
75+
76+
/* check function add_to_pathman_config() -- PHASE #2 */
77+
CREATE TABLE calamity.part_ok(val serial);
78+
INSERT INTO calamity.part_ok SELECT generate_series(1, 2);
79+
SELECT create_hash_partitions('calamity.part_ok', 'val', 4);
80+
CREATE TABLE calamity.wrong_partition (LIKE calamity.part_test) INHERITS (calamity.part_test); /* wrong partition w\o constraints */
81+
82+
SELECT add_to_pathman_config('calamity.part_test', 'val');
83+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
84+
85+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
86+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
87+
88+
ALTER TABLE calamity.wrong_partition
89+
ADD CONSTRAINT pathman_wrong_partition_1_check
90+
CHECK (val < 10); /* wrong constraint */
91+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
92+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
93+
ALTER TABLE calamity.wrong_partition DROP CONSTRAINT pathman_wrong_partition_1_check;
94+
95+
ALTER TABLE calamity.wrong_partition
96+
ADD CONSTRAINT pathman_wrong_partition_1_check
97+
CHECK (val = 1 OR val = 2); /* wrong constraint */
98+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
99+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
100+
ALTER TABLE calamity.wrong_partition DROP CONSTRAINT pathman_wrong_partition_1_check;
101+
102+
ALTER TABLE calamity.wrong_partition
103+
ADD CONSTRAINT pathman_wrong_partition_1_check
104+
CHECK (val >= 10 AND val = 2); /* wrong constraint */
105+
SELECT add_to_pathman_config('calamity.part_test', 'val', '10');
106+
EXPLAIN (COSTS OFF) SELECT * FROM calamity.part_ok; /* check that pathman is enabled */
107+
ALTER TABLE calamity.wrong_partition DROP CONSTRAINT pathman_wrong_partition_1_check;
108+
109+
/* check GUC variable */
110+
SHOW pg_pathman.enable;
111+
112+
113+
DROP SCHEMA calamity CASCADE;
114+
DROP EXTENSION pg_pathman;

‎src/pl_funcs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ invoke_on_partition_created_callback(PG_FUNCTION_ARGS)
768768
val;
769769

770770
/* If there's no callback function specified, we're done */
771-
if (cb_oid == InvalidOid)
771+
if (PG_ARGISNULL(ARG_CALLBACK) || cb_oid == InvalidOid)
772772
PG_RETURN_VOID();
773773

774774
if (PG_ARGISNULL(ARG_PARENT))
@@ -785,7 +785,7 @@ invoke_on_partition_created_callback(PG_FUNCTION_ARGS)
785785

786786
case 5:
787787
{
788-
if (PG_ARGISNULL(ARG_RANGE_START) || PG_ARGISNULL(ARG_RANGE_START))
788+
if (PG_ARGISNULL(ARG_RANGE_START) || PG_ARGISNULL(ARG_RANGE_END))
789789
elog(ERROR, "both bounds must be provided for RANGE partition");
790790

791791
part_type = PT_RANGE;

0 commit comments

Comments
 (0)
Please sign in to comment.