Skip to content

Commit d643c74

Browse files
committed
place lock_partitioned_relation() in various places over the range.sql
1 parent 6f763b6 commit d643c74

File tree

1 file changed

+92
-48
lines changed

1 file changed

+92
-48
lines changed

Diff for: range.sql

+92-48
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,47 @@ END
3434
$$
3535
LANGUAGE plpgsql;
3636

37+
/*
38+
* Check RANGE partition boundaries.
39+
*/
40+
CREATE OR REPLACE FUNCTION @[email protected]_boundaries(
41+
parent_relid REGCLASS,
42+
p_attribute TEXT,
43+
p_start_value ANYELEMENT,
44+
p_end_value ANYELEMENT)
45+
RETURNS VOID AS
46+
$$
47+
DECLARE
48+
v_min p_start_value%TYPE;
49+
v_max p_start_value%TYPE;
50+
v_count BIGINT;
51+
52+
BEGIN
53+
/* Get min and max values */
54+
EXECUTE format('SELECT count(*), min(%1$s), max(%1$s)
55+
FROM %2$s WHERE NOT %1$s IS NULL',
56+
p_attribute, parent_relid::TEXT)
57+
INTO v_count, v_min, v_max;
58+
59+
/* Check if column has NULL values */
60+
IF v_count > 0 AND (v_min IS NULL OR v_max IS NULL) THEN
61+
RAISE EXCEPTION '''%'' column contains NULL values', p_attribute;
62+
END IF;
63+
64+
/* Check lower boundary */
65+
IF p_start_value > v_min THEN
66+
RAISE EXCEPTION 'Start value is less than minimum value of ''%''',
67+
p_attribute;
68+
END IF;
69+
70+
/* Check upper boundary */
71+
IF p_end_value <= v_max THEN
72+
RAISE EXCEPTION 'Not enough partitions to fit all values of ''%''',
73+
p_attribute;
74+
END IF;
75+
END
76+
$$ LANGUAGE plpgsql;
77+
3778
/*
3879
* Creates RANGE partitions for specified relation based on datetime attribute
3980
*/
@@ -53,6 +94,9 @@ DECLARE
5394
i INTEGER;
5495

5596
BEGIN
97+
/* Acquire exclusive lock on parent */
98+
PERFORM @[email protected]_partitioned_relation(parent_relid);
99+
56100
PERFORM @[email protected]_relname(parent_relid);
57101
p_attribute := lower(p_attribute);
58102
PERFORM @[email protected]_relation_checks(parent_relid, p_attribute);
@@ -147,6 +191,9 @@ DECLARE
147191
i INTEGER;
148192

149193
BEGIN
194+
/* Acquire exclusive lock on parent */
195+
PERFORM @[email protected]_partitioned_relation(parent_relid);
196+
150197
PERFORM @[email protected]_relname(parent_relid);
151198
p_attribute := lower(p_attribute);
152199
PERFORM @[email protected]_relation_checks(parent_relid, p_attribute);
@@ -239,6 +286,9 @@ DECLARE
239286
part_count INTEGER := 0;
240287

241288
BEGIN
289+
/* Acquire exclusive lock on parent */
290+
PERFORM @[email protected]_partitioned_relation(parent_relid);
291+
242292
PERFORM @[email protected]_relname(parent_relid);
243293
p_attribute := lower(p_attribute);
244294
PERFORM @[email protected]_relation_checks(parent_relid, p_attribute);
@@ -304,6 +354,9 @@ DECLARE
304354
part_count INTEGER := 0;
305355

306356
BEGIN
357+
/* Acquire exclusive lock on parent */
358+
PERFORM @[email protected]_partitioned_relation(parent_relid);
359+
307360
PERFORM @[email protected]_relname(parent_relid);
308361
p_attribute := lower(p_attribute);
309362
PERFORM @[email protected]_relation_checks(parent_relid, p_attribute);
@@ -351,48 +404,8 @@ END
351404
$$ LANGUAGE plpgsql;
352405

