3434$$
3535LANGUAGE plpgsql;
3636
37+ /*
38+ * Check RANGE partition boundaries.
39+ */
40+ CREATE OR REPLACE FUNCTION @extschema@.check_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
5596BEGIN
97+ /* Acquire exclusive lock on parent */
98+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
99+
56100 PERFORM @extschema@.validate_relname(parent_relid);
57101 p_attribute := lower (p_attribute);
58102 PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
@@ -147,6 +191,9 @@ DECLARE
147191 i INTEGER ;
148192
149193BEGIN
194+ /* Acquire exclusive lock on parent */
195+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
196+
150197 PERFORM @extschema@.validate_relname(parent_relid);
151198 p_attribute := lower (p_attribute);
152199 PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
@@ -239,6 +286,9 @@ DECLARE
239286 part_count INTEGER := 0 ;
240287
241288BEGIN
289+ /* Acquire exclusive lock on parent */
290+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
291+
242292 PERFORM @extschema@.validate_relname(parent_relid);
243293 p_attribute := lower (p_attribute);
244294 PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
@@ -304,6 +354,9 @@ DECLARE
304354 part_count INTEGER := 0 ;
305355
306356BEGIN
357+ /* Acquire exclusive lock on parent */
358+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
359+
307360 PERFORM @extschema@.validate_relname(parent_relid);
308361 p_attribute := lower (p_attribute);
309362 PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
351404$$ LANGUAGE plpgsql;
352405
353406/*
354- * Check RANGE partition boundaries.
355- */
356- CREATE OR REPLACE FUNCTION @extschema@.check_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 */
397410CREATE OR REPLACE FUNCTION @extschema@.create_single_range_partition(
398411 parent_relid REGCLASS,
@@ -485,6 +498,9 @@ BEGIN
485498 v_part_relname := @extschema@.validate_relname(p_partition);
486499 v_parent_relid = @extschema@.get_parent_of_partition(p_partition);
487500
501+ /* Acquire exclusive lock on parent */
502+ PERFORM @extschema@.lock_partitioned_relation(v_parent_relid);
503+
488504 SELECT attname, parttype
489505 FROM @extschema@.pathman_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 @extschema@.lock_partitioned_relation(v_parent_relid1);
594+
576595 SELECT attname, parttype
577596 FROM @extschema@.pathman_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 */
610629CREATE OR REPLACE FUNCTION @extschema@.merge_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 */
673692CREATE OR REPLACE FUNCTION @extschema@.append_range_partition(
674693 parent_relid REGCLASS,
@@ -682,6 +701,9 @@ DECLARE
682701 v_interval TEXT ;
683702
684703BEGIN
704+ /* Acquire exclusive lock on parent */
705+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
706+
685707 SELECT attname, range_interval
686708 FROM @extschema@.pathman_config
687709 WHERE partrel = parent_relid
715737$$
716738LANGUAGE 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+ */
719746CREATE OR REPLACE FUNCTION @extschema@.append_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 */
766793CREATE OR REPLACE FUNCTION @extschema@.prepend_range_partition(
767794 parent_relid REGCLASS,
808835$$
809836LANGUAGE 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+ */
812844CREATE OR REPLACE FUNCTION @extschema@.prepend_partition_internal(
813845 parent_relid REGCLASS,
814846 p_atttype TEXT ,
@@ -867,6 +899,9 @@ DECLARE
867899 v_part_name TEXT ;
868900
869901BEGIN
902+ /* Acquire exclusive lock on parent */
903+ PERFORM @extschema@.lock_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 := @extschema@.get_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 @extschema@.lock_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
940978BEGIN
979+ /* Acquire exclusive lock on parent */
980+ PERFORM @extschema@.lock_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
9981039BEGIN
9991040 parent_relid = @extschema@.get_parent_of_partition(p_partition);
10001041
1042+ /* Acquire exclusive lock on parent */
1043+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
1044+
10011045 v_attname := attname
10021046 FROM @extschema@.pathman_config
10031047 WHERE partrel = parent_relid;
0 commit comments