Skip to content

Commit ccc01a8

Browse files
committed
Merge branch 'master_pg_upgrade_bug' into rel_future_beta
2 parents 99eb0c1 + 338a2cd commit ccc01a8

File tree

9 files changed

+146
-16
lines changed

9 files changed

+146
-16
lines changed

expected/pathman_callbacks.out

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,39 @@ WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_2",
129129

130130
DROP TABLE abc CASCADE;
131131
NOTICE: drop cascades to 2 other objects
132+
/* test the temprary deletion of callback function */
133+
CREATE TABLE abc(a serial, b int);
134+
SELECT set_init_callback('abc',
135+
'callbacks.abc_on_part_created_callback');
136+
set_init_callback
137+
-------------------
138+
139+
(1 row)
140+
141+
SELECT create_range_partitions('abc', 'a', 1, 100, 2);
142+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_1", "range_max": "101", "range_min": "1", "parent_schema": "public", "partition_schema": "public"}
143+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_2", "range_max": "201", "range_min": "101", "parent_schema": "public", "partition_schema": "public"}
144+
create_range_partitions
145+
-------------------------
146+
2
147+
(1 row)
148+
149+
INSERT INTO abc VALUES (201, 0);
150+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_3", "range_max": "301", "range_min": "201", "parent_schema": "public", "partition_schema": "public"}
151+
DROP FUNCTION callbacks.abc_on_part_created_callback(jsonb);
152+
INSERT INTO abc VALUES (301, 0);
153+
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)
156+
RETURNS VOID AS $$
157+
BEGIN
158+
RAISE WARNING 'callback arg: %', args::TEXT;
159+
END
160+
$$ language plpgsql;
161+
INSERT INTO abc VALUES (301, 0);
162+
WARNING: callback arg: {"parent": "abc", "parttype": "2", "partition": "abc_5", "range_max": "401", "range_min": "301", "parent_schema": "public", "partition_schema": "public"}
163+
DROP TABLE abc CASCADE;
164+
NOTICE: drop cascades to 4 other objects
132165
DROP SCHEMA callbacks CASCADE;
133166
NOTICE: drop cascades to 2 other objects
134167
DROP EXTENSION pg_pathman CASCADE;

expected/pathman_permissions.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ SELECT * FROM pathman_config;
4141
SELECT * FROM pathman_config_params;
4242
partrel | enable_parent | auto | init_callback | spawn_using_bgw
4343
-------------------------+---------------+------+---------------+-----------------
44-
permissions.user1_table | f | t | - | f
44+
permissions.user1_table | f | t | | f
4545
(1 row)
4646

4747
/* Should fail */

hash.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ BEGIN
145145

146146
/* Fetch init_callback from 'params' table */
147147
WITH stub_callback(stub) as (values (0))
148-
SELECT coalesce(init_callback, 0::REGPROCEDURE)
148+
SELECT init_callback
149149
FROM stub_callback
150150
LEFT JOIN @extschema@.pathman_config_params AS params
151151
ON params.partrel = parent_relid

init.sql

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,24 +56,25 @@ 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 REGPROC,
59+
callback TEXT,
6060
raise_error BOOL DEFAULT TRUE)
6161
RETURNS BOOL AS 'pg_pathman', 'validate_part_callback_pl'
62-
LANGUAGE C STRICT;
62+
LANGUAGE C;
6363

6464

