aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/tablecmds.c36
-rw-r--r--src/test/regress/expected/truncate.out38
-rw-r--r--src/test/regress/parallel_schedule2
-rw-r--r--src/test/regress/serial_schedule3
-rw-r--r--src/test/regress/sql/truncate.sql17
5 files changed, 93 insertions, 3 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c6e8d686d41..1961ca1344a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.30 2002/08/19 15:08:46 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.31 2002/08/22 04:51:05 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -332,6 +332,10 @@ TruncateRelation(const RangeVar *relation)
{
Relation rel;
Oid relid;
+ ScanKeyData key;
+ Relation fkeyRel;
+ SysScanDesc fkeyScan;
+ HeapTuple tuple;
/* Grab exclusive lock in preparation for truncate */
rel = heap_openrv(relation, AccessExclusiveLock);
@@ -356,6 +360,36 @@ TruncateRelation(const RangeVar *relation)
if (!pg_class_ownercheck(relid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
+ /*
+ * Don't allow truncate on tables which are referenced
+ * by foreign keys
+ */
+ fkeyRel = heap_openr(ConstraintRelationName, AccessShareLock);
+
+ ScanKeyEntryInitialize(&key, 0,
+ Anum_pg_constraint_confrelid,
+ F_OIDEQ,
+ ObjectIdGetDatum(relid));
+
+ fkeyScan = systable_beginscan(fkeyRel, 0, false,
+ SnapshotNow, 1, &key);
+
+ /*
+ * First foriegn key found with us as the reference
+ * should throw an error.
+ */
+ while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
+ {
+ Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
+
+ if (con->contype == 'f')
+ elog(ERROR, "TRUNCATE cannot be used as other tables reference this one via foreign key constraint %s",
+ NameStr(con->conname));
+ }
+
+ systable_endscan(fkeyScan);
+ heap_close(fkeyRel, AccessShareLock);
+
/* Keep the lock until transaction commit */
heap_close(rel, NoLock);
diff --git a/src/test/regress/expected/truncate.out b/src/test/regress/expected/truncate.out
new file mode 100644
index 00000000000..19300f63a36
--- /dev/null
+++ b/src/test/regress/expected/truncate.out
@@ -0,0 +1,38 @@
+-- Test basic TRUNCATE functionality.
+CREATE TABLE truncate_a (col1 integer primary key);
+NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'truncate_a_pkey' for table 'truncate_a'
+INSERT INTO truncate_a VALUES (1);
+INSERT INTO truncate_a VALUES (2);
+SELECT * FROM truncate_a;
+ col1
+------
+ 1
+ 2
+(2 rows)
+
+TRUNCATE truncate_a;
+SELECT * FROM truncate_a;
+ col1
+------
+(0 rows)
+
+-- Test foreign constraint check
+CREATE TABLE truncate_b(col1 integer references truncate_a);
+NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
+INSERT INTO truncate_a VALUES (1);
+SELECT * FROM truncate_a;
+ col1
+------
+ 1
+(1 row)
+
+TRUNCATE truncate_a;
+ERROR: TRUNCATE cannot be used as other tables reference this one via foreign key constraint $1
+SELECT * FROM truncate_a;
+ col1
+------
+ 1
+(1 row)
+
+DROP TABLE truncate_b;
+DROP TABLE truncate_a;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 0ac26307063..e82d9421679 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -74,4 +74,4 @@ test: select_views alter_table portals_p2 rules foreign_key cluster
# The sixth group of parallel test
# ----------
# "plpgsql" cannot run concurrently with "rules"
-test: limit plpgsql temp domain rangefuncs copy2 conversion without_oid
+test: limit plpgsql temp domain rangefuncs copy2 conversion without_oid truncate
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index d7a6deed2c9..553df2dfe7d 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,4 +1,4 @@
-# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.15 2002/08/11 02:06:32 tgl Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.16 2002/08/22 04:51:06 momjian Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
@@ -88,3 +88,4 @@ test: domain
test: rangefuncs
test: without_oid
test: conversion
+test: truncate
diff --git a/src/test/regress/sql/truncate.sql b/src/test/regress/sql/truncate.sql
new file mode 100644
index 00000000000..5333113a9e7
--- /dev/null
+++ b/src/test/regress/sql/truncate.sql
@@ -0,0 +1,17 @@
+-- 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;
+TRUNCATE truncate_a;
+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;
+
+DROP TABLE truncate_b;
+DROP TABLE truncate_a;