353406
/*
354-
* Check RANGE partition boundaries.
355-
*/
356-
CREATE OR REPLACE FUNCTION @[email protected]_boundaries(
357-
parent_relid REGCLASS,
358-
p_attribute TEXT,
359-
p_start_value ANYELEMENT,
360-
p_end_value ANYELEMENT)
361-
RETURNS VOID AS
362-
$$
363-
DECLARE
364-
v_min p_start_value%TYPE;
365-
v_max p_start_value%TYPE;
366-
v_count BIGINT;
367-
368-
BEGIN
369-
/* Get min and max values */
370-
EXECUTE format('SELECT count(*), min(%1$s), max(%1$s)
371-
FROM %2$s WHERE NOT %1$s IS NULL',
372-
p_attribute, parent_relid::TEXT)
373-
INTO v_count, v_min, v_max;
374-
375-
/* Check if column has NULL values */
376-
IF v_count > 0 AND (v_min IS NULL OR v_max IS NULL) THEN
377-
RAISE EXCEPTION '''%'' column contains NULL values', p_attribute;
378-
END IF;
379-
380-
/* Check lower boundary */
381-
IF p_start_value > v_min THEN
382-
RAISE EXCEPTION 'Start value is less than minimum value of ''%''',
383-
p_attribute;
384-
END IF;
385-
386-
/* Check upper boundary */
387-
IF p_end_value <= v_max THEN
388-
RAISE EXCEPTION 'Not enough partitions to fit all values of ''%''',
389-
p_attribute;
390-
END IF;
391-
END
392-
$$ LANGUAGE plpgsql;
393-
394-
/*
395-
* Creates new RANGE partition. Returns partition name
407+
* Creates new RANGE partition. Returns partition name.
408+
* NOTE: This function SHOULD NOT take xact_handling lock (BGWs in 9.5).
396409
*/
397410
CREATE OR REPLACE FUNCTION @[email protected]_single_range_partition(
398411
parent_relid REGCLASS,
@@ -485,6 +498,9 @@ BEGIN
485498
v_part_relname := @[email protected]_relname(p_partition);
486499
v_parent_relid = @[email protected]_parent_of_partition(p_partition);
487500

501+
/* Acquire exclusive lock on parent */
502+
PERFORM @[email protected]_partitioned_relation(v_parent_relid);
503+
488504
SELECT attname, parttype
489505
FROM @[email protected]_config
490506
WHERE partrel = v_parent_relid
@@ -573,6 +589,9 @@ BEGIN
573589
RAISE EXCEPTION 'Cannot merge partitions with different parents';
574590
END IF;
575591

592+
/* Acquire exclusive lock on parent */
593+
PERFORM @[email protected]_partitioned_relation(v_parent_relid1);
594+
576595
SELECT attname, parttype
577596
FROM @[email protected]_config
578597
WHERE partrel = v_parent_relid1
@@ -604,8 +623,8 @@ LANGUAGE plpgsql;
604623
* Merge two partitions. All data will be copied to the first one. Second
605624
* partition will be destroyed.
606625
*
607-
* Notes: dummy field is used to pass the element type to the function
608-
* (it is necessary because of pseudo-types used in function)
626+
* NOTE: dummy field is used to pass the element type to the function
627+
* (it is necessary because of pseudo-types used in function).
609628
*/
610629
CREATE OR REPLACE FUNCTION @[email protected]_range_partitions_internal(
611630
parent_relid REGCLASS,
@@ -668,7 +687,7 @@ $$ LANGUAGE plpgsql;
668687

669688

670689
/*
671-
* Append new partition
690+
* Append new partition.
672691
*/
673692
CREATE OR REPLACE FUNCTION @[email protected]_range_partition(
674693
parent_relid REGCLASS,
@@ -682,6 +701,9 @@ DECLARE
682701
v_interval TEXT;
683702

684703
BEGIN
704+
/* Acquire exclusive lock on parent */
705+
PERFORM @[email protected]_partitioned_relation(parent_relid);
706+
685707
SELECT attname, range_interval
686708
FROM @[email protected]_config
687709
WHERE partrel = parent_relid
@@ -715,7 +737,12 @@ END
715737
$$
716738
LANGUAGE plpgsql;
717739

718-
740+
/*
741+
* Spawn logic for append_partition(). We have to
742+
* separate this in order to pass the 'p_range'.
743+
*
744+
* NOTE: we don't take a xact_handling lock here.
745+
*/
719746
CREATE OR REPLACE FUNCTION @[email protected]_partition_internal(
720747
parent_relid REGCLASS,
721748
p_atttype TEXT,
@@ -761,7 +788,7 @@ LANGUAGE plpgsql;
761788

762789

763790
/*
764-
* Prepend new partition
791+
* Prepend new partition.
765792
*/
766793
CREATE OR REPLACE FUNCTION @[email protected]_range_partition(
767794
parent_relid REGCLASS,
@@ -808,7 +835,12 @@ END
808835
$$
809836
LANGUAGE plpgsql;
810837

811-
838+
/*
839+
* Spawn logic for prepend_partition(). We have to
840+
* separate this in order to pass the 'p_range'.
841+
*
842+
* NOTE: we don't take a xact_handling lock here.
843+
*/
812844
CREATE OR REPLACE FUNCTION @[email protected]_partition_internal(
813845
parent_relid REGCLASS,
814846
p_atttype TEXT,
@@ -867,6 +899,9 @@ DECLARE
867899
v_part_name TEXT;
868900

869901
BEGIN
902+
/* Acquire exclusive lock on parent */
903+
PERFORM @[email protected]_partitioned_relation(parent_relid);
904+
870905
IF p_start_value >= p_end_value THEN
871906
RAISE EXCEPTION 'Failed to create partition: p_start_value is greater than p_end_value';
872907
END IF;
@@ -908,6 +943,9 @@ BEGIN
908943
parent_relid := @[email protected]_parent_of_partition(p_partition);
909944
part_name := p_partition::TEXT; /* save the name to be returned */
910945

946+
/* Acquire exclusive lock on parent */
947+
PERFORM @[email protected]_partitioned_relation(parent_relid);
948+
911949
/* Drop table */
912950
EXECUTE format('DROP TABLE %s', part_name);
913951

@@ -938,6 +976,9 @@ DECLARE
938976
rel_persistence CHAR;
939977

940978
BEGIN
979+
/* Acquire exclusive lock on parent */
980+
PERFORM @[email protected]_partitioned_relation(parent_relid);
981+
941982
/* Ignore temporary tables */
942983
SELECT relpersistence FROM pg_catalog.pg_class
943984
WHERE oid = p_partition INTO rel_persistence;
@@ -998,6 +1039,9 @@ DECLARE
9981039
BEGIN
9991040
parent_relid = @[email protected]_parent_of_partition(p_partition);
10001041

1042+
/* Acquire exclusive lock on parent */
1043+
PERFORM @[email protected]_partitioned_relation(parent_relid);
1044+
10011045
v_attname := attname
10021046
FROM @[email protected]_config
10031047
WHERE partrel = parent_relid;

0 commit comments

Comments
 (0)