Skip to content

Commit 1d5bbba

Browse files
committed
Merge commit '369b49d35fb59f24989abedc5c48e0b8c98bbfb2' into PGPRO9_6_pathman
2 parents 867b37f + 369b49d commit 1d5bbba

File tree

8 files changed

+150
-70
lines changed

8 files changed

+150
-70
lines changed

contrib/pg_pathman/expected/pathman_calamity.out

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ SELECT debug_capture();
99

1010
(1 row)
1111

12+
SELECT get_pathman_lib_version();
13+
get_pathman_lib_version
14+
-------------------------
15+
10300
16+
(1 row)
17+
1218
set client_min_messages = NOTICE;
1319
/* create table to be partitioned */
1420
CREATE TABLE calamity.part_test(val serial);
@@ -396,30 +402,69 @@ SELECT drop_range_partition_expand_next(NULL) IS NULL;
396402
t
397403
(1 row)
398404

399-
/* check invoke_on_partition_created_callback() for RANGE */
400-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, NULL::int);
401-
ERROR: both bounds must be provided for RANGE partition
402-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, 1, NULL);
403-
ERROR: both bounds must be provided for RANGE partition
404-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, 1);
405-
ERROR: both bounds must be provided for RANGE partition
406-
/* check invoke_on_partition_created_callback() for HASH */
405+
/* check invoke_on_partition_created_callback() */
406+
CREATE FUNCTION calamity.dummy_cb(arg jsonb) RETURNS void AS $$
407+
begin
408+
raise warning 'arg: %', arg::text;
409+
end
410+
$$ LANGUAGE plpgsql;
411+
/* Invalid args */
412+
SELECT invoke_on_partition_created_callback(NULL, 'calamity.part_test', 1);
413+
ERROR: 'parent_relid' should not be NULL
414+
SELECT invoke_on_partition_created_callback('calamity.part_test', NULL, 1);
415+
ERROR: 'partition' should not be NULL
416+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 0);
417+
invoke_on_partition_created_callback
418+
--------------------------------------
419+
420+
(1 row)
421+
422+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1);
423+
ERROR: callback function 1 does not exist
407424
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', NULL);
408425
invoke_on_partition_created_callback
409426
--------------------------------------
410427

411428
(1 row)
412429

413-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 0);
430+
/* HASH */
431+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure);
432+
WARNING: arg: {"parent": null, "parttype": "1", "partition": null, "parent_schema": null, "partition_schema": null}
414433
invoke_on_partition_created_callback
415434
--------------------------------------
416435

417436
(1 row)
418437

419-
SELECT invoke_on_partition_created_callback(NULL, 'calamity.part_test', 1);
420-
ERROR: 'parent_relid' should not be NULL
421-
SELECT invoke_on_partition_created_callback('calamity.part_test', NULL, 1);
422-
ERROR: 'partition' should not be NULL
438+
/* RANGE */
439+
SELECT invoke_on_partition_created_callback('calamity.part_test'::regclass, 'pg_class'::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, NULL::int, NULL);
440+
WARNING: arg: {"parent": "part_test", "parttype": "2", "partition": "pg_class", "range_max": null, "range_min": null, "parent_schema": "calamity", "partition_schema": "pg_catalog"}
441+
invoke_on_partition_created_callback
442+
--------------------------------------
443+
444+
(1 row)
445+
446+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, NULL::int, NULL);
447+
WARNING: arg: {"parent": null, "parttype": "2", "partition": null, "range_max": null, "range_min": null, "parent_schema": null, "partition_schema": null}
448+
invoke_on_partition_created_callback
449+
--------------------------------------
450+
451+
(1 row)
452+
453+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, 1, NULL);
454+
WARNING: arg: {"parent": null, "parttype": "2", "partition": null, "range_max": null, "range_min": "1", "parent_schema": null, "partition_schema": null}
455+
invoke_on_partition_created_callback
456+
--------------------------------------
457+
458+
(1 row)
459+
460+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, NULL, 1);
461+
WARNING: arg: {"parent": null, "parttype": "2", "partition": null, "range_max": "1", "range_min": null, "parent_schema": null, "partition_schema": null}
462+
invoke_on_partition_created_callback
463+
--------------------------------------
464+
465+
(1 row)
466+
467+
DROP FUNCTION calamity.dummy_cb(arg jsonb);
423468
/* check function add_to_pathman_config() -- PHASE #1 */
424469
SELECT add_to_pathman_config(NULL, 'val'); /* no table */
425470
ERROR: 'parent_relid' should not be NULL

