Skip to content

Commit 657ac2b

Browse files
committed
pathman: validate relation before attach
1 parent b764fc2 commit 657ac2b

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

contrib/pg_pathman/expected/pg_pathman.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,18 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt BETWEEN '2014-11-15' A
588588
Index Cond: (dt <= 'Thu Jan 15 00:00:00 2015'::timestamp without time zone)
589589
(4 rows)
590590

591+
CREATE TABLE test.range_rel_test1 (
592+
id SERIAL PRIMARY KEY,
593+
dt TIMESTAMP,
594+
txt TEXT,
595+
abc INTEGER);
596+
SELECT pathman.attach_range_partition('test.range_rel', 'test.range_rel_test1', '2013-01-01'::DATE, '2014-01-01'::DATE);
597+
ERROR: Partition must have the exact same structure as parent P0001
598+
CREATE TABLE test.range_rel_test2 (
599+
id SERIAL PRIMARY KEY,
600+
dt TIMESTAMP);
601+
SELECT pathman.attach_range_partition('test.range_rel', 'test.range_rel_test2', '2013-01-01'::DATE, '2014-01-01'::DATE);
602+
ERROR: Partition must have the exact same structure as parent P0001
591603
/*
592604
* Clean up
593605
*/

contrib/pg_pathman/init.sql

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,34 @@ END
233233
$$
234234
LANGUAGE plpgsql;
235235

236+
/*
237+
* Check if two relations have equal structures
238+
*/
239+
CREATE OR REPLACE FUNCTION @extschema@.validate_relations_equality(relation1 OID, relation2 OID)
240+
RETURNS BOOLEAN AS
241+
$$
242+
DECLARE
243+
rec RECORD;
244+
BEGIN
245+
FOR rec IN (
246+
WITH
247+
a1 AS (select * from pg_attribute where attrelid = relation1 and attnum > 0),
248+
a2 AS (select * from pg_attribute where attrelid = relation2 and attnum > 0)
249+
SELECT a1.attname name1, a2.attname name2, a1.atttypid type1, a2.atttypid type2
250+
FROM a1
251+
FULL JOIN a2 ON a1.attnum = a2.attnum
252+
)
253+
LOOP
254+
IF rec.name1 IS NULL OR rec.name2 IS NULL OR rec.name1 != rec.name2 THEN
255+
RETURN False;
256+
END IF;
257+
END LOOP;
258+
259+
RETURN True;
260+
END
261+
$$
262+
LANGUAGE plpgsql;
263+
236264
/*
237265
* Check if regclass if date or timestamp
238266
*/

contrib/pg_pathman/range.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,10 @@ BEGIN
886886
RAISE EXCEPTION 'Specified range overlaps with existing partitions';
887887
END IF;
888888

889+
IF NOT @extschema@.validate_relations_equality(p_relation::regclass, p_partition::regclass) THEN
890+
RAISE EXCEPTION 'Partition must have the exact same structure as parent';
891+
END IF;
892+
889893
/* Set inheritance */
890894
EXECUTE format('ALTER TABLE %s INHERIT %s'
891895
, p_partition

contrib/pg_pathman/sql/pg_pathman.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,16 @@ SELECT pathman.attach_range_partition('test.range_rel', 'test.range_rel_archive'
138138
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt BETWEEN '2014-11-15' AND '2015-01-15';
139139
SELECT pathman.detach_range_partition('test.range_rel_archive');
140140
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt BETWEEN '2014-11-15' AND '2015-01-15';
141+
CREATE TABLE test.range_rel_test1 (
142+
id SERIAL PRIMARY KEY,
143+
dt TIMESTAMP,
144+
txt TEXT,
145+
abc INTEGER);
146+
SELECT pathman.attach_range_partition('test.range_rel', 'test.range_rel_test1', '2013-01-01'::DATE, '2014-01-01'::DATE);
147+
CREATE TABLE test.range_rel_test2 (
148+
id SERIAL PRIMARY KEY,
149+
dt TIMESTAMP);
150+
SELECT pathman.attach_range_partition('test.range_rel', 'test.range_rel_test2', '2013-01-01'::DATE, '2014-01-01'::DATE);
141151

142152
/*
143153
* Clean up

0 commit comments

Comments
 (0)