@@ -18,14 +18,6 @@ CREATE OR REPLACE FUNCTION @extschema@.create_hash_partitions(
1818 partition_data BOOLEAN DEFAULT TRUE)
1919RETURNS INTEGER AS
2020$$
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-
2921BEGIN
3022 PERFORM @extschema@.validate_relname(parent_relid);
3123
4032 attribute := lower (attribute);
4133 PERFORM @extschema@.common_relation_checks(parent_relid, attribute);
4234
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-
5035 /* Insert new entry to pathman config */
5136 INSERT INTO @extschema@.pathman_config (partrel, attname, parttype)
5237 VALUES (parent_relid, attribute, 1 );
@@ -74,29 +59,42 @@ SET client_min_messages = WARNING;
7459
7560/*
7661 * 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?
7865 */
7966CREATE OR REPLACE FUNCTION @extschema@.replace_hash_partition(
8067 old_partition REGCLASS,
81- new_partition REGCLASS)
68+ new_partition REGCLASS,
69+ lock_parent BOOL DEFAULT TRUE)
8270RETURNS REGCLASS AS
8371$$
8472DECLARE
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 */
8677 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+
9180BEGIN
9281 PERFORM @extschema@.validate_relname(old_partition);
9382 PERFORM @extschema@.validate_relname(new_partition);
9483
9584 /* 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;
9794
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);
10098
10199 /* Ignore temporary tables */
102100 SELECT relpersistence FROM pg_catalog .pg_class
@@ -108,52 +106,54 @@ BEGIN
108106 END IF;
109107
110108 /* 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
112110 RAISE EXCEPTION ' partition must have the exact same structure as parent' ;
113111 END IF;
114112
115113 /* 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 ;
119117 END IF;
120118
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;
124127
125128 /* 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' ,
135137 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);
142141
143142 /* Fetch init_callback from 'params' table */
144143 WITH stub_callback(stub) as (values (0 ))
145144 SELECT coalesce(init_callback, 0 ::REGPROCEDURE)
146145 FROM stub_callback
147146 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 ;
150149
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,
152152 new_partition,
153- v_init_callback );
153+ p_init_callback );
154154
155155 /* Invalidate cache */
156- PERFORM @extschema@.on_update_partitions(v_parent_relid );
156+ PERFORM @extschema@.on_update_partitions(parent_relid );
157157
158158 RETURN new_partition;
159159END
@@ -292,3 +292,14 @@ LANGUAGE C STRICT;
292292CREATE OR REPLACE FUNCTION @extschema@.get_hash_part_idx(INTEGER , INTEGER )
293293RETURNS INTEGER AS ' pg_pathman' , ' get_hash_part_idx'
294294LANGUAGE 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