contrib/pg_pathman/sql/pathman_calamity.sql

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CREATE SCHEMA calamity;
77
/* call for coverage test */
88
set client_min_messages = ERROR;
99
SELECT debug_capture();
10+
SELECT get_pathman_lib_version();
1011
set client_min_messages = NOTICE;
1112

1213

@@ -153,16 +154,32 @@ SELECT stop_concurrent_part_task(1::regclass);
153154
SELECT drop_range_partition_expand_next('pg_class');
154155
SELECT drop_range_partition_expand_next(NULL) IS NULL;
155156

156-
/* check invoke_on_partition_created_callback() for RANGE */
157-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, NULL::int);
158-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, 1, NULL);
159-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1, NULL, 1);
160157

161-
/* check invoke_on_partition_created_callback() for HASH */
162-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', NULL);
163-
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 0);
158+
/* check invoke_on_partition_created_callback() */
159+
CREATE FUNCTION calamity.dummy_cb(arg jsonb) RETURNS void AS $$
160+
begin
161+
raise warning 'arg: %', arg::text;
162+
end
163+
$$ LANGUAGE plpgsql;
164+
165+
/* Invalid args */
164166
SELECT invoke_on_partition_created_callback(NULL, 'calamity.part_test', 1);
165167
SELECT invoke_on_partition_created_callback('calamity.part_test', NULL, 1);
168+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 0);
169+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', 1);
170+
SELECT invoke_on_partition_created_callback('calamity.part_test', 'calamity.part_test', NULL);
171+
172+
/* HASH */
173+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure);
174+
175+
/* RANGE */
176+
SELECT invoke_on_partition_created_callback('calamity.part_test'::regclass, 'pg_class'::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, NULL::int, NULL);
177+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, NULL::int, NULL);
178+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, 1, NULL);
179+
SELECT invoke_on_partition_created_callback(0::regclass, 1::regclass, 'calamity.dummy_cb(jsonb)'::regprocedure, NULL, 1);
180+
181+
DROP FUNCTION calamity.dummy_cb(arg jsonb);
182+
166183

167184
/* check function add_to_pathman_config() -- PHASE #1 */
168185
SELECT add_to_pathman_config(NULL, 'val'); /* no table */

contrib/pg_pathman/src/hooks.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,11 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
468468

469469
PlannedStmt *result;
470470
uint32 query_id = parse->queryId;
471+
bool pathman_ready = IsPathmanReady(); /* in case it changes */
471472

