@@ -18,14 +18,6 @@ CREATE OR REPLACE FUNCTION @extschema@.create_hash_partitions(
18
18
partition_data BOOLEAN DEFAULT TRUE)
19
19
RETURNS INTEGER AS
20
20
$$
21
- DECLARE
22
- v_child_relname TEXT ;
23
- v_plain_schema TEXT ;
24
- v_plain_relname TEXT ;
25
- -- v_atttype REGTYPE;
26
- -- v_hashfunc REGPROC;
27
- v_init_callback REGPROCEDURE;
28
-
29
21
BEGIN
30
22
PERFORM @extschema@.validate_relname(parent_relid);
31
23
40
32
attribute := lower (attribute);
41
33
PERFORM @extschema@.common_relation_checks(parent_relid, attribute);
42
34
43
- /* Fetch atttype and its hash function */
44
- -- v_atttype := @extschema@.get_attribute_type(parent_relid, attribute);
45
- -- v_hashfunc := @extschema@.get_type_hash_func(v_atttype);
46
-
47
- SELECT * INTO v_plain_schema, v_plain_relname
48
- FROM @extschema@.get_plain_schema_and_relname(parent_relid);
49
-
50
35
/* Insert new entry to pathman config */
51
36
INSERT INTO @extschema@.pathman_config (partrel, attname, parttype)
52
37
VALUES (parent_relid, attribute, 1 );
@@ -74,29 +59,42 @@ SET client_min_messages = WARNING;
74
59
75
60
/*
76
61
* Replace hash partition with another one. It could be useful in case when
77
- * someone wants to attach foreign table as a partition
62
+ * someone wants to attach foreign table as a partition.
63
+ *
64
+ * lock_parent - should we take an exclusive lock?
78
65
*/
79
66
CREATE OR REPLACE FUNCTION @extschema@.replace_hash_partition(
80
67
old_partition REGCLASS,
81
- new_partition REGCLASS)
68
+ new_partition REGCLASS,
69
+ lock_parent BOOL DEFAULT TRUE)
82
70
RETURNS REGCLASS AS
83
71
$$
84
72
DECLARE
85
- v_attname TEXT ;
73
+ parent_relid REGCLASS;
74
+ part_attname TEXT ; /* partitioned column */
75
+ old_constr_name TEXT ; /* name of old_partition's constraint */
76
+ old_constr_def TEXT ; /* definition of old_partition's constraint */
86
77
rel_persistence CHAR ;
87
- v_init_callback REGPROCEDURE;
88
- v_parent_relid REGCLASS;
89
- v_part_count INT ;
90
- v_part_num INT ;
78
+ p_init_callback REGPROCEDURE;
79
+
91
80
BEGIN
92
81
PERFORM @extschema@.validate_relname(old_partition);
93
82
PERFORM @extschema@.validate_relname(new_partition);
94
83
95
84
/* Parent relation */
96
- v_parent_relid := @extschema@.get_parent_of_partition(old_partition);
85
+ parent_relid := @extschema@.get_parent_of_partition(old_partition);
86
+
87
+ IF lock_parent THEN
88
+ /* Acquire data modification lock (prevent further modifications) */
89
+ PERFORM @extschema@.prevent_relation_modification(parent_relid);
90
+ ELSE
91
+ /* Acquire lock on parent */
92
+ PERFORM @extschema@.lock_partitioned_relation(parent_relid);
93
+ END IF;
97
94
98
- /* Acquire lock on parent */
99
- PERFORM @extschema@.lock_partitioned_relation(v_parent_relid);
95
+ /* Acquire data modification lock (prevent further modifications) */
96
+ PERFORM @extschema@.prevent_relation_modification(old_partition);
97
+ PERFORM @extschema@.prevent_relation_modification(new_partition);
100
98
101
99
/* Ignore temporary tables */
102
100
SELECT relpersistence FROM pg_catalog .pg_class
@@ -108,52 +106,54 @@ BEGIN
108
106
END IF;
109
107
110
108
/* Check that new partition has an equal structure as parent does */
111
- IF NOT @extschema@.validate_relations_equality(v_parent_relid , new_partition) THEN
109
+ IF NOT @extschema@.validate_relations_equality(parent_relid , new_partition) THEN
112
110
RAISE EXCEPTION ' partition must have the exact same structure as parent' ;
113
111
END IF;
114
112
115
113
/* Get partitioning key */
116
- v_attname := attname FROM @extschema@.pathman_config WHERE partrel = v_parent_relid ;
117
- IF v_attname IS NULL THEN
118
- RAISE EXCEPTION ' table "%" is not partitioned' , v_parent_relid ::TEXT ;
114
+ part_attname := attname FROM @extschema@.pathman_config WHERE partrel = parent_relid ;
115
+ IF part_attname IS NULL THEN
116
+ RAISE EXCEPTION ' table "%" is not partitioned' , parent_relid ::TEXT ;
119
117
END IF;
120
118
121
- /* Calculate partitions count and old partition's number */
122
- v_part_count := count (* ) FROM @extschema@.pathman_partition_list WHERE parent = v_parent_relid;
123
- v_part_num := @extschema@.get_partition_hash(v_parent_relid, old_partition);
119
+ /* Fetch name of old_partition's HASH constraint */
120
+ old_constr_name = @extschema@.build_check_constraint_name(old_partition::REGCLASS,
121
+ part_attname);
122
+
123
+ /* Fetch definition of old_partition's HASH constraint */
124
+ SELECT pg_catalog .pg_get_constraintdef (oid ) FROM pg_catalog .pg_constraint
125
+ WHERE conrelid = old_partition AND conname = old_constr_name
126
+ INTO old_constr_def;
124
127
125
128
/* Detach old partition */
126
- EXECUTE format(' ALTER TABLE %s NO INHERIT %s' , old_partition, v_parent_relid);
127
- EXECUTE format(' ALTER TABLE %s DROP CONSTRAINT IF EXISTS %s' ,
128
- old_partition,
129
- @extschema@.build_check_constraint_name(old_partition::REGCLASS,
130
- v_attname));
131
-
132
- /* Attach new one */
133
- EXECUTE format(' ALTER TABLE %s INHERIT %s' , new_partition, v_parent_relid);
134
- EXECUTE format(' ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s)' ,
129
+ EXECUTE format(' ALTER TABLE %s NO INHERIT %s' , old_partition, parent_relid);
130
+ EXECUTE format(' ALTER TABLE %s DROP CONSTRAINT %s' ,
131
+ old_partition,
132
+ old_constr_name);
133
+
134
+ /* Attach the new one */
135
+ EXECUTE format(' ALTER TABLE %s INHERIT %s' , new_partition, parent_relid);
136
+ EXECUTE format(' ALTER TABLE %s ADD CONSTRAINT %s %s' ,
135
137
new_partition,
136
- @extschema@.build_check_constraint_name(new_partition::regclass,
137
- v_attname),
138
- @extschema@.build_hash_condition(new_partition::regclass,
139
- v_attname,
140
- v_part_count,
141
- v_part_num));
138
+ @extschema@.build_check_constraint_name(new_partition::REGCLASS,
139
+ part_attname),
140
+ old_constr_def);
142
141
143
142
/* Fetch init_callback from 'params' table */
144
143
WITH stub_callback(stub) as (values (0 ))
145
144
SELECT coalesce(init_callback, 0 ::REGPROCEDURE)
146
145
FROM stub_callback
147
146
LEFT JOIN @extschema@.pathman_config_params AS params
148
- ON params .partrel = v_parent_relid
149
- INTO v_init_callback ;
147
+ ON params .partrel = parent_relid
148
+ INTO p_init_callback ;
150
149
151
- PERFORM @extschema@.invoke_on_partition_created_callback(v_parent_relid,
150
+ /* Finally invoke init_callback */
151
+ PERFORM @extschema@.invoke_on_partition_created_callback(parent_relid,
152
152
new_partition,
153
- v_init_callback );
153
+ p_init_callback );
154
154
155
155
/* Invalidate cache */
156
- PERFORM @extschema@.on_update_partitions(v_parent_relid );
156
+ PERFORM @extschema@.on_update_partitions(parent_relid );
157
157
158
158
RETURN new_partition;
159
159
END
@@ -292,3 +292,14 @@ LANGUAGE C STRICT;
292
292
CREATE OR REPLACE FUNCTION @extschema@.get_hash_part_idx(INTEGER , INTEGER )
293
293
RETURNS INTEGER AS ' pg_pathman' , ' get_hash_part_idx'
294
294
LANGUAGE C STRICT;
295
+
296
+ /*
297
+ * Build hash condition for a CHECK CONSTRAINT
298
+ */
299
+ CREATE OR REPLACE FUNCTION @extschema@.build_hash_condition(
300
+ attribute_type REGTYPE,
301
+ attribute TEXT ,
302
+ partitions_count INT4,
303
+ partitions_index INT4)
304
+ RETURNS TEXT AS ' pg_pathman' , ' build_hash_condition'
305
+ LANGUAGE C STRICT;
0 commit comments