1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
DROP EXTENSION IF EXISTS pg_rewrite;
CREATE EXTENSION pg_rewrite;
CREATE TABLE tab1(i int PRIMARY KEY, j int, k int);
-- If a dropped column is encountered, the source tuple should be converted
-- so it matches the destination table.
ALTER TABLE tab1 DROP COLUMN k;
ALTER TABLE tab1 ADD COLUMN k int;
INSERT INTO tab1(i, j, k)
SELECT i, i / 2, i
FROM generate_series(0, 1023) g(i);
CREATE TABLE tab1_new(i int PRIMARY KEY, j int, k int) PARTITION BY RANGE(i);
CREATE TABLE tab1_new_part_1 PARTITION OF tab1_new FOR VALUES FROM (0) TO (256);
CREATE TABLE tab1_new_part_2 PARTITION OF tab1_new FOR VALUES FROM (256) TO (512);
CREATE TABLE tab1_new_part_3 PARTITION OF tab1_new FOR VALUES FROM (512) TO (768);
CREATE TABLE tab1_new_part_4 PARTITION OF tab1_new FOR VALUES FROM (768) TO (1024);
-- Also test handling of constraints that require "manual" validation.
ALTER TABLE tab1 ADD CHECK (k >= 0);
CREATE TABLE tab1_fk(i int REFERENCES tab1);
INSERT INTO tab1_fk(i) VALUES (1);
\d tab1
-- Process the table.
SELECT rewrite_table('tab1', 'tab1_new', 'tab1_orig');
-- tab1 should now be partitioned.
\d tab1
-- Validate the constraints.
ALTER TABLE tab1 VALIDATE CONSTRAINT tab1_k_check2;
ALTER TABLE tab1_fk VALIDATE CONSTRAINT tab1_fk_i_fkey2;
\d tab1
EXPLAIN (COSTS off) SELECT * FROM tab1;
-- Check that the contents has not changed.
SELECT count(*) FROM tab1;
SELECT *
FROM tab1 t FULL JOIN tab1_orig o ON t.i = o.i
WHERE t.i ISNULL OR o.i ISNULL;
-- List partitioning
CREATE TABLE tab2(i int, j int, PRIMARY KEY (i, j));
INSERT INTO tab2(i, j)
SELECT i, j
FROM generate_series(1, 4) g(i), generate_series(1, 4) h(j);
CREATE TABLE tab2_new(i int, j int, PRIMARY KEY (i, j)) PARTITION BY LIST(i);
CREATE TABLE tab2_new_part_1 PARTITION OF tab2_new FOR VALUES IN (1);
CREATE TABLE tab2_new_part_2 PARTITION OF tab2_new FOR VALUES IN (2);
CREATE TABLE tab2_new_part_3 PARTITION OF tab2_new FOR VALUES IN (3);
CREATE TABLE tab2_new_part_4 PARTITION OF tab2_new FOR VALUES IN (4);
SELECT rewrite_table('tab2', 'tab2_new', 'tab2_orig');
TABLE tab2_new_part_1;
TABLE tab2_new_part_2;
TABLE tab2_new_part_3;
TABLE tab2_new_part_4;
-- Hash partitioning
CREATE TABLE tab3(i int, j int, PRIMARY KEY (i, j));
INSERT INTO tab3(i, j)
SELECT i, j
FROM generate_series(1, 4) g(i), generate_series(1, 4) h(j);
CREATE TABLE tab3_new(i int, j int, PRIMARY KEY (i, j)) PARTITION BY HASH(i);
CREATE TABLE tab3_new_part_1 PARTITION OF tab3_new FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE tab3_new_part_2 PARTITION OF tab3_new FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE tab3_new_part_3 PARTITION OF tab3_new FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE tab3_new_part_4 PARTITION OF tab3_new FOR VALUES WITH (MODULUS 4, REMAINDER 3);
SELECT rewrite_table('tab3', 'tab3_new', 'tab3_orig');
TABLE tab3_new_part_1;
TABLE tab3_new_part_2;
TABLE tab3_new_part_3;
TABLE tab3_new_part_4;
-- Change of precision and scale of a numeric data type.
CREATE TABLE tab4(i int PRIMARY KEY, j numeric(3, 1));
INSERT INTO tab4(i, j) VALUES (1, 0.1);
CREATE TABLE tab4_new(i int PRIMARY KEY, j numeric(4, 2));
TABLE tab4;
SELECT rewrite_table('tab4', 'tab4_new', 'tab4_orig');
TABLE tab4;
-- One more test for "manual" validation of FKs, this time we rewrite the PK
-- table. The NOT VALID constraint cannot be used if the FK table is
-- partitioned and if PG version is < 18, so we need a separate test.
CREATE TABLE tab1_pk(i int primary key);
INSERT INTO tab1_pk(i) VALUES (1);
CREATE TABLE tab1_pk_new(i bigint primary key);
DROP TABLE tab1_fk;
CREATE TABLE tab1_fk(i int REFERENCES tab1_pk);
INSERT INTO tab1_fk(i) VALUES (1);
\d tab1_pk
SELECT rewrite_table('tab1_pk', 'tab1_pk_new', 'tab1_pk_orig');
\d tab1_pk
ALTER TABLE tab1_fk VALIDATE CONSTRAINT tab1_fk_i_fkey2;
\d tab1_pk
-- For the partitioned FK table, test at least that the FK creation is skipped
-- (i.e. ERROR saying that NOT VALID is not supported is no raised)
DROP TABLE tab1_fk;
CREATE TABLE tab1_fk(i int REFERENCES tab1_pk) PARTITION BY RANGE (i);
CREATE TABLE tab1_fk_1 PARTITION OF tab1_fk DEFAULT;
INSERT INTO tab1_fk(i) VALUES (1);
ALTER TABLE tab1_pk_orig RENAME TO tab1_pk_new;
TRUNCATE TABLE tab1_pk_new;
\d tab1_fk
SELECT rewrite_table('tab1_pk', 'tab1_pk_new', 'tab1_pk_orig');
-- Note that tab1_fk still references tab1_pk_orig - that's expected.
\d tab1_fk
-- The same once again, but now rewrite the FK table.
DROP TABLE tab1_fk;
DROP TABLE tab1_pk;
ALTER TABLE tab1_pk_orig RENAME TO tab1_pk;
CREATE TABLE tab1_fk(i int PRIMARY KEY REFERENCES tab1_pk);
INSERT INTO tab1_fk(i) VALUES (1);
CREATE TABLE tab1_fk_new(i int PRIMARY KEY) PARTITION BY RANGE (i);
CREATE TABLE tab1_fk_new_1 PARTITION OF tab1_fk_new DEFAULT;
\d tab1_fk
SELECT rewrite_table('tab1_fk', 'tab1_fk_new', 'tab1_fk_orig');
\d tab1_fk
-- Check if sequence on the target table is synchronized with that of the
-- source table.
CREATE TABLE tab5(i int primary key generated always as identity);
CREATE TABLE tab5_new(i int primary key generated always as identity);
INSERT INTO tab5(i) VALUES (DEFAULT);
SELECT rewrite_table('tab5', 'tab5_new', 'tab5_orig');
INSERT INTO tab5(i) VALUES (DEFAULT);
SELECT i FROM tab5 ORDER BY i;
-- The same with serial column.
CREATE TABLE tab6(i serial primary key);
CREATE TABLE tab6_new(i serial primary key);
INSERT INTO tab6(i) VALUES (DEFAULT);
SELECT rewrite_table('tab6', 'tab6_new', 'tab6_orig');
INSERT INTO tab6(i) VALUES (DEFAULT);
SELECT i FROM tab6 ORDER BY i;
|