472473
PG_TRY();
473474
{
474-
if (IsPathmanReady())
475+
if (pathman_ready)
475476
{
476477
/* Increment parenthood_statuses refcount */
477478
incr_refcount_parenthood_statuses();
@@ -486,7 +487,7 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
486487
else
487488
result = standard_planner(parse, cursorOptions, boundParams);
488489

489-
if (IsPathmanReady())
490+
if (pathman_ready)
490491
{
491492
/* Give rowmark-related attributes correct names */
492493
ExecuteForPlanTree(result, postprocess_lock_rows);
@@ -504,9 +505,13 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
504505
/* We must decrease parenthood statuses refcount on ERROR */
505506
PG_CATCH();
506507
{
507-
/* Caught an ERROR, decrease refcount */
508-
decr_refcount_parenthood_statuses();
508+
if (pathman_ready)
509+
{
510+
/* Caught an ERROR, decrease refcount */
511+
decr_refcount_parenthood_statuses();
512+
}
509513

514+
/* Rethrow ERROR further */
510515
PG_RE_THROW();
511516
}
512517
PG_END_TRY();

contrib/pg_pathman/src/partition_creation.c

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ create_partitions_for_value(Oid relid, Datum value, Oid value_type)
270270
elog(DEBUG2, "create_partitions(): chose backend [%u]", MyProcPid);
271271
last_partition = create_partitions_for_value_internal(relid,
272272
value,
273-
value_type);
273+
value_type,
274+
false); /* backend */
274275
}
275276
}
276277
else
@@ -299,7 +300,8 @@ create_partitions_for_value(Oid relid, Datum value, Oid value_type)
299300
* use create_partitions_for_value() instead.
300301
*/
301302
Oid
302-
create_partitions_for_value_internal(Oid relid, Datum value, Oid value_type)
303+
create_partitions_for_value_internal(Oid relid, Datum value, Oid value_type,
304+
bool is_background_worker)
303305
{
304306
MemoryContext old_mcxt = CurrentMemoryContext;
305307
Oid partid = InvalidOid; /* last created partition (or InvalidOid) */
@@ -405,7 +407,7 @@ create_partitions_for_value_internal(Oid relid, Datum value, Oid value_type)
405407
ErrorData *edata;
406408

407409
/* Simply rethrow ERROR if we're in backend */
408-
if (!IsBackgroundWorker)
410+
if (!is_background_worker)
409411
PG_RE_THROW();
410412

411413
/* Switch to the original context & copy edata */
@@ -1422,15 +1424,18 @@ invoke_init_callback_internal(init_callback_params *cb_params)
14221424
{
14231425
#define JSB_INIT_VAL(value, val_type, val_cstring) \
14241426
do { \
1425-
(value)->type = jbvString; \
1426-
(value)->val.string.len = strlen(val_cstring); \
1427-
(value)->val.string.val = val_cstring; \
1428-
pushJsonbValue(&jsonb_state, val_type, (value)); \
1429-
} while (0)
1430-
1431-
#define JSB_INIT_NULL_VAL(value, val_type) \
1432-
do { \
1433-
(value)->type = jbvNull; \
1427+
if ((val_cstring) != NULL) \
1428+
{ \
1429+
(value)->type = jbvString; \
1430+
(value)->val.string.len = strlen(val_cstring); \
1431+
(value)->val.string.val = val_cstring; \
1432+
} \
1433+
else \
1434+
{ \
1435+
(value)->type = jbvNull; \
1436+
Assert((val_type) != WJB_KEY); \
1437+
} \
1438+
\
14341439
pushJsonbValue(&jsonb_state, val_type, (value)); \
14351440
} while (0)
14361441

@@ -1445,6 +1450,12 @@ invoke_init_callback_internal(init_callback_params *cb_params)
14451450
key,
14461451
val;
14471452

1453+
char *parent_name,
1454+
*parent_namespace,
1455+
*partition_name,
1456+
*partition_namespace;
1457+
1458+
14481459
/* Fetch & cache callback's Oid if needed */
14491460
if (!cb_params->callback_is_cached)
14501461
{
@@ -1472,8 +1483,10 @@ invoke_init_callback_internal(init_callback_params *cb_params)
14721483
errmsg("callback function \"%s\" does not exist",
14731484
TextDatumGetCString(init_cb_datum))));
14741485
}
1475-
else
1476-
cb_params->callback = InvalidOid;
1486+
/* There's no callback */
1487+
else cb_params->callback = InvalidOid;
1488+
1489+
/* We've made a lookup */
14771490
cb_params->callback_is_cached = true;
14781491
}
14791492
}
@@ -1485,6 +1498,12 @@ invoke_init_callback_internal(init_callback_params *cb_params)
14851498
/* Validate the callback's signature */
14861499
validate_part_callback(cb_params->callback, true);
14871500

1501+
parent_name = get_rel_name(parent_oid);
1502+
parent_namespace = get_namespace_name(get_rel_namespace(parent_oid));
1503+
1504+
partition_name = get_rel_name(partition_oid);
1505+
partition_namespace = get_namespace_name(get_rel_namespace(partition_oid));
1506+
14881507
/* Generate JSONB we're going to pass to callback */
14891508
switch (cb_params->parttype)
14901509
{
@@ -1493,13 +1512,13 @@ invoke_init_callback_internal(init_callback_params *cb_params)
14931512
pushJsonbValue(&jsonb_state, WJB_BEGIN_OBJECT, NULL);
14941513

14951514
JSB_INIT_VAL(&key, WJB_KEY, "parent");
1496-
JSB_INIT_VAL(&val, WJB_VALUE, get_rel_name_or_relid(parent_oid));
1515+
JSB_INIT_VAL(&val, WJB_VALUE, parent_name);
14971516
JSB_INIT_VAL(&key, WJB_KEY, "parent_schema");
1498-
JSB_INIT_VAL(&val, WJB_VALUE, get_namespace_name(get_rel_namespace(parent_oid)));
1517+
JSB_INIT_VAL(&val, WJB_VALUE, parent_namespace);
14991518
JSB_INIT_VAL(&key, WJB_KEY, "partition");
1500-
JSB_INIT_VAL(&val, WJB_VALUE, get_rel_name_or_relid(partition_oid));
1519+
JSB_INIT_VAL(&val, WJB_VALUE, partition_name);
15011520
JSB_INIT_VAL(&key, WJB_KEY, "partition_schema");
1502-
JSB_INIT_VAL(&val, WJB_VALUE, get_namespace_name(get_rel_namespace(partition_oid)));
1521+
JSB_INIT_VAL(&val, WJB_VALUE, partition_namespace);
15031522
JSB_INIT_VAL(&key, WJB_KEY, "parttype");
15041523
JSB_INIT_VAL(&val, WJB_VALUE, PartTypeToCString(PT_HASH));
15051524

@@ -1509,46 +1528,40 @@ invoke_init_callback_internal(init_callback_params *cb_params)
15091528

15101529
case PT_RANGE:
15111530
{
1512-
char *start_value,
1513-
*end_value;
1531+
char *start_value = NULL,
1532+
*end_value = NULL;
15141533
Bound sv_datum = cb_params->params.range_params.start_value,
15151534
ev_datum = cb_params->params.range_params.end_value;
15161535
Oid type = cb_params->params.range_params.value_type;
15171536

1537+
/* Convert min to CSTRING */
1538+
if (!IsInfinite(&sv_datum))
1539+
start_value = datum_to_cstring(BoundGetValue(&sv_datum), type);
1540+
1541+
/* Convert max to CSTRING */
1542+
if (!IsInfinite(&ev_datum))
1543+
end_value = datum_to_cstring(BoundGetValue(&ev_datum), type);
1544+
15181545
pushJsonbValue(&jsonb_state, WJB_BEGIN_OBJECT, NULL);
15191546

15201547
JSB_INIT_VAL(&key, WJB_KEY, "parent");
1521-
JSB_INIT_VAL(&val, WJB_VALUE, get_rel_name_or_relid(parent_oid));
1548+
JSB_INIT_VAL(&val, WJB_VALUE, parent_name);
15221549
JSB_INIT_VAL(&key, WJB_KEY, "parent_schema");
1523-
JSB_INIT_VAL(&val, WJB_VALUE, get_namespace_name(get_rel_namespace(parent_oid)));
1550+
JSB_INIT_VAL(&val, WJB_VALUE, parent_namespace);
15241551
JSB_INIT_VAL(&key, WJB_KEY, "partition");
1525-
JSB_INIT_VAL(&val, WJB_VALUE, get_rel_name_or_relid(partition_oid));
1552+
JSB_INIT_VAL(&val, WJB_VALUE, partition_name);
15261553
JSB_INIT_VAL(&key, WJB_KEY, "partition_schema");
1527-
JSB_INIT_VAL(&val, WJB_VALUE, get_namespace_name(get_rel_namespace(partition_oid)));
1554+
JSB_INIT_VAL(&val, WJB_VALUE, partition_namespace);
15281555
JSB_INIT_VAL(&key, WJB_KEY, "parttype");
15291556
JSB_INIT_VAL(&val, WJB_VALUE, PartTypeToCString(PT_RANGE));
15301557

15311558
/* Lower bound */
15321559
JSB_INIT_VAL(&key, WJB_KEY, "range_min");
1533-
if (!IsInfinite(&sv_datum))
1534-
{
1535-
/* Convert min to CSTRING */
1536-
start_value = datum_to_cstring(BoundGetValue(&sv_datum), type);
1537-
JSB_INIT_VAL(&val, WJB_VALUE, start_value);
1538-
}
1539-
else
1540-
JSB_INIT_NULL_VAL(&val, WJB_VALUE);
1560+
JSB_INIT_VAL(&val, WJB_VALUE, start_value);
15411561

15421562
/* Upper bound */
15431563
JSB_INIT_VAL(&key, WJB_KEY, "range_max");
1544-
if (!IsInfinite(&ev_datum))
1545-
{
1546-
/* Convert max to CSTRING */
1547-
end_value = datum_to_cstring(BoundGetValue(&ev_datum), type);
1548-
JSB_INIT_VAL(&val, WJB_VALUE, end_value);
1549-
}
1550-
else
1551-
JSB_INIT_NULL_VAL(&val, WJB_VALUE);
1564+
JSB_INIT_VAL(&val, WJB_VALUE, end_value);
15521565

15531566
result = pushJsonbValue(&jsonb_state, WJB_END_OBJECT, NULL);
15541567
}

contrib/pg_pathman/src/partition_creation.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424

2525
/* Create RANGE partitions to store some value */
2626
Oid create_partitions_for_value(Oid relid, Datum value, Oid value_type);
27-
Oid create_partitions_for_value_internal(Oid relid, Datum value, Oid value_type);
27+
Oid create_partitions_for_value_internal(Oid relid, Datum value, Oid value_type,
28+
bool is_background_worker);
2829

2930

3031
/* Create one RANGE partition */

contrib/pg_pathman/src/pathman_workers.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ bgw_main_spawn_partitions(Datum main_arg)
366366
args->parallel_master_pid))
367367
return;
368368
#endif
369-
370369
/* Establish connection and start transaction */
370+
371371
BackgroundWorkerInitializeConnectionByOid(args->dbid, args->userid);
372372

373373
/* Start new transaction (syscache access etc.) */
@@ -392,7 +392,8 @@ bgw_main_spawn_partitions(Datum main_arg)
392392
/* Create partitions and save the Oid of the last one */
393393
args->result = create_partitions_for_value_internal(args->partitioned_table,
394394
value, /* unpacked Datum */
395-
args->value_type);
395+
args->value_type,
396+
true); /* background woker */
396397

397398
/* Finish transaction in an appropriate way */
398399
if (args->result == InvalidOid)

contrib/pg_pathman/src/pl_funcs.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -841,9 +841,6 @@ invoke_on_partition_created_callback(PG_FUNCTION_ARGS)
841841
end;
842842
Oid value_type;
843843

844-
if (PG_ARGISNULL(ARG_RANGE_START) || PG_ARGISNULL(ARG_RANGE_END))
845-
elog(ERROR, "both bounds must be provided for RANGE partition");
846-
847844
/* Fetch start & end values for RANGE + their type */
848845
start = PG_ARGISNULL(ARG_RANGE_START) ?
849846
MakeBoundInf(MINUS_INFINITY) :

0 commit comments

Comments
 (0)