1 -- Test basic TRUNCATE functionality.
2 CREATE TABLE truncate_a (col1 integer primary key);
3 INSERT INTO truncate_a VALUES (1);
4 INSERT INTO truncate_a VALUES (2);
5 SELECT * FROM truncate_a;
16 SELECT * FROM truncate_a;
23 -- Commit the truncate this time
27 SELECT * FROM truncate_a;
32 -- Test foreign-key checks
33 CREATE TABLE trunc_b (a int REFERENCES truncate_a);
34 CREATE TABLE trunc_c (a serial PRIMARY KEY);
35 CREATE TABLE trunc_d (a int REFERENCES trunc_c);
36 CREATE TABLE trunc_e (a int REFERENCES truncate_a, b int REFERENCES trunc_c);
37 TRUNCATE TABLE truncate_a; -- fail
38 ERROR: cannot truncate a table referenced in a foreign key constraint
39 DETAIL: Table "trunc_b" references "truncate_a".
40 HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
41 TRUNCATE TABLE truncate_a,trunc_b; -- fail
42 ERROR: cannot truncate a table referenced in a foreign key constraint
43 DETAIL: Table "trunc_e" references "truncate_a".
44 HINT: Truncate table "trunc_e" at the same time, or use TRUNCATE ... CASCADE.
45 TRUNCATE TABLE truncate_a,trunc_b,trunc_e; -- ok
46 TRUNCATE TABLE truncate_a,trunc_e; -- fail
47 ERROR: cannot truncate a table referenced in a foreign key constraint
48 DETAIL: Table "trunc_b" references "truncate_a".
49 HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
50 TRUNCATE TABLE trunc_c; -- fail
51 ERROR: cannot truncate a table referenced in a foreign key constraint
52 DETAIL: Table "trunc_d" references "trunc_c".
53 HINT: Truncate table "trunc_d" at the same time, or use TRUNCATE ... CASCADE.
54 TRUNCATE TABLE trunc_c,trunc_d; -- fail
55 ERROR: cannot truncate a table referenced in a foreign key constraint
56 DETAIL: Table "trunc_e" references "trunc_c".
57 HINT: Truncate table "trunc_e" at the same time, or use TRUNCATE ... CASCADE.
58 TRUNCATE TABLE trunc_c,trunc_d,trunc_e; -- ok
59 TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a; -- fail
60 ERROR: cannot truncate a table referenced in a foreign key constraint
61 DETAIL: Table "trunc_b" references "truncate_a".
62 HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
63 TRUNCATE TABLE trunc_c,trunc_d,trunc_e,truncate_a,trunc_b; -- ok
64 TRUNCATE TABLE truncate_a RESTRICT; -- fail
65 ERROR: cannot truncate a table referenced in a foreign key constraint
66 DETAIL: Table "trunc_b" references "truncate_a".
67 HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
68 TRUNCATE TABLE truncate_a CASCADE; -- ok
69 NOTICE: truncate cascades to table "trunc_b"
70 NOTICE: truncate cascades to table "trunc_e"
71 -- circular references
72 ALTER TABLE truncate_a ADD FOREIGN KEY (col1) REFERENCES trunc_c;
73 -- Add some data to verify that truncating actually works ...
74 INSERT INTO trunc_c VALUES (1);
75 INSERT INTO truncate_a VALUES (1);
76 INSERT INTO trunc_b VALUES (1);
77 INSERT INTO trunc_d VALUES (1);
78 INSERT INTO trunc_e VALUES (1,1);
79 TRUNCATE TABLE trunc_c;
80 ERROR: cannot truncate a table referenced in a foreign key constraint
81 DETAIL: Table "truncate_a" references "trunc_c".
82 HINT: Truncate table "truncate_a" at the same time, or use TRUNCATE ... CASCADE.
83 TRUNCATE TABLE trunc_c,truncate_a;
84 ERROR: cannot truncate a table referenced in a foreign key constraint
85 DETAIL: Table "trunc_d" references "trunc_c".
86 HINT: Truncate table "trunc_d" at the same time, or use TRUNCATE ... CASCADE.
87 TRUNCATE TABLE trunc_c,truncate_a,trunc_d;
88 ERROR: cannot truncate a table referenced in a foreign key constraint
89 DETAIL: Table "trunc_e" references "trunc_c".
90 HINT: Truncate table "trunc_e" at the same time, or use TRUNCATE ... CASCADE.
91 TRUNCATE TABLE trunc_c,truncate_a,trunc_d,trunc_e;
92 ERROR: cannot truncate a table referenced in a foreign key constraint
93 DETAIL: Table "trunc_b" references "truncate_a".
94 HINT: Truncate table "trunc_b" at the same time, or use TRUNCATE ... CASCADE.
95 TRUNCATE TABLE trunc_c,truncate_a,trunc_d,trunc_e,trunc_b;
96 -- Verify that truncating did actually work
97 SELECT * FROM truncate_a
101 SELECT * FROM trunc_b
103 SELECT * FROM trunc_d;
108 SELECT * FROM trunc_e;
113 -- Add data again to test TRUNCATE ... CASCADE
114 INSERT INTO trunc_c VALUES (1);
115 INSERT INTO truncate_a VALUES (1);
116 INSERT INTO trunc_b VALUES (1);
117 INSERT INTO trunc_d VALUES (1);
118 INSERT INTO trunc_e VALUES (1,1);
119 TRUNCATE TABLE trunc_c CASCADE; -- ok
120 NOTICE: truncate cascades to table "truncate_a"
121 NOTICE: truncate cascades to table "trunc_d"
122 NOTICE: truncate cascades to table "trunc_e"
123 NOTICE: truncate cascades to table "trunc_b"
124 SELECT * FROM truncate_a
126 SELECT * FROM trunc_c
128 SELECT * FROM trunc_b
130 SELECT * FROM trunc_d;
135 SELECT * FROM trunc_e;
140 DROP TABLE truncate_a,trunc_c,trunc_b,trunc_d,trunc_e CASCADE;
141 -- Test TRUNCATE with inheritance
142 CREATE TABLE trunc_f (col1 integer primary key);
143 INSERT INTO trunc_f VALUES (1);
144 INSERT INTO trunc_f VALUES (2);
145 CREATE TABLE trunc_fa (col2a text) INHERITS (trunc_f);
146 INSERT INTO trunc_fa VALUES (3, 'three');
147 CREATE TABLE trunc_fb (col2b int) INHERITS (trunc_f);
148 INSERT INTO trunc_fb VALUES (4, 444);
149 CREATE TABLE trunc_faa (col3 text) INHERITS (trunc_fa);
150 INSERT INTO trunc_faa VALUES (5, 'five', 'FIVE');
152 SELECT * FROM trunc_f;
163 SELECT * FROM trunc_f;
170 SELECT * FROM trunc_f;
180 TRUNCATE ONLY trunc_f;
181 SELECT * FROM trunc_f;
191 SELECT * FROM trunc_f;
201 SELECT * FROM trunc_fa;
208 SELECT * FROM trunc_faa;
210 ------+-------+------
214 TRUNCATE ONLY trunc_fb, ONLY trunc_fa;
215 SELECT * FROM trunc_f;
223 SELECT * FROM trunc_fa;
229 SELECT * FROM trunc_faa;
231 ------+-------+------
237 SELECT * FROM trunc_f;
247 SELECT * FROM trunc_fa;
254 SELECT * FROM trunc_faa;
256 ------+-------+------
260 TRUNCATE ONLY trunc_fb, trunc_fa;
261 SELECT * FROM trunc_f;
268 SELECT * FROM trunc_fa;
273 SELECT * FROM trunc_faa;
275 ------+-------+------
279 DROP TABLE trunc_f CASCADE;
280 NOTICE: drop cascades to 3 other objects
281 DETAIL: drop cascades to table trunc_fa
282 drop cascades to table trunc_faa
283 drop cascades to table trunc_fb
284 -- Test ON TRUNCATE triggers
285 CREATE TABLE trunc_trigger_test (f1 int, f2 text, f3 text);
286 CREATE TABLE trunc_trigger_log (tgop text, tglevel text, tgwhen text,
287 tgargv text, tgtable name, rowcount bigint);
288 CREATE FUNCTION trunctrigger() RETURNS trigger as $$
291 execute 'select count(*) from ' || quote_ident(tg_table_name) into c;
292 insert into trunc_trigger_log values
293 (TG_OP, TG_LEVEL, TG_WHEN, TG_ARGV[0], tg_table_name, c);
297 -- basic before trigger
298 INSERT INTO trunc_trigger_test VALUES(1, 'foo', 'bar'), (2, 'baz', 'quux');
300 BEFORE TRUNCATE ON trunc_trigger_test
302 EXECUTE PROCEDURE trunctrigger('before trigger truncate');
303 SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
304 Row count in test table
305 -------------------------
309 SELECT * FROM trunc_trigger_log;
310 tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
311 ------+---------+--------+--------+---------+----------
314 TRUNCATE trunc_trigger_test;
315 SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
316 Row count in test table
317 -------------------------
321 SELECT * FROM trunc_trigger_log;
322 tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
323 ----------+-----------+--------+-------------------------+--------------------+----------
324 TRUNCATE | STATEMENT | BEFORE | before trigger truncate | trunc_trigger_test | 2
327 DROP TRIGGER t ON trunc_trigger_test;
328 truncate trunc_trigger_log;
329 -- same test with an after trigger
330 INSERT INTO trunc_trigger_test VALUES(1, 'foo', 'bar'), (2, 'baz', 'quux');
332 AFTER TRUNCATE ON trunc_trigger_test
334 EXECUTE PROCEDURE trunctrigger('after trigger truncate');
335 SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
336 Row count in test table
337 -------------------------
341 SELECT * FROM trunc_trigger_log;
342 tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
343 ------+---------+--------+--------+---------+----------
346 TRUNCATE trunc_trigger_test;
347 SELECT count(*) as "Row count in test table" FROM trunc_trigger_test;
348 Row count in test table
349 -------------------------
353 SELECT * FROM trunc_trigger_log;
354 tgop | tglevel | tgwhen | tgargv | tgtable | rowcount
355 ----------+-----------+--------+------------------------+--------------------+----------
356 TRUNCATE | STATEMENT | AFTER | after trigger truncate | trunc_trigger_test | 0
359 DROP TABLE trunc_trigger_test;
360 DROP TABLE trunc_trigger_log;
361 DROP FUNCTION trunctrigger();
362 -- test TRUNCATE ... RESTART IDENTITY
363 CREATE SEQUENCE truncate_a_id1 START WITH 33;
364 CREATE TABLE truncate_a (id serial,
365 id1 integer default nextval('truncate_a_id1'));
366 ALTER SEQUENCE truncate_a_id1 OWNED BY truncate_a.id1;
367 INSERT INTO truncate_a DEFAULT VALUES;
368 INSERT INTO truncate_a DEFAULT VALUES;
369 SELECT * FROM truncate_a;
377 INSERT INTO truncate_a DEFAULT VALUES;
378 INSERT INTO truncate_a DEFAULT VALUES;
379 SELECT * FROM truncate_a;
386 TRUNCATE truncate_a RESTART IDENTITY;
387 INSERT INTO truncate_a DEFAULT VALUES;
388 INSERT INTO truncate_a DEFAULT VALUES;
389 SELECT * FROM truncate_a;
396 CREATE TABLE truncate_b (id int GENERATED ALWAYS AS IDENTITY (START WITH 44));
397 INSERT INTO truncate_b DEFAULT VALUES;
398 INSERT INTO truncate_b DEFAULT VALUES;
399 SELECT * FROM truncate_b;
407 INSERT INTO truncate_b DEFAULT VALUES;
408 INSERT INTO truncate_b DEFAULT VALUES;
409 SELECT * FROM truncate_b;
416 TRUNCATE truncate_b RESTART IDENTITY;
417 INSERT INTO truncate_b DEFAULT VALUES;
418 INSERT INTO truncate_b DEFAULT VALUES;
419 SELECT * FROM truncate_b;
426 -- check rollback of a RESTART IDENTITY operation
428 TRUNCATE truncate_a RESTART IDENTITY;
429 INSERT INTO truncate_a DEFAULT VALUES;
430 SELECT * FROM truncate_a;
437 INSERT INTO truncate_a DEFAULT VALUES;
438 INSERT INTO truncate_a DEFAULT VALUES;
439 SELECT * FROM truncate_a;
448 DROP TABLE truncate_a;
449 SELECT nextval('truncate_a_id1'); -- fail, seq should have been dropped
450 ERROR: relation "truncate_a_id1" does not exist
451 LINE 1: SELECT nextval('truncate_a_id1');
454 CREATE TABLE truncparted (a int, b char) PARTITION BY LIST (a);
455 -- error, can't truncate a partitioned table
456 TRUNCATE ONLY truncparted;
457 ERROR: cannot truncate only a partitioned table
458 HINT: Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.
459 CREATE TABLE truncparted1 PARTITION OF truncparted FOR VALUES IN (1);
460 INSERT INTO truncparted VALUES (1, 'a');
461 -- error, must truncate partitions
462 TRUNCATE ONLY truncparted;
463 ERROR: cannot truncate only a partitioned table
464 HINT: Do not specify the ONLY keyword, or use TRUNCATE ONLY on the partitions directly.
465 TRUNCATE truncparted;
466 DROP TABLE truncparted;
467 -- foreign key on partitioned table: partition key is referencing column.
468 -- Make sure truncate did execute on all tables
469 CREATE FUNCTION tp_ins_data() RETURNS void LANGUAGE plpgsql AS $$
471 INSERT INTO truncprim VALUES (1), (100), (150);
472 INSERT INTO truncpart VALUES (1), (100), (150);
475 CREATE FUNCTION tp_chk_data(OUT pktb regclass, OUT pkval int, OUT fktb regclass, OUT fkval int)
476 RETURNS SETOF record LANGUAGE plpgsql AS $$
479 pk.tableoid::regclass, pk.a, fk.tableoid::regclass, fk.a
480 FROM truncprim pk FULL JOIN truncpart fk USING (a)
484 CREATE TABLE truncprim (a int PRIMARY KEY);
485 CREATE TABLE truncpart (a int REFERENCES truncprim)
486 PARTITION BY RANGE (a);
487 CREATE TABLE truncpart_1 PARTITION OF truncpart FOR VALUES FROM (0) TO (100);
488 CREATE TABLE truncpart_2 PARTITION OF truncpart FOR VALUES FROM (100) TO (200)
489 PARTITION BY RANGE (a);
490 CREATE TABLE truncpart_2_1 PARTITION OF truncpart_2 FOR VALUES FROM (100) TO (150);
491 CREATE TABLE truncpart_2_d PARTITION OF truncpart_2 DEFAULT;
492 TRUNCATE TABLE truncprim; -- should fail
493 ERROR: cannot truncate a table referenced in a foreign key constraint
494 DETAIL: Table "truncpart" references "truncprim".
495 HINT: Truncate table "truncpart" at the same time, or use TRUNCATE ... CASCADE.
496 select tp_ins_data();
502 -- should truncate everything
503 TRUNCATE TABLE truncprim, truncpart;
504 select * from tp_chk_data();
505 pktb | pkval | fktb | fkval
506 ------+-------+------+-------
509 select tp_ins_data();
515 -- should truncate everything
516 TRUNCATE TABLE truncprim CASCADE;
517 NOTICE: truncate cascades to table "truncpart"
518 NOTICE: truncate cascades to table "truncpart_1"
519 NOTICE: truncate cascades to table "truncpart_2"
520 NOTICE: truncate cascades to table "truncpart_2_1"
521 NOTICE: truncate cascades to table "truncpart_2_d"
522 SELECT * FROM tp_chk_data();
523 pktb | pkval | fktb | fkval
524 ------+-------+------+-------
527 SELECT tp_ins_data();
533 -- should truncate all partitions
534 TRUNCATE TABLE truncpart;
535 SELECT * FROM tp_chk_data();
536 pktb | pkval | fktb | fkval
537 -----------+-------+------+-------
543 DROP TABLE truncprim, truncpart;
544 DROP FUNCTION tp_ins_data(), tp_chk_data();