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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy