1+ /* **********************************************************************
2+ * Modify config params table
3+ **********************************************************************/
4+ ALTER TABLE @extschema@.pathman_config_params ADD COLUMN init_callback REGPROCEDURE NOT NULL DEFAULT 0 ;
5+ ALTER TABLE @extschema@.pathman_config_params ALTER COLUMN enable_parent SET DEFAULT FALSE;
6+
7+ /* Enable permissions */
8+ GRANT SELECT , INSERT, UPDATE , DELETE
9+ ON @extschema@.pathman_config, @extschema@.pathman_config_params
10+ TO public;
11+
12+ CREATE OR REPLACE FUNCTION @extschema@.check_security_policy(relation regclass)
13+ RETURNS BOOL AS ' pg_pathman' , ' check_security_policy' LANGUAGE C STRICT;
14+
15+ CREATE POLICY deny_modification ON @extschema@.pathman_config
16+ FOR ALL USING (check_security_policy(partrel));
17+
18+ CREATE POLICY deny_modification ON @extschema@.pathman_config_params
19+ FOR ALL USING (check_security_policy(partrel));
20+
21+ CREATE POLICY allow_select ON @extschema@.pathman_config FOR SELECT USING (true);
22+
23+ CREATE POLICY allow_select ON @extschema@.pathman_config_params FOR SELECT USING (true);
24+
25+ ALTER TABLE @extschema@.pathman_config ENABLE ROW LEVEL SECURITY;
26+ ALTER TABLE @extschema@.pathman_config_params ENABLE ROW LEVEL SECURITY;
27+
28+ GRANT SELECT ON @extschema@.pathman_concurrent_part_tasks TO PUBLIC;
29+
30+ /* Drop irrelevant functions */
31+ DROP FUNCTION @extschema@.invalidate_relcache(OID );
32+ DROP FUNCTION @extschema@.pathman_set_param(REGCLASS, TEXT , BOOLEAN );
33+ DROP FUNCTION @extschema@.enable_parent(REGCLASS);
34+ DROP FUNCTION @extschema@.disable_parent(relation REGCLASS);
35+ DROP FUNCTION @extschema@.enable_auto(relation REGCLASS);
36+ DROP FUNCTION @extschema@.disable_auto(relation REGCLASS);
37+ DROP FUNCTION @extschema@.partition_table_concurrently(relation regclass);
38+ DROP FUNCTION @extschema@._partition_data_concurrent(REGCLASS, ANYELEMENT, ANYELEMENT, INT , OUT BIGINT );
39+ DROP FUNCTION @extschema@.common_relation_checks(REGCLASS, TEXT );
40+
41+ /* Alter functions' modifiers */
42+ ALTER FUNCTION @extschema@.partitions_count(REGCLASS) STRICT;
43+ ALTER FUNCTION @extschema@.partition_data(REGCLASS, OUT BIGINT ) STRICT;
44+ ALTER FUNCTION @extschema@.disable_pathman_for(REGCLASS) STRICT;
45+ ALTER FUNCTION @extschema@.get_plain_schema_and_relname(REGCLASS, OUT TEXT , OUT TEXT ) STRICT;
46+
47+ /* Create functions */
48+ CREATE OR REPLACE FUNCTION @extschema@.pathman_set_param(
49+ relation REGCLASS,
50+ param TEXT ,
51+ value ANYELEMENT)
52+ RETURNS VOID AS
53+ $$
54+ BEGIN
55+ EXECUTE format(' INSERT INTO @extschema@.pathman_config_params
56+ (partrel, %1$s) VALUES ($1, $2)
57+ ON CONFLICT (partrel) DO UPDATE SET %1$s = $2' , param)
58+ USING relation, value;
59+ END
60+ $$
61+ LANGUAGE plpgsql;
62+
63+ CREATE OR REPLACE FUNCTION @extschema@.set_enable_parent(
64+ relation REGCLASS,
65+ value BOOLEAN )
66+ RETURNS VOID AS
67+ $$
68+ BEGIN
69+ PERFORM @extschema@.pathman_set_param(relation, ' enable_parent' , value);
70+ END
71+ $$
72+ LANGUAGE plpgsql STRICT;
73+
74+ /*
75+ * Partition table using ConcurrentPartWorker.
76+ */
77+ CREATE OR REPLACE FUNCTION @extschema@.partition_table_concurrently(
78+ relation REGCLASS,
79+ batch_size INTEGER DEFAULT 1000 ,
80+ sleep_time FLOAT8 DEFAULT 1 .0 )
81+ RETURNS VOID AS ' pg_pathman' , ' partition_table_concurrently'
82+ LANGUAGE C STRICT;
83+
84+ /*
85+ * Copy rows to partitions concurrently.
86+ */
87+ CREATE OR REPLACE FUNCTION @extschema@._partition_data_concurrent(
88+ relation REGCLASS,
89+ p_min ANYELEMENT DEFAULT NULL ::text ,
90+ p_max ANYELEMENT DEFAULT NULL ::text ,
91+ p_limit INT DEFAULT NULL ,
92+ OUT p_total BIGINT )
93+ AS
94+ $$
95+ DECLARE
96+ v_attr TEXT ;
97+ v_limit_clause TEXT := ' ' ;
98+ v_where_clause TEXT := ' ' ;
99+ ctids TID[];
100+
101+ BEGIN
102+ SELECT attname INTO v_attr
103+ FROM @extschema@.pathman_config WHERE partrel = relation;
104+
105+ p_total := 0 ;
106+
107+ /* Format LIMIT clause if needed */
108+ IF NOT p_limit IS NULL THEN
109+ v_limit_clause := format(' LIMIT %s' , p_limit);
110+ END IF;
111+
112+ /* Format WHERE clause if needed */
113+ IF NOT p_min IS NULL THEN
114+ v_where_clause := format(' %1$s >= $1' , v_attr);
115+ END IF;
116+
117+ IF NOT p_max IS NULL THEN
118+ IF NOT p_min IS NULL THEN
119+ v_where_clause := v_where_clause || ' AND ' ;
120+ END IF;
121+ v_where_clause := v_where_clause || format(' %1$s < $2' , v_attr);
122+ END IF;
123+
124+ IF v_where_clause != ' ' THEN
125+ v_where_clause := ' WHERE ' || v_where_clause;
126+ END IF;
127+
128+ /* Lock rows and copy data */
129+ RAISE NOTICE ' Copying data to partitions...' ;
130+ EXECUTE format(' SELECT array(SELECT ctid FROM ONLY %1$s %2$s %3$s FOR UPDATE NOWAIT)' ,
131+ relation, v_where_clause, v_limit_clause)
132+ USING p_min, p_max
133+ INTO ctids;
134+
135+ EXECUTE format('
136+ WITH data AS (
137+ DELETE FROM ONLY %1$s WHERE ctid = ANY($1) RETURNING *)
138+ INSERT INTO %1$s SELECT * FROM data' ,
139+ relation)
140+ USING ctids;
141+
142+ /* Get number of inserted rows */
143+ GET DIAGNOSTICS p_total = ROW_COUNT;
144+ RETURN;
145+ END
146+ $$
147+ LANGUAGE plpgsql
148+ SET pg_pathman .enable_partitionfilter = on ; /* ensures that PartitionFilter is ON */
149+
150+ /*
151+ * Aggregates several common relation checks before partitioning.
152+ * Suitable for every partitioning type.
153+ */
154+ CREATE OR REPLACE FUNCTION @extschema@.common_relation_checks(
155+ relation REGCLASS,
156+ p_attribute TEXT )
157+ RETURNS BOOLEAN AS
158+ $$
159+ DECLARE
160+ v_rec RECORD;
161+ is_referenced BOOLEAN ;
162+ rel_persistence CHAR ;
163+
164+ BEGIN
165+ /* Ignore temporary tables */
166+ SELECT relpersistence FROM pg_catalog .pg_class
167+ WHERE oid = relation INTO rel_persistence;
168+
169+ IF rel_persistence = ' t' ::CHAR THEN
170+ RAISE EXCEPTION ' temporary table "%" cannot be partitioned' ,
171+ relation::TEXT ;
172+ END IF;
173+
174+ IF EXISTS (SELECT * FROM @extschema@.pathman_config
175+ WHERE partrel = relation) THEN
176+ RAISE EXCEPTION ' relation "%" has already been partitioned' , relation;
177+ END IF;
178+
179+ IF @extschema@.is_attribute_nullable(relation, p_attribute) THEN
180+ RAISE EXCEPTION ' partitioning key ' ' %' ' must be NOT NULL' , p_attribute;
181+ END IF;
182+
183+ /* Check if there are foreign keys that reference the relation */
184+ FOR v_rec IN (SELECT * FROM pg_catalog .pg_constraint
185+ WHERE confrelid = relation::REGCLASS::OID )
186+ LOOP
187+ is_referenced := TRUE;
188+ RAISE WARNING ' foreign key "%" references relation "%"' ,
189+ v_rec .conname , relation;
190+ END LOOP;
191+
192+ IF is_referenced THEN
193+ RAISE EXCEPTION ' relation "%" is referenced from other relations' , relation;
194+ END IF;
195+
196+ RETURN TRUE;
197+ END
198+ $$
199+ LANGUAGE plpgsql;
0 commit comments