mirror of
https://github.com/postgres/postgres.git
synced 2025-12-12 02:37:31 +03:00
Generalize TRUNCATE to support truncating multiple tables in one
command. This is useful because we can allow truncation of tables referenced by foreign keys, so long as the referencing table is truncated in the same command. Alvaro Herrera
This commit is contained in:
@@ -82,3 +82,30 @@ ERROR: relation "temptest" does not exist
|
||||
-- ON COMMIT is only allowed for TEMP
|
||||
CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS;
|
||||
ERROR: ON COMMIT can only be used on temporary tables
|
||||
-- Test foreign keys
|
||||
BEGIN;
|
||||
CREATE TEMP TABLE temptest1(col int PRIMARY KEY);
|
||||
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "temptest1_pkey" for table "temptest1"
|
||||
CREATE TEMP TABLE temptest2(col int REFERENCES temptest1)
|
||||
ON COMMIT DELETE ROWS;
|
||||
INSERT INTO temptest1 VALUES (1);
|
||||
INSERT INTO temptest2 VALUES (1);
|
||||
COMMIT;
|
||||
SELECT * FROM temptest1;
|
||||
col
|
||||
-----
|
||||
1
|
||||
(1 row)
|
||||
|
||||
SELECT * FROM temptest2;
|
||||
col
|
||||
-----
|
||||
(0 rows)
|
||||
|
||||
BEGIN;
|
||||
CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS;
|
||||
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "temptest3_pkey" for table "temptest3"
|
||||
CREATE TEMP TABLE temptest4(col int REFERENCES temptest3);
|
||||
COMMIT;
|
||||
ERROR: unsupported ON COMMIT and foreign key combination
|
||||
DETAIL: Table "temptest4" references "temptest3" via foreign key constraint "temptest4_col_fkey", but they do not have the same ON COMMIT setting.
|
||||
|
||||
@@ -30,23 +30,84 @@ SELECT * FROM truncate_a;
|
||||
------
|
||||
(0 rows)
|
||||
|
||||
-- Test foreign constraint check
|
||||
CREATE TABLE truncate_b(col1 integer references truncate_a);
|
||||
INSERT INTO truncate_a VALUES (1);
|
||||
SELECT * FROM truncate_a;
|
||||
col1
|
||||
------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
TRUNCATE truncate_a;
|
||||
-- Test foreign-key checks
|
||||
CREATE TABLE trunc_b (a int REFERENCES truncate_a);
|
||||
CREATE TABLE trunc_c (a serial PRIMARY KEY);
|
||||
NOTICE: CREATE TABLE will create implicit sequence "trunc_c_a_seq" for serial column "trunc_c.a"
|
||||
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "trunc_c_pkey" for table "trunc_c"
|
||||
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 "truncate_b" references "truncate_a" via foreign key constraint "truncate_b_col1_fkey".
|
||||
SELECT * FROM truncate_a;
|
||||
DETAIL: Table "trunc_b" references "truncate_a" via foreign key constraint "trunc_b_a_fkey".
|
||||
HINT: Truncate table "trunc_b" at the same time.
|
||||
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" via foreign key constraint "trunc_e_a_fkey".
|
||||
HINT: Truncate table "trunc_e" at the same time.
|
||||
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" via foreign key constraint "trunc_b_a_fkey".
|
||||
HINT: Truncate table "trunc_b" at the same time.
|
||||
TRUNCATE TABLE trunc_c; -- fail
|
||||
ERROR: cannot truncate a table referenced in a foreign key constraint
|
||||
DETAIL: Table "trunc_d" references "trunc_c" via foreign key constraint "trunc_d_a_fkey".
|
||||
HINT: Truncate table "trunc_d" at the same time.
|
||||
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" via foreign key constraint "trunc_e_b_fkey".
|
||||
HINT: Truncate table "trunc_e" at the same time.
|
||||
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" via foreign key constraint "trunc_b_a_fkey".
|
||||
HINT: Truncate table "trunc_b" at the same time.
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a,trunc_b; -- ok
|
||||
-- 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 "trunc_d" references "trunc_c" via foreign key constraint "trunc_d_a_fkey".
|
||||
HINT: Truncate table "trunc_d" at the same time.
|
||||
TRUNCATE TABLE trunc_c,trunc_d;
|
||||
ERROR: cannot truncate a table referenced in a foreign key constraint
|
||||
DETAIL: Table "trunc_e" references "trunc_c" via foreign key constraint "trunc_e_b_fkey".
|
||||
HINT: Truncate table "trunc_e" at the same time.
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e;
|
||||
ERROR: cannot truncate a table referenced in a foreign key constraint
|
||||
DETAIL: Table "truncate_a" references "trunc_c" via foreign key constraint "truncate_a_col1_fkey".
|
||||
HINT: Truncate table "truncate_a" at the same time.
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a;
|
||||
ERROR: cannot truncate a table referenced in a foreign key constraint
|
||||
DETAIL: Table "trunc_b" references "truncate_a" via foreign key constraint "trunc_b_a_fkey".
|
||||
HINT: Truncate table "trunc_b" at the same time.
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a,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
|
||||
------
|
||||
1
|
||||
(1 row)
|
||||
(0 rows)
|
||||
|
||||
DROP TABLE truncate_b;
|
||||
DROP TABLE truncate_a;
|
||||
SELECT * FROM trunc_e;
|
||||
a | b
|
||||
---+---
|
||||
(0 rows)
|
||||
|
||||
DROP TABLE truncate_a,trunc_c,trunc_b,trunc_d,trunc_e CASCADE;
|
||||
NOTICE: drop cascades to constraint trunc_e_a_fkey on table trunc_e
|
||||
NOTICE: drop cascades to constraint trunc_b_a_fkey on table trunc_b
|
||||
NOTICE: drop cascades to constraint trunc_e_b_fkey on table trunc_e
|
||||
NOTICE: drop cascades to constraint trunc_d_a_fkey on table trunc_d
|
||||
|
||||
@@ -83,3 +83,19 @@ SELECT * FROM temptest;
|
||||
-- ON COMMIT is only allowed for TEMP
|
||||
|
||||
CREATE TABLE temptest(col int) ON COMMIT DELETE ROWS;
|
||||
|
||||
-- Test foreign keys
|
||||
BEGIN;
|
||||
CREATE TEMP TABLE temptest1(col int PRIMARY KEY);
|
||||
CREATE TEMP TABLE temptest2(col int REFERENCES temptest1)
|
||||
ON COMMIT DELETE ROWS;
|
||||
INSERT INTO temptest1 VALUES (1);
|
||||
INSERT INTO temptest2 VALUES (1);
|
||||
COMMIT;
|
||||
SELECT * FROM temptest1;
|
||||
SELECT * FROM temptest2;
|
||||
|
||||
BEGIN;
|
||||
CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS;
|
||||
CREATE TEMP TABLE temptest4(col int REFERENCES temptest3);
|
||||
COMMIT;
|
||||
|
||||
@@ -14,12 +14,45 @@ TRUNCATE truncate_a;
|
||||
COMMIT;
|
||||
SELECT * FROM truncate_a;
|
||||
|
||||
-- Test foreign constraint check
|
||||
CREATE TABLE truncate_b(col1 integer references truncate_a);
|
||||
INSERT INTO truncate_a VALUES (1);
|
||||
SELECT * FROM truncate_a;
|
||||
TRUNCATE truncate_a;
|
||||
SELECT * FROM truncate_a;
|
||||
-- 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);
|
||||
|
||||
DROP TABLE truncate_b;
|
||||
DROP TABLE truncate_a;
|
||||
TRUNCATE TABLE truncate_a; -- fail
|
||||
TRUNCATE TABLE truncate_a,trunc_b; -- fail
|
||||
TRUNCATE TABLE truncate_a,trunc_b,trunc_e; -- ok
|
||||
TRUNCATE TABLE truncate_a,trunc_e; -- fail
|
||||
TRUNCATE TABLE trunc_c; -- fail
|
||||
TRUNCATE TABLE trunc_c,trunc_d; -- fail
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e; -- ok
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a; -- fail
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a,trunc_b; -- ok
|
||||
|
||||
-- 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;
|
||||
TRUNCATE TABLE trunc_c,trunc_d;
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e;
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a;
|
||||
TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a,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;
|
||||
SELECT * FROM trunc_e;
|
||||
|
||||
DROP TABLE truncate_a,trunc_c,trunc_b,trunc_d,trunc_e CASCADE;
|
||||
|
||||
Reference in New Issue
Block a user