Skip to content

Commit d3dea68

Browse files
committed
rewrite create_single_range_partition() function in C language
1 parent 1cd5a12 commit d3dea68

14 files changed

+568
-325
lines changed

hash.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* ------------------------------------------------------------------------
22
*
33
* hash.sql
4-
* HASH partitioning functions
4+
* HASH partitioning functions
55
*
66
* Copyright (c) 2015-2016, Postgres Professional
77
*

range.sql

Lines changed: 36 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,20 @@
11
/* ------------------------------------------------------------------------
22
*
33
* range.sql
4-
* RANGE partitioning functions
4+
* RANGE partitioning functions
55
*
66
* Copyright (c) 2015-2016, Postgres Professional
77
*
88
* ------------------------------------------------------------------------
99
*/
1010

11-
CREATE OR REPLACE FUNCTION @extschema@.get_sequence_name(
12-
plain_schema TEXT,
13-
plain_relname TEXT)
14-
RETURNS TEXT AS
15-
$$
16-
BEGIN
17-
RETURN format('%s.%s',
18-
quote_ident(plain_schema),
19-
quote_ident(format('%s_seq', plain_relname)));
20-
END
21-
$$
22-
LANGUAGE plpgsql;
23-
2411
CREATE OR REPLACE FUNCTION @extschema@.create_or_replace_sequence(
25-
plain_schema TEXT,
26-
plain_relname TEXT,
12+
parent_relid REGCLASS,
2713
OUT seq_name TEXT)
2814
AS $$
2915
BEGIN
30-
seq_name := @extschema@.get_sequence_name(plain_schema, plain_relname);
16+
seq_name := @extschema@.build_sequence_name(parent_relid);
17+
3118
EXECUTE format('DROP SEQUENCE IF EXISTS %s', seq_name);
3219
EXECUTE format('CREATE SEQUENCE %s START 1', seq_name);
3320
END
@@ -110,7 +97,7 @@ BEGIN
11097
PERFORM @extschema@.common_relation_checks(parent_relid, attribute);
11198

