diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 36 |
1 files changed, 35 insertions, 1 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); |