6565
/*
6666
* Optional parameters for partitioned tables.
6767
* partrel - regclass (relation type, stored as Oid)
6868
* enable_parent - add parent table to plan
6969
* auto - enable automatic partition creation
70-
* init_callback - cb to be executed on partition creation
70+
* init_callback - text signature of cb to be executed on partition
71+
* creation
7172
*/
7273
CREATE TABLE IF NOT EXISTS @extschema@.pathman_config_params (
7374
partrel REGCLASS NOT NULL PRIMARY KEY,
7475
enable_parent BOOLEAN NOT NULL DEFAULT FALSE,
7576
auto BOOLEAN NOT NULL DEFAULT TRUE,
76-
init_callback REGPROCEDURE NOT NULL DEFAULT 0,
77+
init_callback TEXT DEFAULT NULL,
7778
spawn_using_bgw BOOLEAN NOT NULL DEFAULT FALSE
7879

7980
CHECK (@extschema@.validate_part_callback(init_callback)) /* check signature */
@@ -140,7 +141,7 @@ BEGIN
140141
USING relation, value;
141142
END
142143
$$
143-
LANGUAGE plpgsql STRICT;
144+
LANGUAGE plpgsql;
144145

145146
/*
146147
* Include\exclude parent relation in query plan.
@@ -178,8 +179,25 @@ CREATE OR REPLACE FUNCTION @extschema@.set_init_callback(
178179
callback REGPROC DEFAULT 0)
179180
RETURNS VOID AS
180181
$$
182+
DECLARE
183+
regproc_text TEXT := NULL;
184+
181185
BEGIN
182-
PERFORM @extschema@.pathman_set_param(relation, 'init_callback', callback);
186+
187+
/* Fetch schema-qualified name of callback */
188+
IF callback != 0 THEN
189+
SELECT quote_ident(nspname) || '.' ||
190+
quote_ident(proname) || '(' ||
191+
(SELECT string_agg(x.argtype::REGTYPE::TEXT, ',')
192+
FROM unnest(proargtypes) AS x(argtype)) ||
193+
')'
194+
FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n
195+
ON n.oid = p.pronamespace
196+
WHERE p.oid = callback
197+
INTO regproc_text; /* <= result */
198+
END IF;
199+
200+
PERFORM @extschema@.pathman_set_param(relation, 'init_callback', regproc_text);
183201
END
184202
$$
185203
LANGUAGE plpgsql STRICT;

range.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ BEGIN
946946

947947
/* Fetch init_callback from 'params' table */
948948
WITH stub_callback(stub) as (values (0))
949-
SELECT coalesce(init_callback, 0::REGPROCEDURE)
949+
SELECT init_callback
950950
FROM stub_callback
951951
LEFT JOIN @extschema@.pathman_config_params AS params
952952
ON params.partrel = parent_relid

sql/pathman_callbacks.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,26 @@ SELECT create_range_partitions('abc', 'a', 1, 100, 2);
5353

5454
DROP TABLE abc CASCADE;
5555

56+
/* test the temprary deletion of callback function */
57+
CREATE TABLE abc(a serial, b int);
58+
SELECT set_init_callback('abc',
59+
'callbacks.abc_on_part_created_callback');
60+
SELECT create_range_partitions('abc', 'a', 1, 100, 2);
61+
62+
INSERT INTO abc VALUES (201, 0);
63+
DROP FUNCTION callbacks.abc_on_part_created_callback(jsonb);
64+
INSERT INTO abc VALUES (301, 0);
65+
CREATE OR REPLACE FUNCTION callbacks.abc_on_part_created_callback(
66+
args JSONB)
67+
RETURNS VOID AS $$
68+
BEGIN
69+
RAISE WARNING 'callback arg: %', args::TEXT;
70+
END
71+
$$ language plpgsql;
72+
INSERT INTO abc VALUES (301, 0);
73+
74+
DROP TABLE abc CASCADE;
75+
76+
5677
DROP SCHEMA callbacks CASCADE;
5778
DROP EXTENSION pg_pathman CASCADE;

src/init.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,6 @@ read_pathman_params(Oid relid, Datum *values, bool *isnull)
782782
Assert(!isnull[Anum_pathman_config_params_partrel - 1]);
783783
Assert(!isnull[Anum_pathman_config_params_enable_parent - 1]);
784784
Assert(!isnull[Anum_pathman_config_params_auto - 1]);
785-
Assert(!isnull[Anum_pathman_config_params_init_callback - 1]);
786785
Assert(!isnull[Anum_pathman_config_params_spawn_using_bgw - 1]);
787786
}
788787

