mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Code review for recent TRUNCATE changes. Tighten relation-kind check,
tighten foreign-key check (a self-reference should not prevent TRUNCATE), improve error message, cause a relation's TOAST table to be truncated along with the relation.
This commit is contained in:
parent
b4f24fed7a
commit
0f1112923c
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.31 2002/08/22 04:51:05 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.32 2002/08/22 14:23:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -332,6 +332,7 @@ TruncateRelation(const RangeVar *relation)
|
|||||||
{
|
{
|
||||||
Relation rel;
|
Relation rel;
|
||||||
Oid relid;
|
Oid relid;
|
||||||
|
Oid toastrelid;
|
||||||
ScanKeyData key;
|
ScanKeyData key;
|
||||||
Relation fkeyRel;
|
Relation fkeyRel;
|
||||||
SysScanDesc fkeyScan;
|
SysScanDesc fkeyScan;
|
||||||
@ -341,17 +342,20 @@ TruncateRelation(const RangeVar *relation)
|
|||||||
rel = heap_openrv(relation, AccessExclusiveLock);
|
rel = heap_openrv(relation, AccessExclusiveLock);
|
||||||
relid = RelationGetRelid(rel);
|
relid = RelationGetRelid(rel);
|
||||||
|
|
||||||
|
/* Only allow truncate on regular tables */
|
||||||
|
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||||
|
{
|
||||||
|
/* special errors for backwards compatibility */
|
||||||
if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
|
if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
|
||||||
elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
|
elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
|
||||||
RelationGetRelationName(rel));
|
RelationGetRelationName(rel));
|
||||||
|
|
||||||
if (rel->rd_rel->relkind == RELKIND_VIEW)
|
if (rel->rd_rel->relkind == RELKIND_VIEW)
|
||||||
elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
|
elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
|
||||||
RelationGetRelationName(rel));
|
RelationGetRelationName(rel));
|
||||||
|
/* else a generic error message will do */
|
||||||
if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
|
elog(ERROR, "TRUNCATE can only be used on tables. '%s' is not a table",
|
||||||
elog(ERROR, "TRUNCATE cannot be used on type relations. '%s' is a type",
|
|
||||||
RelationGetRelationName(rel));
|
RelationGetRelationName(rel));
|
||||||
|
}
|
||||||
|
|
||||||
if (!allowSystemTableMods && IsSystemRelation(rel))
|
if (!allowSystemTableMods && IsSystemRelation(rel))
|
||||||
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
|
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
|
||||||
@ -375,25 +379,33 @@ TruncateRelation(const RangeVar *relation)
|
|||||||
SnapshotNow, 1, &key);
|
SnapshotNow, 1, &key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First foriegn key found with us as the reference
|
* First foreign key found with us as the reference
|
||||||
* should throw an error.
|
* should throw an error.
|
||||||
*/
|
*/
|
||||||
while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
|
while (HeapTupleIsValid(tuple = systable_getnext(fkeyScan)))
|
||||||
{
|
{
|
||||||
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
|
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
|
||||||
|
|
||||||
if (con->contype == 'f')
|
if (con->contype == 'f' && con->conrelid != relid)
|
||||||
elog(ERROR, "TRUNCATE cannot be used as other tables reference this one via foreign key constraint %s",
|
elog(ERROR, "TRUNCATE cannot be used as table %s references this one via foreign key constraint %s",
|
||||||
|
get_rel_name(con->conrelid),
|
||||||
NameStr(con->conname));
|
NameStr(con->conname));
|
||||||
}
|
}
|
||||||
|
|
||||||
systable_endscan(fkeyScan);
|
systable_endscan(fkeyScan);
|
||||||
heap_close(fkeyRel, AccessShareLock);
|
heap_close(fkeyRel, AccessShareLock);
|
||||||
|
|
||||||
|
toastrelid = rel->rd_rel->reltoastrelid;
|
||||||
|
|
||||||
/* Keep the lock until transaction commit */
|
/* Keep the lock until transaction commit */
|
||||||
heap_close(rel, NoLock);
|
heap_close(rel, NoLock);
|
||||||
|
|
||||||
|
/* Truncate the table proper */
|
||||||
heap_truncate(relid);
|
heap_truncate(relid);
|
||||||
|
|
||||||
|
/* If it has a toast table, truncate that too */
|
||||||
|
if (OidIsValid(toastrelid))
|
||||||
|
heap_truncate(toastrelid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------
|
/*----------
|
||||||
|
@ -27,7 +27,7 @@ SELECT * FROM truncate_a;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
TRUNCATE truncate_a;
|
TRUNCATE truncate_a;
|
||||||
ERROR: TRUNCATE cannot be used as other tables reference this one via foreign key constraint $1
|
ERROR: TRUNCATE cannot be used as table truncate_b references this one via foreign key constraint $1
|
||||||
SELECT * FROM truncate_a;
|
SELECT * FROM truncate_a;
|
||||||
col1
|
col1
|
||||||
------
|
------
|
||||||
|
Loading…
Reference in New Issue
Block a user