mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-05 00:58:04 +02:00
9710d3d4a8
When running TRUNCATE CASCADE on a child of a partitioned table referenced by another partitioned table, the truncate was not applied to partitions of the referencing table; this could leave rows violating the constraint in the referencing partitioned table. Repair by walking the pg_constraint chain all the way up to the topmost referencing table. Note: any partitioned tables containing FKs that reference other partitioned tables should be checked for possible violating rows, if TRUNCATE has occurred in partitions of the referenced table. Reported-by: Christophe Courtois Author: Jehan-Guillaume de Rorthais Discussion: https://postgr.es/m/20200204183906.115f693e@firost
595 lines
16 KiB
Plaintext
595 lines
16 KiB
Plaintext
-- Test basic TRUNCATE functionality.
|
|
CREATE TABLE truncate_a (col1 integer primary key);
|
|
INSERT INTO truncate_a VALUES (1);
|
|
INSERT INTO truncate_a VALUES (2);
|
|
SELECT * FROM truncate_a;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
(2 rows)
|
|
|
|
-- Roll truncate back
|
|
BEGIN;
|
|
TRUNCATE truncate_a;
|
|
ROLLBACK;
|
|
SELECT * FROM truncate_a;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
(2 rows)
|
|
|
|
-- Commit the truncate this time
|
|
BEGIN;
|
|
TRUNCATE truncate_a;
|
|
COMMIT;
|
|
SELECT * FROM truncate_a;
|
|
col1
|
|
------
|
|
(0 rows)
|
|
|
|
-- Test foreign-key checks
|
|
CREATE TABLE trunc_b (a int REFERENCES truncate_a);
|
|
CREATE TABLE trunc_c (a serial PRIMARY KEY);
|
|
CREATE TABLE trunc_d (a int REFERENCES trunc_c);
|
|
CREATE TABLE trunc_e (a int REFERENCES truncate_a, b int REFERENCES trunc_c);
|
|
TRUNCATE TABLE truncate_a; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_b" references "truncate_a".
|
|
HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE truncate_a,trunc_b; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_e" references "truncate_a".
|
|
HINT: Truncate table "trunc_e" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE truncate_a,trunc_b,trunc_e; -- ok
|
|
TRUNCATE TABLE truncate_a,trunc_e; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_b" references "truncate_a".
|
|
HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_d" references "trunc_c".
|
|
HINT: Truncate table "trunc_d" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,trunc_d; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_e" references "trunc_c".
|
|
HINT: Truncate table "trunc_e" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,trunc_d,trunc_e; -- ok
|
|
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_b" references "truncate_a".
|
|
HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a,trunc_b; -- ok
|
|
TRUNCATE TABLE truncate_a RESTRICT; -- fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_b" references "truncate_a".
|
|
HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE truncate_a CASCADE; -- ok
|
|
NOTICE: truncate cascades to table "trunc_b"
|
|
NOTICE: truncate cascades to table "trunc_e"
|
|
-- circular references
|
|
ALTER TABLE truncate_a ADD FOREIGN KEY (col1) REFERENCES trunc_c;
|
|
-- Add some data to verify that truncating actually works ...
|
|
INSERT INTO trunc_c VALUES (1);
|
|
INSERT INTO truncate_a VALUES (1);
|
|
INSERT INTO trunc_b VALUES (1);
|
|
INSERT INTO trunc_d VALUES (1);
|
|
INSERT INTO trunc_e VALUES (1,1);
|
|
TRUNCATE TABLE trunc_c;
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "truncate_a" references "trunc_c".
|
|
HINT: Truncate table "truncate_a" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,truncate_a;
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_d" references "trunc_c".
|
|
HINT: Truncate table "trunc_d" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,truncate_a,trunc_d;
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_e" references "trunc_c".
|
|
HINT: Truncate table "trunc_e" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,truncate_a,trunc_d,trunc_e;
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "trunc_b" references "truncate_a".
|
|
HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
|
|
TRUNCATE TABLE trunc_c,truncate_a,trunc_d,trunc_e,trunc_b;
|
|
-- Verify that truncating did actually work
|
|
SELECT * FROM truncate_a
|
|
UNION ALL
|
|
SELECT * FROM trunc_c
|
|
UNION ALL
|
|
SELECT * FROM trunc_b
|
|
UNION ALL
|
|
SELECT * FROM trunc_d;
|
|
col1
|
|
------
|
|
(0 rows)
|
|
|
|
SELECT * FROM trunc_e;
|
|
a | b
|
|
---+---
|
|
(0 rows)
|
|
|
|
-- Add data again to test TRUNCATE ... CASCADE
|
|
INSERT INTO trunc_c VALUES (1);
|
|
INSERT INTO truncate_a VALUES (1);
|
|
INSERT INTO trunc_b VALUES (1);
|
|
INSERT INTO trunc_d VALUES (1);
|
|
INSERT INTO trunc_e VALUES (1,1);
|
|
TRUNCATE TABLE trunc_c CASCADE; -- ok
|
|
NOTICE: truncate cascades to table "truncate_a"
|
|
NOTICE: truncate cascades to table "trunc_d"
|
|
NOTICE: truncate cascades to table "trunc_e"
|
|
NOTICE: truncate cascades to table "trunc_b"
|
|
SELECT * FROM truncate_a
|
|
UNION ALL
|
|
SELECT * FROM trunc_c
|
|
UNION ALL
|
|
SELECT * FROM trunc_b
|
|
UNION ALL
|
|
SELECT * FROM trunc_d;
|
|
col1
|
|
------
|
|
(0 rows)
|
|
|
|
SELECT * FROM trunc_e;
|
|
a | b
|
|
---+---
|
|
(0 rows)
|
|
|
|
DROP TABLE truncate_a,trunc_c,trunc_b,trunc_d,trunc_e CASCADE;
|
|
-- Test TRUNCATE with inheritance
|
|
CREATE TABLE trunc_f (col1 integer primary key);
|
|
INSERT INTO trunc_f VALUES (1);
|
|
INSERT INTO trunc_f VALUES (2);
|
|
CREATE TABLE trunc_fa (col2a text) INHERITS (trunc_f);
|
|
INSERT INTO trunc_fa VALUES (3, 'three');
|
|
CREATE TABLE trunc_fb (col2b int) INHERITS (trunc_f);
|
|
INSERT INTO trunc_fb VALUES (4, 444);
|
|
CREATE TABLE trunc_faa (col3 text) INHERITS (trunc_fa);
|
|
INSERT INTO trunc_faa VALUES (5, 'five', 'FIVE');
|
|
BEGIN;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
(5 rows)
|
|
|
|
TRUNCATE trunc_f;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
(0 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
(5 rows)
|
|
|
|
TRUNCATE ONLY trunc_f;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
3
|
|
4
|
|
5
|
|
(3 rows)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
(5 rows)
|
|
|
|
SELECT * FROM trunc_fa;
|
|
col1 | col2a
|
|
------+-------
|
|
3 | three
|
|
5 | five
|
|
(2 rows)
|
|
|
|
SELECT * FROM trunc_faa;
|
|
col1 | col2a | col3
|
|
------+-------+------
|
|
5 | five | FIVE
|
|
(1 row)
|
|
|
|
TRUNCATE ONLY trunc_fb, ONLY trunc_fa;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
5
|
|
(3 rows)
|
|
|
|
SELECT * FROM trunc_fa;
|
|
col1 | col2a
|
|
------+-------
|
|
5 | five
|
|
(1 row)
|
|
|
|
SELECT * FROM trunc_faa;
|
|
col1 | col2a | col3
|
|
------+-------+------
|
|
5 | five | FIVE
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
BEGIN;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
(5 rows)
|
|
|
|
SELECT * FROM trunc_fa;
|
|
col1 | col2a
|
|
------+-------
|
|
3 | three
|
|
5 | five
|
|
(2 rows)
|
|
|
|
SELECT * FROM trunc_faa;
|
|
col1 | col2a | col3
|
|
------+-------+------
|
|
5 | five | FIVE
|
|
(1 row)
|
|
|
|
TRUNCATE ONLY trunc_fb, trunc_fa;
|
|
SELECT * FROM trunc_f;
|
|
col1
|
|
------
|
|
1
|
|
2
|
|
(2 rows)
|
|
|
|
SELECT * FROM trunc_fa;
|
|
col1 | col2a
|
|
------+-------
|
|
(0 rows)
|
|
|
|
SELECT * FROM trunc_faa;
|
|
col1 | col2a | col3
|
|
------+-------+------
|
|
(0 rows)
|
|
|
|
ROLLBACK;
|
|
DROP TABLE trunc_f CASCADE;
|
|
NOTICE: drop cascades to 3 other objects
|
|
DETAIL: drop cascades to table trunc_fa
|
|
drop cascades to table trunc_faa
|
|
drop cascades to table trunc_fb
|
|
-- Test ON TRUNCATE triggers
|
|
CREATE TABLE trunc_trigger_test (f1 int, f2 text, f3 text);
|
|
CREATE TABLE trunc_trigger_log (tgop text, tglevel text, tgwhen text,
|
|
tgargv text, tgtable name, rowcount bigint);
|
|
CREATE FUNCTION trunctrigger() RETURNS trigger as $$
|
|
declare c bigint;
|
|
begin
|
|
execute 'select count(*) from ' || quote_ident(tg_table_name) into c;
|
|
insert into trunc_trigger_log values
|
|
(TG_OP, TG_LEVEL, TG_WHEN, TG_ARGV[0], tg_table_name, c);
|
|
return null;
|
|
end;
|
|
$$ LANGUAGE plpgsql;
|
|
-- basic before trigger
|
|
INSERT INTO trunc_trigger_test VALUES(1, 'foo', 'bar'), (2, 'baz', 'quux');
|
|
CREATE TRIGGER t
|
|
BEFORE TRUNCATE ON trunc_trigger_test
|
|
FOR EACH STATEMENT
|
|
EXECUTE PROCEDURE trunctrigger('before trigger truncate');
|
|
SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
|
|
Row count in test table
|
|
-------------------------
|
|
2
|
|
(1 row)
|
|
|
|
SELECT * FROM trunc_trigger_log;
|
|
tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
|
|
------+---------+--------+--------+---------+----------
|
|
(0 rows)
|
|
|
|
TRUNCATE trunc_trigger_test;
|
|
SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
|
|
Row count in test table
|
|
-------------------------
|
|
0
|
|
(1 row)
|
|
|
|
SELECT * FROM trunc_trigger_log;
|
|
tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
|
|
----------+-----------+--------+-------------------------+--------------------+----------
|
|
TRUNCATE | STATEMENT | BEFORE | before trigger truncate | trunc_trigger_test | 2
|
|
(1 row)
|
|
|
|
DROP TRIGGER t ON trunc_trigger_test;
|
|
truncate trunc_trigger_log;
|
|
-- same test with an after trigger
|
|
INSERT INTO trunc_trigger_test VALUES(1, 'foo', 'bar'), (2, 'baz', 'quux');
|
|
CREATE TRIGGER tt
|
|
AFTER TRUNCATE ON trunc_trigger_test
|
|
FOR EACH STATEMENT
|
|
EXECUTE PROCEDURE trunctrigger('after trigger truncate');
|
|
SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
|
|
Row count in test table
|
|
-------------------------
|
|
2
|
|
(1 row)
|
|
|
|
SELECT * FROM trunc_trigger_log;
|
|
tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
|
|
------+---------+--------+--------+---------+----------
|
|
(0 rows)
|
|
|
|
TRUNCATE trunc_trigger_test;
|
|
SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
|
|
Row count in test table
|
|
-------------------------
|
|
0
|
|
(1 row)
|
|
|
|
SELECT * FROM trunc_trigger_log;
|
|
tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
|
|
----------+-----------+--------+------------------------+--------------------+----------
|
|
TRUNCATE | STATEMENT | AFTER | after trigger truncate | trunc_trigger_test | 0
|
|
(1 row)
|
|
|
|
DROP TABLE trunc_trigger_test;
|
|
DROP TABLE trunc_trigger_log;
|
|
DROP FUNCTION trunctrigger();
|
|
-- test TRUNCATE ... RESTART IDENTITY
|
|
CREATE SEQUENCE truncate_a_id1 START WITH 33;
|
|
CREATE TABLE truncate_a (id serial,
|
|
id1 integer default nextval('truncate_a_id1'));
|
|
ALTER SEQUENCE truncate_a_id1 OWNED BY truncate_a.id1;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
SELECT * FROM truncate_a;
|
|
id | id1
|
|
----+-----
|
|
1 | 33
|
|
2 | 34
|
|
(2 rows)
|
|
|
|
TRUNCATE truncate_a;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
SELECT * FROM truncate_a;
|
|
id | id1
|
|
----+-----
|
|
3 | 35
|
|
4 | 36
|
|
(2 rows)
|
|
|
|
TRUNCATE truncate_a RESTART IDENTITY;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
SELECT * FROM truncate_a;
|
|
id | id1
|
|
----+-----
|
|
1 | 33
|
|
2 | 34
|
|
(2 rows)
|
|
|
|
CREATE TABLE truncate_b (id int GENERATED ALWAYS AS IDENTITY (START WITH 44));
|
|
INSERT INTO truncate_b DEFAULT VALUES;
|
|
INSERT INTO truncate_b DEFAULT VALUES;
|
|
SELECT * FROM truncate_b;
|
|
id
|
|
----
|
|
44
|
|
45
|
|
(2 rows)
|
|
|
|
TRUNCATE truncate_b;
|
|
INSERT INTO truncate_b DEFAULT VALUES;
|
|
INSERT INTO truncate_b DEFAULT VALUES;
|
|
SELECT * FROM truncate_b;
|
|
id
|
|
----
|
|
46
|
|
47
|
|
(2 rows)
|
|
|
|
TRUNCATE truncate_b RESTART IDENTITY;
|
|
INSERT INTO truncate_b DEFAULT VALUES;
|
|
INSERT INTO truncate_b DEFAULT VALUES;
|
|
SELECT * FROM truncate_b;
|
|
id
|
|
----
|
|
44
|
|
45
|
|
(2 rows)
|
|
|
|
-- check rollback of a RESTART IDENTITY operation
|
|
BEGIN;
|
|
TRUNCATE truncate_a RESTART IDENTITY;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
SELECT * FROM truncate_a;
|
|
id | id1
|
|
----+-----
|
|
1 | 33
|
|
(1 row)
|
|
|
|
ROLLBACK;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
INSERT INTO truncate_a DEFAULT VALUES;
|
|
SELECT * FROM truncate_a;
|
|
id | id1
|
|
----+-----
|
|
1 | 33
|
|
2 | 34
|
|
3 | 35
|
|
4 | 36
|
|
(4 rows)
|
|
|
|
DROP TABLE truncate_a;
|
|
SELECT nextval('truncate_a_id1'); -- fail, seq should have been dropped
|
|
ERROR: relation "truncate_a_id1" does not exist
|
|
LINE 1: SELECT nextval('truncate_a_id1');
|
|
^
|
|
-- partitioned table
|
|
CREATE TABLE truncparted (a int, b char) PARTITION BY LIST (a);
|
|
-- error, can't truncate a partitioned table
|
|
TRUNCATE ONLY truncparted;
|
|
ERROR: cannot truncate only a partitioned table
|
|
HINT: Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.
|
|
CREATE TABLE truncparted1 PARTITION OF truncparted FOR VALUES IN (1);
|
|
INSERT INTO truncparted VALUES (1, 'a');
|
|
-- error, must truncate partitions
|
|
TRUNCATE ONLY truncparted;
|
|
ERROR: cannot truncate only a partitioned table
|
|
HINT: Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.
|
|
TRUNCATE truncparted;
|
|
DROP TABLE truncparted;
|
|
-- foreign key on partitioned table: partition key is referencing column.
|
|
-- Make sure truncate did execute on all tables
|
|
CREATE FUNCTION tp_ins_data() RETURNS void LANGUAGE plpgsql AS $$
|
|
BEGIN
|
|
INSERT INTO truncprim VALUES (1), (100), (150);
|
|
INSERT INTO truncpart VALUES (1), (100), (150);
|
|
END
|
|
$$;
|
|
CREATE FUNCTION tp_chk_data(OUT pktb regclass, OUT pkval int, OUT fktb regclass, OUT fkval int)
|
|
RETURNS SETOF record LANGUAGE plpgsql AS $$
|
|
BEGIN
|
|
RETURN QUERY SELECT
|
|
pk.tableoid::regclass, pk.a, fk.tableoid::regclass, fk.a
|
|
FROM truncprim pk FULL JOIN truncpart fk USING (a)
|
|
ORDER BY 2, 4;
|
|
END
|
|
$$;
|
|
CREATE TABLE truncprim (a int PRIMARY KEY);
|
|
CREATE TABLE truncpart (a int REFERENCES truncprim)
|
|
PARTITION BY RANGE (a);
|
|
CREATE TABLE truncpart_1 PARTITION OF truncpart FOR VALUES FROM (0) TO (100);
|
|
CREATE TABLE truncpart_2 PARTITION OF truncpart FOR VALUES FROM (100) TO (200)
|
|
PARTITION BY RANGE (a);
|
|
CREATE TABLE truncpart_2_1 PARTITION OF truncpart_2 FOR VALUES FROM (100) TO (150);
|
|
CREATE TABLE truncpart_2_d PARTITION OF truncpart_2 DEFAULT;
|
|
TRUNCATE TABLE truncprim; -- should fail
|
|
ERROR: cannot truncate a table referenced in a foreign key constraint
|
|
DETAIL: Table "truncpart" references "truncprim".
|
|
HINT: Truncate table "truncpart" at the same time, or use TRUNCATE ... CASCADE.
|
|
select tp_ins_data();
|
|
tp_ins_data
|
|
-------------
|
|
|
|
(1 row)
|
|
|
|
-- should truncate everything
|
|
TRUNCATE TABLE truncprim, truncpart;
|
|
select * from tp_chk_data();
|
|
pktb | pkval | fktb | fkval
|
|
------+-------+------+-------
|
|
(0 rows)
|
|
|
|
select tp_ins_data();
|
|
tp_ins_data
|
|
-------------
|
|
|
|
(1 row)
|
|
|
|
-- should truncate everything
|
|
TRUNCATE TABLE truncprim CASCADE;
|
|
NOTICE: truncate cascades to table "truncpart"
|
|
NOTICE: truncate cascades to table "truncpart_1"
|
|
NOTICE: truncate cascades to table "truncpart_2"
|
|
NOTICE: truncate cascades to table "truncpart_2_1"
|
|
NOTICE: truncate cascades to table "truncpart_2_d"
|
|
SELECT * FROM tp_chk_data();
|
|
pktb | pkval | fktb | fkval
|
|
------+-------+------+-------
|
|
(0 rows)
|
|
|
|
SELECT tp_ins_data();
|
|
tp_ins_data
|
|
-------------
|
|
|
|
(1 row)
|
|
|
|
-- should truncate all partitions
|
|
TRUNCATE TABLE truncpart;
|
|
SELECT * FROM tp_chk_data();
|
|
pktb | pkval | fktb | fkval
|
|
-----------+-------+------+-------
|
|
truncprim | 1 | |
|
|
truncprim | 100 | |
|
|
truncprim | 150 | |
|
|
(3 rows)
|
|
|
|
DROP TABLE truncprim, truncpart;
|
|
DROP FUNCTION tp_ins_data(), tp_chk_data();
|
|
-- test cascade when referencing a partitioned table
|
|
CREATE TABLE trunc_a (a INT PRIMARY KEY) PARTITION BY RANGE (a);
|
|
CREATE TABLE trunc_a1 PARTITION OF trunc_a FOR VALUES FROM (0) TO (10);
|
|
CREATE TABLE trunc_a2 PARTITION OF trunc_a FOR VALUES FROM (10) TO (20)
|
|
PARTITION BY RANGE (a);
|
|
CREATE TABLE trunc_a21 PARTITION OF trunc_a2 FOR VALUES FROM (10) TO (12);
|
|
CREATE TABLE trunc_a22 PARTITION OF trunc_a2 FOR VALUES FROM (12) TO (16);
|
|
CREATE TABLE trunc_a2d PARTITION OF trunc_a2 DEFAULT;
|
|
CREATE TABLE trunc_a3 PARTITION OF trunc_a FOR VALUES FROM (20) TO (30);
|
|
INSERT INTO trunc_a VALUES (0), (5), (10), (15), (20), (25);
|
|
-- truncate a partition cascading to a table
|
|
CREATE TABLE ref_b (
|
|
b INT PRIMARY KEY,
|
|
a INT REFERENCES trunc_a(a) ON DELETE CASCADE
|
|
);
|
|
INSERT INTO ref_b VALUES (10, 0), (50, 5), (100, 10), (150, 15);
|
|
TRUNCATE TABLE trunc_a1 CASCADE;
|
|
NOTICE: truncate cascades to table "ref_b"
|
|
SELECT a FROM ref_b;
|
|
a
|
|
---
|
|
(0 rows)
|
|
|
|
DROP TABLE ref_b;
|
|
-- truncate a partition cascading to a partitioned table
|
|
CREATE TABLE ref_c (
|
|
c INT PRIMARY KEY,
|
|
a INT REFERENCES trunc_a(a) ON DELETE CASCADE
|
|
) PARTITION BY RANGE (c);
|
|
CREATE TABLE ref_c1 PARTITION OF ref_c FOR VALUES FROM (100) TO (200);
|
|
CREATE TABLE ref_c2 PARTITION OF ref_c FOR VALUES FROM (200) TO (300);
|
|
INSERT INTO ref_c VALUES (100, 10), (150, 15), (200, 20), (250, 25);
|
|
TRUNCATE TABLE trunc_a21 CASCADE;
|
|
NOTICE: truncate cascades to table "ref_c"
|
|
NOTICE: truncate cascades to table "ref_c1"
|
|
NOTICE: truncate cascades to table "ref_c2"
|
|
SELECT a as "from table ref_c" FROM ref_c;
|
|
from table ref_c
|
|
------------------
|
|
(0 rows)
|
|
|
|
SELECT a as "from table trunc_a" FROM trunc_a ORDER BY a;
|
|
from table trunc_a
|
|
--------------------
|
|
15
|
|
20
|
|
25
|
|
(3 rows)
|
|
|
|
DROP TABLE trunc_a, ref_c;
|