34
34
$$
35
35
LANGUAGE plpgsql;
36
36
37
+ /*
38
+ * Check RANGE partition boundaries.
39
+ */
40
+ CREATEOR REPLACE FUNCTION @extschema@.check_boundaries(
41
+ parent_relidREGCLASS,
42
+ p_attributeTEXT ,
43
+ p_start_valueANYELEMENT,
44
+ p_end_valueANYELEMENT)
45
+ RETURNS VOIDAS
46
+ $$
47
+ DECLARE
48
+ v_minp_start_value%TYPE;
49
+ v_maxp_start_value%TYPE;
50
+ v_countBIGINT ;
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 ISNULL OR v_max ISNULL ) 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
+
37
78
/*
38
79
* Creates RANGE partitions for specified relation based on datetime attribute
39
80
*/
@@ -53,6 +94,9 @@ DECLARE
53
94
iINTEGER ;
54
95
55
96
BEGIN
97
+ /* Acquire exclusive lock on parent*/
98
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
99
+
56
100
PERFORM @extschema@.validate_relname(parent_relid);
57
101
p_attribute := lower (p_attribute);
58
102
PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
@@ -147,6 +191,9 @@ DECLARE
147
191
iINTEGER ;
148
192
149
193
BEGIN
194
+ /* Acquire exclusive lock on parent*/
195
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
196
+
150
197
PERFORM @extschema@.validate_relname(parent_relid);
151
198
p_attribute := lower (p_attribute);
152
199
PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
@@ -239,6 +286,9 @@ DECLARE
239
286
part_countINTEGER := 0 ;
240
287
241
288
BEGIN
289
+ /* Acquire exclusive lock on parent*/
290
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
291
+
242
292
PERFORM @extschema@.validate_relname(parent_relid);
243
293
p_attribute := lower (p_attribute);
244
294
PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
@@ -304,6 +354,9 @@ DECLARE
304
354
part_countINTEGER := 0 ;
305
355
306
356
BEGIN
357
+ /* Acquire exclusive lock on parent*/
358
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
359
+
307
360
PERFORM @extschema@.validate_relname(parent_relid);
308
361
p_attribute := lower (p_attribute);
309
362
PERFORM @extschema@.common_relation_checks(parent_relid, p_attribute);
351
404
$$ LANGUAGE plpgsql;
352
405
353
406
/*
354
- * Check RANGE partition boundaries.
355
- */
356
- CREATEOR REPLACE FUNCTION @extschema@.check_boundaries(
357
- parent_relidREGCLASS,
358
- p_attributeTEXT ,
359
- p_start_valueANYELEMENT,
360
- p_end_valueANYELEMENT)
361
- RETURNS VOIDAS
362
- $$
363
- DECLARE
364
- v_minp_start_value%TYPE;
365
- v_maxp_start_value%TYPE;
366
- v_countBIGINT ;
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 ISNULL OR v_max ISNULL ) 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).
396
409
*/
397
410
CREATEOR REPLACE FUNCTION @extschema@.create_single_range_partition(
398
411
parent_relidREGCLASS,
@@ -485,6 +498,9 @@ BEGIN
485
498
v_part_relname := @extschema@.validate_relname(p_partition);
486
499
v_parent_relid= @extschema@.get_parent_of_partition(p_partition);
487
500
501
+ /* Acquire exclusive lock on parent*/
502
+ PERFORM @extschema@.lock_partitioned_relation(v_parent_relid);
503
+
488
504
SELECT attname, parttype
489
505
FROM @extschema@.pathman_config
490
506
WHERE partrel= v_parent_relid
@@ -573,6 +589,9 @@ BEGIN
573
589
RAISE EXCEPTION' Cannot merge partitions with different parents' ;
574
590
END IF;
575
591
592
+ /* Acquire exclusive lock on parent*/
593
+ PERFORM @extschema@.lock_partitioned_relation(v_parent_relid1);
594
+
576
595
SELECT attname, parttype
577
596
FROM @extschema@.pathman_config
578
597
WHERE partrel= v_parent_relid1
@@ -604,8 +623,8 @@ LANGUAGE plpgsql;
604
623
* Merge two partitions. All data will be copied to the first one. Second
605
624
* partition will be destroyed.
606
625
*
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).
609
628
*/
610
629
CREATEOR REPLACE FUNCTION @extschema@.merge_range_partitions_internal(
611
630
parent_relidREGCLASS,
@@ -668,7 +687,7 @@ $$ LANGUAGE plpgsql;
668
687
669
688
670
689
/*
671
- * Append new partition
690
+ * Append new partition.
672
691
*/
673
692
CREATEOR REPLACE FUNCTION @extschema@.append_range_partition(
674
693
parent_relidREGCLASS,
@@ -682,6 +701,9 @@ DECLARE
682
701
v_intervalTEXT ;
683
702
684
703
BEGIN
704
+ /* Acquire exclusive lock on parent*/
705
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
706
+
685
707
SELECT attname, range_interval
686
708
FROM @extschema@.pathman_config
687
709
WHERE partrel= parent_relid
715
737
$$
716
738
LANGUAGE plpgsql;
717
739
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
+ */
719
746
CREATEOR REPLACE FUNCTION @extschema@.append_partition_internal(
720
747
parent_relidREGCLASS,
721
748
p_atttypeTEXT ,
@@ -761,7 +788,7 @@ LANGUAGE plpgsql;
761
788
762
789
763
790
/*
764
- * Prepend new partition
791
+ * Prepend new partition.
765
792
*/
766
793
CREATEOR REPLACE FUNCTION @extschema@.prepend_range_partition(
767
794
parent_relidREGCLASS,
808
835
$$
809
836
LANGUAGE plpgsql;
810
837
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
+ */
812
844
CREATEOR REPLACE FUNCTION @extschema@.prepend_partition_internal(
813
845
parent_relidREGCLASS,
814
846
p_atttypeTEXT ,
@@ -867,6 +899,9 @@ DECLARE
867
899
v_part_nameTEXT ;
868
900
869
901
BEGIN
902
+ /* Acquire exclusive lock on parent*/
903
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
904
+
870
905
IF p_start_value>= p_end_value THEN
871
906
RAISE EXCEPTION' Failed to create partition: p_start_value is greater than p_end_value' ;
872
907
END IF;
@@ -908,6 +943,9 @@ BEGIN
908
943
parent_relid := @extschema@.get_parent_of_partition(p_partition);
909
944
part_name := p_partition::TEXT ;/* save the name to be returned*/
910
945
946
+ /* Acquire exclusive lock on parent*/
947
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
948
+
911
949
/* Drop table*/
912
950
EXECUTE format(' DROP TABLE %s' , part_name);
913
951
@@ -938,6 +976,9 @@ DECLARE
938
976
rel_persistenceCHAR ;
939
977
940
978
BEGIN
979
+ /* Acquire exclusive lock on parent*/
980
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
981
+
941
982
/* Ignore temporary tables*/
942
983
SELECT relpersistenceFROM pg_catalog .pg_class
943
984
WHERE oid = p_partition INTO rel_persistence;
@@ -998,6 +1039,9 @@ DECLARE
998
1039
BEGIN
999
1040
parent_relid= @extschema@.get_parent_of_partition(p_partition);
1000
1041
1042
+ /* Acquire exclusive lock on parent*/
1043
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
1044
+
1001
1045
v_attname := attname
1002
1046
FROM @extschema@.pathman_config
1003
1047
WHERE partrel= parent_relid;