11299
IF p_count < 0 THEN
113-
RAISE EXCEPTION '''p_count'' must not be less than 0';
100+
RAISE EXCEPTION '"p_count" must not be less than 0';
114101
END IF;
115102

116103
/* Try to determine partitions count if not set */
@@ -154,7 +141,7 @@ BEGIN
154141
END IF;
155142

156143
/* Create sequence for child partitions names */
157-
PERFORM @extschema@.create_or_replace_sequence(schema, relname)
144+
PERFORM @extschema@.create_or_replace_sequence(parent_relid)
158145
FROM @extschema@.get_plain_schema_and_relname(parent_relid);
159146

160147
/* Insert new entry to pathman config */
@@ -269,7 +256,7 @@ BEGIN
269256
END IF;
270257

271258
/* Create sequence for child partitions names */
272-
PERFORM @extschema@.create_or_replace_sequence(schema, relname)
259+
PERFORM @extschema@.create_or_replace_sequence(parent_relid)
273260
FROM @extschema@.get_plain_schema_and_relname(parent_relid);
274261

275262
/* Insert new entry to pathman config */
@@ -343,7 +330,7 @@ BEGIN
343330
end_value);
344331

345332
/* Create sequence for child partitions names */
346-
PERFORM @extschema@.create_or_replace_sequence(schema, relname)
333+
PERFORM @extschema@.create_or_replace_sequence(parent_relid)
347334
FROM @extschema@.get_plain_schema_and_relname(parent_relid);
348335

349336
/* Insert new entry to pathman config */
@@ -413,7 +400,7 @@ BEGIN
413400
end_value);
414401

415402
/* Create sequence for child partitions names */
416-
PERFORM @extschema@.create_or_replace_sequence(schema, relname)
403+
PERFORM @extschema@.create_or_replace_sequence(parent_relid)
417404
FROM @extschema@.get_plain_schema_and_relname(parent_relid);
418405

419406
/* Insert new entry to pathman config */
@@ -450,102 +437,6 @@ BEGIN
450437
END
451438
$$ LANGUAGE plpgsql;
452439

453-
/*
454-
* Creates new RANGE partition. Returns partition name.
455-
* NOTE: This function SHOULD NOT take xact_handling lock (BGWs in 9.5).
456-
*/
457-
CREATE OR REPLACE FUNCTION @extschema@.create_single_range_partition(
458-
parent_relid REGCLASS,
459-
start_value ANYELEMENT,
460-
end_value ANYELEMENT,
461-
partition_name TEXT DEFAULT NULL,
462-
tablespace TEXT DEFAULT NULL)
463-
RETURNS REGCLASS AS
464-
$$
465-
DECLARE
466-
v_part_num INT;
467-
v_child_relname TEXT;
468-
v_plain_child_relname TEXT;
469-
v_attname TEXT;
470-
v_plain_schema TEXT;
471-
v_plain_relname TEXT;
472-
v_child_relname_exists BOOL;
473-
v_seq_name TEXT;
474-
v_init_callback REGPROCEDURE;
475-
476-
BEGIN
477-
v_attname := attname FROM @extschema@.pathman_config
478-
WHERE partrel = parent_relid;
479-
480-
IF v_attname IS NULL THEN
481-
RAISE EXCEPTION 'table "%" is not partitioned', parent_relid::TEXT;
482-
END IF;
483-
484-
SELECT * INTO v_plain_schema, v_plain_relname
485-
FROM @extschema@.get_plain_schema_and_relname(parent_relid);
486-
487-
v_seq_name := @extschema@.get_sequence_name(v_plain_schema, v_plain_relname);
488-
489-
IF partition_name IS NULL THEN
490-
/* Get next value from sequence */
491-
LOOP
492-
v_part_num := nextval(v_seq_name);
493-
v_plain_child_relname := format('%s_%s', v_plain_relname, v_part_num);
494-
v_child_relname := format('%s.%s',
495-
quote_ident(v_plain_schema),
496-
quote_ident(v_plain_child_relname));
497-
498-
v_child_relname_exists := count(*) > 0
499-
FROM pg_class
500-
WHERE relname = v_plain_child_relname AND
501-
relnamespace = v_plain_schema::regnamespace
502-
LIMIT 1;
503-
504-
EXIT WHEN v_child_relname_exists = false;
505-
END LOOP;
506-
ELSE
507-
v_child_relname := partition_name;
508-
END IF;
509-
510-
IF tablespace IS NULL THEN
511-
tablespace := @extschema@.get_rel_tablespace_name(parent_relid);
512-
END IF;
513-
514-
EXECUTE format('CREATE TABLE %1$s (LIKE %2$s INCLUDING ALL)
515-
INHERITS (%2$s) TABLESPACE %3$s',
516-
v_child_relname,
517-
parent_relid::TEXT,
518-
tablespace);
519-
520-
EXECUTE format('ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s)',
521-
v_child_relname,
522-
@extschema@.build_check_constraint_name(v_child_relname::REGCLASS,
523-
v_attname),
524-
@extschema@.build_range_condition(v_attname,
525-
start_value,
526-
end_value));
527-
528-
PERFORM @extschema@.copy_foreign_keys(parent_relid, v_child_relname::REGCLASS);
529-
530-
/* Fetch init_callback from 'params' table */
531-
WITH stub_callback(stub) as (values (0))
532-
SELECT coalesce(init_callback, 0::REGPROCEDURE)
533-
FROM stub_callback
534-
LEFT JOIN @extschema@.pathman_config_params AS params
535-
ON params.partrel = parent_relid
536-
INTO v_init_callback;
537-
538-
PERFORM @extschema@.invoke_on_partition_created_callback(parent_relid,
539-
v_child_relname::REGCLASS,
540-
v_init_callback,
541-
start_value,
542-
end_value);
543-
544-
RETURN v_child_relname::REGCLASS;
545-
END
546-
$$ LANGUAGE plpgsql
547-
SET client_min_messages = WARNING;
548-
549440
/*
550441
* Split RANGE partition
551442
*/
@@ -1016,9 +907,10 @@ BEGIN
1016907
END IF;
1017908

1018909
/* check range overlap */
1019-
IF @extschema@.partitions_count(parent_relid) > 0
1020-
AND @extschema@.check_overlap(parent_relid, start_value, end_value) THEN
1021-
RAISE EXCEPTION 'specified range overlaps with existing partitions';
910+
IF @extschema@.partitions_count(parent_relid) > 0 THEN
911+
PERFORM @extschema@.check_range_available(parent_relid,
912+
start_value,
913+
end_value);
1022914
END IF;
1023915

1024916
/* Create new partition */
@@ -1133,9 +1025,8 @@ BEGIN
11331025
partition::TEXT;
11341026
END IF;
11351027

1136-
IF @extschema@.check_overlap(parent_relid, start_value, end_value) THEN
1137-
RAISE EXCEPTION 'specified range overlaps with existing partitions';
1138-
END IF;
1028+
/* check range overlap */
1029+
PERFORM @extschema@.check_range_available(parent_relid, start_value, end_value);
11391030

11401031
IF NOT @extschema@.validate_relations_equality(parent_relid, partition) THEN
11411032
RAISE EXCEPTION 'partition must have the exact same structure as parent';
@@ -1321,6 +1212,20 @@ BEGIN
13211212
END
13221213
$$ LANGUAGE plpgsql;
13231214

1215+
/*
1216+
* Creates new RANGE partition. Returns partition name.
1217+
* NOTE: This function SHOULD NOT take xact_handling lock (BGWs in 9.5).
1218+
*/
1219+
CREATE OR REPLACE FUNCTION @extschema@.create_single_range_partition(
1220+
parent_relid REGCLASS,
1221+
start_value ANYELEMENT,
1222+
end_value ANYELEMENT,
1223+
partition_name TEXT DEFAULT NULL,
1224+
tablespace TEXT DEFAULT NULL)
1225+
RETURNS REGCLASS AS 'pg_pathman', 'create_single_range_partition_pl'
1226+
LANGUAGE C
1227+
SET client_min_messages = WARNING;
1228+
13241229
/*
13251230
* Construct CHECK constraint condition for a range partition.
13261231
*/
@@ -1331,6 +1236,11 @@ CREATE OR REPLACE FUNCTION @extschema@.build_range_condition(
13311236
RETURNS TEXT AS 'pg_pathman', 'build_range_condition'
13321237
LANGUAGE C;
13331238

1239+
CREATE OR REPLACE FUNCTION @extschema@.build_sequence_name(
1240+
parent_relid REGCLASS)
1241+
RETURNS TEXT AS 'pg_pathman', 'build_sequence_name'
1242+
LANGUAGE C;
1243+
13341244
/*
13351245
* Returns N-th range (as an array of two elements).
13361246
*/
@@ -1354,11 +1264,11 @@ LANGUAGE C;
13541264
* Checks if range overlaps with existing partitions.
13551265
* Returns TRUE if overlaps and FALSE otherwise.
13561266
*/
1357-
CREATE OR REPLACE FUNCTION @extschema@.check_overlap(
1267+
CREATE OR REPLACE FUNCTION @extschema@.check_range_available(
13581268
parent_relid REGCLASS,
13591269
range_min ANYELEMENT,
13601270
range_max ANYELEMENT)
1361-
RETURNS BOOLEAN AS 'pg_pathman', 'check_overlap'
1271+
RETURNS VOID AS 'pg_pathman', 'check_range_available_pl'
13621272
LANGUAGE C;
13631273

13641274
/*

sql/pathman_basic.sql

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,13 @@ CREATE TABLE test.num_range_rel (
280280
id SERIAL PRIMARY KEY,
281281
txt TEXT);
282282
SELECT pathman.create_range_partitions('test.num_range_rel', 'id', 1000, 1000, 4);
283-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 4001, 5000);
284-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 4000, 5000);
285-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 3999, 5000);
286-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 3000, 3500);
287-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 0, 999);
288-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 0, 1000);
289-
SELECT pathman.check_overlap('test.num_range_rel'::regclass::oid, 0, 1001);
283+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 4001, 5000);
284+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 4000, 5000);
285+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 3999, 5000);
286+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 3000, 3500);
287+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 0, 999);
288+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 0, 1000);
289+
SELECT pathman.check_range_available('test.num_range_rel'::regclass, 0, 1001);
290290

291291
/* CaMeL cAsE table names and attributes */
292292
CREATE TABLE test."TeSt" (a INT NOT NULL, b INT);

src/init.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,17 @@ build_check_constraint_name_internal(Oid relid, AttrNumber attno)
572572
return psprintf("pathman_%s_%u_check", get_rel_name(relid), attno);
573573
}
574574

575+
/*
576+
* Generate part sequence name for a parent.
577+
*
578+
* This function does not perform sanity checks at all.
579+
*/
580+
char *
581+
build_sequence_name_internal(Oid relid)
582+
{
583+
return psprintf("%s_seq", get_rel_name(relid));
584+
}
585+
575586
/*
576587
* Check that relation 'relid' is partitioned by pg_pathman.
577588
*

src/init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ Oid *find_inheritance_children_array(Oid parentrelId,
116116
char *build_check_constraint_name_internal(Oid relid,
117117
AttrNumber attno);
118118

119+
char *build_sequence_name_internal(Oid relid);
120+
119121
bool pathman_config_contains_relation(Oid relid,
120122
Datum *values,
121123
bool *isnull,

0 commit comments

Comments
 (0)