Skip to content

Commit bf219ed

Browse files
committed
create_range_partitions() for array of boundaries
1 parent 3999694 commit bf219ed

File tree

2 files changed

+144
-4
lines changed

2 files changed

+144
-4
lines changed

range.sql

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,6 @@ BEGIN
317317
attribute := lower(attribute);
318318
PERFORM @extschema@.common_relation_checks(parent_relid, attribute);
319319

320-
IF p_interval <= 0 THEN
321-
RAISE EXCEPTION 'interval must be positive';
322-
END IF;
323-
324320
/* Check boundaries */
325321
PERFORM @extschema@.check_boundaries(parent_relid,
326322
attribute,
@@ -435,6 +431,77 @@ BEGIN
435431
END
436432
$$ LANGUAGE plpgsql;
437433

434+
435+
CREATE OR REPLACE FUNCTION @extschema@.create_range_partitions2(
436+
parent_relid REGCLASS,
437+
attribute TEXT,
438+
bounds ANYARRAY)
439+
RETURNS INTEGER AS
440+
$$
441+
DECLARE
442+
part_count INTEGER;
443+
BEGIN
444+
IF array_ndims(bounds) > 1 THEN
445+
RAISE EXCEPTION 'Bounds array must be a one dimensional array';
446+
END IF;
447+
448+
IF array_length(bounds, 1) < 2 THEN
449+
RAISE EXCEPTION 'Bounds array must have at least two values';
450+
END IF;
451+
452+
PERFORM @extschema@.validate_relname(parent_relid);
453+
454+
IF partition_data = true THEN
455+
/* Acquire data modification lock */
456+
PERFORM @extschema@.prevent_relation_modification(parent_relid);
457+
ELSE
458+
/* Acquire lock on parent */
459+
PERFORM @extschema@.lock_partitioned_relation(parent_relid);
460+
END IF;
461+
462+
attribute := lower(attribute);
463+
PERFORM @extschema@.common_relation_checks(parent_relid, attribute);
464+
465+
/* Check boundaries */
466+
PERFORM @extschema@.check_boundaries(parent_relid,
467+
attribute,
468+
bounds[0],
469+
bounds[array_length(bounds, 1) - 1]);
470+
471+
INSERT INTO @extschema@.pathman_config (partrel, attname, parttype, range_interval)
472+
VALUES (parent_relid, attribute, 2, NULL);
473+
474+
/* Create sequence for child partitions names */
475+
PERFORM @extschema@.create_or_replace_sequence(parent_relid)
476+
FROM @extschema@.get_plain_schema_and_relname(parent_relid);
477+
478+
/* Create partitions */
479+
part_count := @extschema@.create_range_partitions_internal(parent_relid, bounds);
480+
481+
/* Notify backend about changes */
482+
PERFORM @extschema@.on_create_partitions(parent_relid);
483+
484+
/* Relocate data if asked to */
485+
IF partition_data = true THEN
486+
PERFORM @extschema@.set_enable_parent(parent_relid, false);
487+
PERFORM @extschema@.partition_data(parent_relid);
488+
ELSE
489+
PERFORM @extschema@.set_enable_parent(parent_relid, true);
490+
END IF;
491+
492+
RETURN 0;
493+
END
494+
$$
495+
LANGUAGE plpgsql;
496+
497+
498+
CREATE OR REPLACE FUNCTION @extschema@.create_range_partitions_internal(
499+
parent_relid REGCLASS,
500+
value ANYARRAY)
501+
RETURNS REGCLASS AS 'pg_pathman', 'create_range_partitions_internal'
502+
LANGUAGE C;
503+
504+
438505
/*
439506
* Split RANGE partition
440507
*/

src/pl_range_funcs.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ PG_FUNCTION_INFO_V1( merge_range_partitions );
6969
PG_FUNCTION_INFO_V1( drop_range_partition_expand_next );
7070
PG_FUNCTION_INFO_V1( validate_interval_value );
7171

72+
PG_FUNCTION_INFO_V1( create_range_partitions_internal );
73+
7274

7375
/*
7476
* -----------------------------
@@ -1007,3 +1009,74 @@ drop_table_by_oid(Oid relid)
10071009

10081010
RemoveRelations(n);
10091011
}
1012+
1013+
1014+
Datum
1015+
create_range_partitions_internal(PG_FUNCTION_ARGS)
1016+
{
1017+
Oid relid = PG_GETARG_OID(0);
1018+
// char *attname = TextDatumGetCString(PG_GETARG_TEXT_P(1));
1019+
int16 typlen;
1020+
bool typbyval;
1021+
char typalign;
1022+
FmgrInfo cmp_func;
1023+
1024+
/* bounds */
1025+
ArrayType *arr = PG_GETARG_ARRAYTYPE_P(1);
1026+
Oid elemtype = ARR_ELEMTYPE(arr);
1027+
Datum *datums;
1028+
bool *nulls;
1029+
int ndatums;
1030+
int i;
1031+
1032+
/* Extract bounds */
1033+
get_typlenbyvalalign(elemtype, &typlen, &typbyval, &typalign);
1034+
deconstruct_array(arr, elemtype,
1035+
typlen, typbyval, typalign,
1036+
&datums, &nulls, &ndatums);
1037+
1038+
/* Check if bounds array is ascending */
1039+
fill_type_cmp_fmgr_info(&cmp_func,
1040+
getBaseType(elemtype),
1041+
getBaseType(elemtype));
1042+
for (i = 0; i < ndatums-1; i++)
1043+
{
1044+
/*
1045+
* Only first bound can be NULL
1046+
*
1047+
* XXX Probably the last one too...
1048+
*/
1049+
if (nulls[i])
1050+
{
1051+
if (i == 0)
1052+
continue;
1053+
else
1054+
elog(ERROR,
1055+
"Only first bound can be NULL");
1056+
}
1057+
1058+
if (DatumGetInt32(FunctionCall2(&cmp_func, datums[i], datums[i+1])) >= 0)
1059+
elog(ERROR,
1060+
"Bounds array must be ascending");
1061+
}
1062+
1063+
/* Create partitions */
1064+
for (i = 0; i < ndatums-1; i++)
1065+
{
1066+
Bound start = nulls[i] ?
1067+
MakeBoundInf(MINUS_INFINITY) :
1068+
MakeBound(datums[i]);
1069+
Bound end = nulls[i+1] ?
1070+
MakeBoundInf(PLUS_INFINITY) :
1071+
MakeBound(datums[i+1]);
1072+
1073+
(void) create_single_range_partition_internal(relid,
1074+
&start,
1075+
&end,
1076+
elemtype,
1077+
NULL,
1078+
NULL);
1079+
}
1080+
1081+
PG_RETURN_VOID();
1082+
}

0 commit comments

Comments
 (0)