Commit 47b37a6b authored by Bruce Momjian's avatar Bruce Momjian

# Disallow TRUNCATE on tables that are involved in referential

constraints


The issue with finding and removing foreign key constraints is no longer
an issue, so please apply the attached.

It does NOT check for rules or on delete triggers (old style foreign
keys) as those are difficult to deal with (remove, truncate, re-add).

Rod Taylor
parent dac22ee4
......@@ -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);
......
-- 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;
......@@ -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
# $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
-- 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment