Skip to content

Commit 0116da3

Browse files
committed
improved init callback API, tests
1 parent ccc01a8 commit 0116da3

File tree

7 files changed

+120
-36
lines changed

7 files changed

+120
-36
lines changed

expected/pathman_callbacks.out

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
CREATE EXTENSION pg_pathman;
33
CREATE SCHEMA callbacks;
44
/* Check callbacks */
5-
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(
6-
args JSONB)
5+
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(args JSONB)
76
RETURNS VOID AS $$
87
BEGIN
98
RAISE WARNING 'callback arg: %', args::TEXT;
109
END
1110
$$ language plpgsql;
12-
/* set callback to be called on RANGE partitions */
11+
/* callback is in public namespace, must be schema-qualified */
12+
CREATE OR REPLACE FUNCTION public.dummy_cb(args JSONB)
13+
RETURNS VOID AS $$
14+
BEGIN
15+
END
16+
$$ language plpgsql;
1317
CREATE TABLE callbacks.abc(a serial, b int);
1418
SELECT create_range_partitions('callbacks.abc', 'a', 1, 100, 2);
1519
NOTICE: sequence "abc_seq" does not exist, skipping
@@ -18,8 +22,62 @@ NOTICE: sequence "abc_seq" does not exist, skipping
1822
2
1923
(1 row)
2024

25+
SELECT set_init_callback('callbacks.abc', 'public.dummy_cb(jsonb)');
26+
set_init_callback
27+
-------------------
28+
29+
(1 row)
30+
31+
/* check that callback is schema-qualified */
32+
SELECT init_callback FROM pathman_config_params
33+
WHERE partrel = 'callbacks.abc'::REGCLASS;
34+
init_callback
35+
------------------------
36+
public.dummy_cb(jsonb)
37+
(1 row)
38+
39+
/* reset callback */
40+
SELECT set_init_callback('callbacks.abc');
41+
set_init_callback
42+
-------------------
43+
44+
(1 row)
45+
46+
/* should return NULL */
47+
SELECT init_callback FROM pathman_config_params
48+
WHERE partrel = 'callbacks.abc'::REGCLASS;
49+
init_callback
50+
---------------
51+
52+
(1 row)
53+
54+
SELECT set_init_callback('callbacks.abc',
55+
'callbacks.abc_on_part_created_callback(jsonb)');
56+
set_init_callback
57+
-------------------
58+
59+
(1 row)
60+
61+
/* check that callback is schema-qualified */
62+
SELECT init_callback FROM pathman_config_params
63+
WHERE partrel = 'callbacks.abc'::REGCLASS;
64+
init_callback
65+
-----------------------------------------------
66+
callbacks.abc_on_part_created_callback(jsonb)
67+
(1 row)
68+
69+
DROP TABLE callbacks.abc CASCADE;
70+
NOTICE: drop cascades to 2 other objects
71+
/* set callback to be called on RANGE partitions */
72+
CREATE TABLE callbacks.abc(a serial, b int);
73+
SELECT create_range_partitions('callbacks.abc', 'a', 1, 100, 2);
74+
create_range_partitions
75+
-------------------------
76+
2
77+
(1 row)
78+
2179
SELECT set_init_callback('callbacks.abc',
22-
'callbacks.abc_on_part_created_callback');
80+
'callbacks.abc_on_part_created_callback(jsonb)');
2381
set_init_callback
2482
-------------------
2583

@@ -90,7 +148,7 @@ NOTICE: 0 rows copied from callbacks.abc_7
90148

91149
/* set callback to be called on HASH partitions */
92150
SELECT set_init_callback('callbacks.abc',
93-
'callbacks.abc_on_part_created_callback');
151+
'callbacks.abc_on_part_created_callback(jsonb)');
94152
set_init_callback
95153
-------------------
96154

@@ -112,7 +170,7 @@ NOTICE: drop cascades to 5 other objects
112170
/* create table in public schema */
113171
CREATE TABLE abc(a serial, b int);
114172
SELECT set_init_callback('abc',
115-
'callbacks.abc_on_part_created_callback');
173+
'callbacks.abc_on_part_created_callback(jsonb)');
116174
set_init_callback
117175
-------------------
118176

@@ -132,7 +190,7 @@ NOTICE: drop cascades to 2 other objects
132190
/* test the temprary deletion of callback function */
133191
CREATE TABLE abc(a serial, b int);
134192
SELECT set_init_callback('abc',
135-
'callbacks.abc_on_part_created_callback');
193+
'callbacks.abc_on_part_created_callback(jsonb)');
136194
set_init_callback
137195
-------------------
138196

@@ -151,8 +209,7 @@ WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_3",
151209
DROP FUNCTION callbacks.abc_on_part_created_callback(jsonb);
152210
INSERT INTO abc VALUES (301, 0);
153211
ERROR: callback function "callbacks.abc_on_part_created_callback(jsonb)" does not exist
154-
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(
155-
args JSONB)
212+
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(args JSONB)
156213
RETURNS VOID AS $$
157214
BEGIN
158215
RAISE WARNING 'callback arg: %', args::TEXT;

expected/pathman_inserts.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ BEGIN
4040
EXECUTE format('create trigger print_new_row_after_insert after insert on %s.%s for each row execute procedure test_inserts.print_cols_after_change();', args->>'partition_schema', args->>'partition');
4141
END;
4242
$$ LANGUAGE plpgsql;
43-
SELECT set_init_callback('test_inserts.storage', 'test_inserts.set_triggers');
43+
SELECT set_init_callback('test_inserts.storage', 'test_inserts.set_triggers(jsonb)');
4444
set_init_callback
4545
-------------------
4646

init.sql

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ CREATE TABLE IF NOT EXISTS @extschema@.pathman_config (
5656
* NOTE: this function is used in CHECK CONSTRAINT.
5757
*/
5858
CREATE OR REPLACE FUNCTION @extschema@.validate_part_callback(
59-
callback TEXT,
59+
callback REGPROCEDURE,
6060
raise_error BOOL DEFAULT TRUE)
6161
RETURNS BOOL AS 'pg_pathman', 'validate_part_callback_pl'
62-
LANGUAGE C;
62+
LANGUAGE C STRICT;
6363

6464

6565
/*
@@ -77,7 +77,11 @@ CREATE TABLE IF NOT EXISTS @extschema@.pathman_config_params (
7777
init_callback TEXT DEFAULT NULL,
7878
spawn_using_bgw BOOLEAN NOT NULL DEFAULT FALSE
7979

80-
CHECK (@extschema@.validate_part_callback(init_callback)) /* check signature */
80+
/* check callback's signature */
81+
CHECK (@extschema@.validate_part_callback(CASE WHEN init_callback IS NULL
82+
THEN 0::REGPROCEDURE
83+
ELSE init_callback::REGPROCEDURE
84+
END))
8185
);
8286

8387
GRANT SELECT, INSERT, UPDATE, DELETE
@@ -176,7 +180,7 @@ LANGUAGE plpgsql STRICT;
176180
*/
177181
CREATE OR REPLACE FUNCTION @extschema@.set_init_callback(
178182
relation REGCLASS,
179-
callback REGPROC DEFAULT 0)
183+
callback REGPROCEDURE DEFAULT 0)
180184
RETURNS VOID AS
181185
$$
182186
DECLARE

sql/pathman_callbacks.sql

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,54 @@ CREATE SCHEMA callbacks;
55

66
/* Check callbacks */
77

8-
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(
9-
args JSONB)
8+
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(args JSONB)
109
RETURNS VOID AS $$
1110
BEGIN
1211
RAISE WARNING 'callback arg: %', args::TEXT;
1312
END
1413
$$ language plpgsql;
1514

1615

16+
17+
/* callback is in public namespace, must be schema-qualified */
18+
CREATE OR REPLACE FUNCTION public.dummy_cb(args JSONB)
19+
RETURNS VOID AS $$
20+
BEGIN
21+
END
22+
$$ language plpgsql;
23+
24+
CREATE TABLE callbacks.abc(a serial, b int);
25+
SELECT create_range_partitions('callbacks.abc', 'a', 1, 100, 2);
26+
27+
SELECT set_init_callback('callbacks.abc', 'public.dummy_cb(jsonb)');
28+
29+
/* check that callback is schema-qualified */
30+
SELECT init_callback FROM pathman_config_params
31+
WHERE partrel = 'callbacks.abc'::REGCLASS;
32+
33+
/* reset callback */
34+
SELECT set_init_callback('callbacks.abc');
35+
36+
/* should return NULL */
37+
SELECT init_callback FROM pathman_config_params
38+
WHERE partrel = 'callbacks.abc'::REGCLASS;
39+
40+
SELECT set_init_callback('callbacks.abc',
41+
'callbacks.abc_on_part_created_callback(jsonb)');
42+
43+
/* check that callback is schema-qualified */
44+
SELECT init_callback FROM pathman_config_params
45+
WHERE partrel = 'callbacks.abc'::REGCLASS;
46+
47+
DROP TABLE callbacks.abc CASCADE;
48+
49+
1750
/* set callback to be called on RANGE partitions */
1851
CREATE TABLE callbacks.abc(a serial, b int);
1952
SELECT create_range_partitions('callbacks.abc', 'a', 1, 100, 2);
2053

2154
SELECT set_init_callback('callbacks.abc',
22-
'callbacks.abc_on_part_created_callback');
55+
'callbacks.abc_on_part_created_callback(jsonb)');
2356

2457
INSERT INTO callbacks.abc VALUES (123, 1);
2558
INSERT INTO callbacks.abc VALUES (223, 1); /* show warning */
@@ -40,30 +73,29 @@ SELECT drop_partitions('callbacks.abc');
4073

4174
/* set callback to be called on HASH partitions */
4275
SELECT set_init_callback('callbacks.abc',
43-
'callbacks.abc_on_part_created_callback');
76+
'callbacks.abc_on_part_created_callback(jsonb)');
4477
SELECT create_hash_partitions('callbacks.abc', 'a', 5);
4578

4679
DROP TABLE callbacks.abc CASCADE;
4780

4881
/* create table in public schema */
4982
CREATE TABLE abc(a serial, b int);
5083
SELECT set_init_callback('abc',
51-
'callbacks.abc_on_part_created_callback');
84+
'callbacks.abc_on_part_created_callback(jsonb)');
5285
SELECT create_range_partitions('abc', 'a', 1, 100, 2);
5386

5487
DROP TABLE abc CASCADE;
5588

5689
/* test the temprary deletion of callback function */
5790
CREATE TABLE abc(a serial, b int);
5891
SELECT set_init_callback('abc',
59-
'callbacks.abc_on_part_created_callback');
92+
'callbacks.abc_on_part_created_callback(jsonb)');
6093
SELECT create_range_partitions('abc', 'a', 1, 100, 2);
6194

6295
INSERT INTO abc VALUES (201, 0);
6396
DROP FUNCTION callbacks.abc_on_part_created_callback(jsonb);
6497
INSERT INTO abc VALUES (301, 0);
65-
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(
66-
args JSONB)
98+
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(args JSONB)
6799
RETURNS VOID AS $$
68100
BEGIN
69101
RAISE WARNING 'callback arg: %', args::TEXT;

sql/pathman_inserts.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ BEGIN
3838
EXECUTE format('create trigger print_new_row_after_insert after insert on %s.%s for each row execute procedure test_inserts.print_cols_after_change();', args->>'partition_schema', args->>'partition');
3939
END;
4040
$$ LANGUAGE plpgsql;
41-
SELECT set_init_callback('test_inserts.storage', 'test_inserts.set_triggers');
41+
SELECT set_init_callback('test_inserts.storage', 'test_inserts.set_triggers(jsonb)');
4242

4343
/* we don't support ON CONLICT */
4444
INSERT INTO test_inserts.storage VALUES(0, 0, 0, 'UNSUPPORTED_1')

src/partition_creation.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,7 +1622,7 @@ validate_part_callback(Oid procid, bool emit_error)
16221622

16231623
tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(procid));
16241624
if (!HeapTupleIsValid(tp))
1625-
elog(ERROR, "cache lookup failed for function %u", procid);
1625+
elog(ERROR, "callback function %u does not exist", procid);
16261626

16271627
functup = (Form_pg_proc) GETSTRUCT(tp);
16281628

@@ -1635,7 +1635,7 @@ validate_part_callback(Oid procid, bool emit_error)
16351635

16361636
if (emit_error && !is_ok)
16371637
elog(ERROR,
1638-
"Callback function must have the following signature: "
1638+
"callback function must have the following signature: "
16391639
"callback(arg JSONB) RETURNS VOID");
16401640

16411641
return is_ok;

src/pl_funcs.c

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -792,17 +792,8 @@ prevent_relation_modification(PG_FUNCTION_ARGS)
792792
Datum
793793
validate_part_callback_pl(PG_FUNCTION_ARGS)
794794
{
795-
const char *cb_cstring;
796-
Oid cb_oid;
797-
798-
if (PG_ARGISNULL(0))
799-
PG_RETURN_BOOL(true);
800-
801-
cb_cstring = text_to_cstring(PG_GETARG_TEXT_P(0));
802-
cb_oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
803-
CStringGetDatum(cb_cstring)));
804-
805-
PG_RETURN_BOOL(validate_part_callback(cb_oid, PG_GETARG_BOOL(1)));
795+
PG_RETURN_BOOL(validate_part_callback(PG_GETARG_OID(0),
796+
PG_GETARG_BOOL(1)));
806797
}
807798

808799
/*

0 commit comments

Comments
 (0)