*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
Relation rel;
Oid relid;
+ ScanKeyData key;
+ Relation fkeyRel;
+ SysScanDesc fkeyScan;
+ HeapTuple tuple;
/* Grab exclusive lock in preparation for truncate */
rel = heap_openrv(relation, AccessExclusiveLock);
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);
--- /dev/null
+-- 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;
# 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
-# $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
test: rangefuncs
test: without_oid
test: conversion
+test: truncate
--- /dev/null
+-- 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;