src/partition_creation.c

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ static ObjectAddress create_table_using_stmt(CreateStmt *create_stmt,
7474
static void copy_foreign_keys(Oid parent_relid, Oid partition_oid);
7575
static void postprocess_child_table_and_atts(Oid parent_relid, Oid partition_relid);
7676

77+
static Oid text_to_regprocedure(text *proname_args);
78+
7779
static Constraint *make_constraint_common(char *name, Node *raw_expr);
7880

7981
static Value make_string_value_struct(char *str);
@@ -406,13 +408,20 @@ create_partitions_for_value_internal(Oid relid, Datum value, Oid value_type)
406408
{
407409
ErrorData *edata;
408410

411+
/* Simply rethrow ERROR if we're in backend */
412+
if (!IsBackgroundWorker)
413+
PG_RE_THROW();
414+
409415
/* Switch to the original context & copy edata */
410416
MemoryContextSwitchTo(old_mcxt);
411417
edata = CopyErrorData();
412418
FlushErrorState();
413419

414-
elog(LOG, "create_partitions_internal(): %s [%u]",
415-
edata->message, MyProcPid);
420+
/* Produce log message if we're in BGW */
421+
ereport(LOG,
422+
(errmsg(CppAsString(create_partitions_for_value_internal) ": %s [%u]",
423+
edata->message, MyProcPid),
424+
(edata->detail) ? errdetail("%s", edata->detail) : 0));
416425

417426
FreeErrorData(edata);
418427

@@ -1466,14 +1475,26 @@ invoke_init_callback_internal(init_callback_params *cb_params)
14661475
/* Search for init_callback entry in PATHMAN_CONFIG_PARAMS */
14671476
if (read_pathman_params(parent_oid, param_values, param_isnull))
14681477
{
1469-
Datum init_cb_datum; /* Oid of init_callback */
1478+
Datum init_cb_datum; /* signature of init_callback */
14701479
AttrNumber init_cb_attno = Anum_pathman_config_params_init_callback;
14711480

1472-
/* Extract Datum storing callback's Oid */
1481+
/* Extract Datum storing callback's signature */
14731482
init_cb_datum = param_values[init_cb_attno - 1];
14741483

14751484
/* Cache init_callback's Oid */
1476-
cb_params->callback = DatumGetObjectId(init_cb_datum);
1485+
if (init_cb_datum)
1486+
{
1487+
/* Try fetching callback's Oid */
1488+
cb_params->callback = text_to_regprocedure(DatumGetTextP(init_cb_datum));
1489+
1490+
if (!RegProcedureIsValid(cb_params->callback))
1491+
ereport(ERROR,
1492+
(errcode(ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION),
1493+
errmsg("callback function \"%s\" does not exist",
1494+
TextDatumGetCString(init_cb_datum))));
1495+
}
1496+
else
1497+
cb_params->callback = InvalidOid;
14771498
cb_params->callback_is_cached = true;
14781499
}
14791500
}
@@ -1619,3 +1640,31 @@ validate_part_callback(Oid procid, bool emit_error)
16191640

16201641
return is_ok;
16211642
}
1643+
1644+
/*
1645+
* Utility function that converts signature of procedure into regprocedure.
1646+
*
1647+
* Precondition: proc_signature != NULL.
1648+
*
1649+
* Returns InvalidOid if proname_args is not found.
1650+
* Raise error if it's incorrect.
1651+
*/
1652+
static Oid
1653+
text_to_regprocedure(text *proc_signature)
1654+
{
1655+
FunctionCallInfoData fcinfo;
1656+
Datum result;
1657+
1658+
InitFunctionCallInfoData(fcinfo, NULL, 1, InvalidOid, NULL, NULL);
1659+
1660+
#if PG_VERSION_NUM >= 90600
1661+
fcinfo.arg[0] = PointerGetDatum(proc_signature);
1662+
#else
1663+
fcinfo.arg[0] = CStringGetDatum(text_to_cstring(proc_signature));
1664+
#endif
1665+
fcinfo.argnull[0] = false;
1666+
1667+
result = to_regprocedure(&fcinfo);
1668+
1669+
return DatumGetObjectId(result);
1670+
}

src/pl_funcs.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,17 @@ prevent_relation_modification(PG_FUNCTION_ARGS)
792792
Datum
793793
validate_part_callback_pl(PG_FUNCTION_ARGS)
794794
{
795-
PG_RETURN_BOOL(validate_part_callback(PG_GETARG_OID(0), PG_GETARG_BOOL(1)));
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)));
796806
}
797807

798808
/*

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