]> granicus.if.org Git - postgresql/commitdiff
Code review for recent TRUNCATE changes. Tighten relation-kind check,
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 22 Aug 2002 14:23:36 +0000 (14:23 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 22 Aug 2002 14:23:36 +0000 (14:23 +0000)
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.

src/backend/commands/tablecmds.c
src/test/regress/expected/truncate.out

index 1961ca1344ad90a73e90fb5ad2c918915611492a..ee2df73f21ee5396498bdebb56f62fc5c1d9245d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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;
        Oid                     relid;
+       Oid                     toastrelid;
        ScanKeyData key;
        Relation        fkeyRel;
        SysScanDesc     fkeyScan;
@@ -341,17 +342,20 @@ TruncateRelation(const RangeVar *relation)
        rel = heap_openrv(relation, AccessExclusiveLock);
        relid = RelationGetRelid(rel);
 
-       if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
-               elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
-                        RelationGetRelationName(rel));
-
-       if (rel->rd_rel->relkind == RELKIND_VIEW)
-               elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
-                        RelationGetRelationName(rel));
-
-       if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-               elog(ERROR, "TRUNCATE cannot be used on type relations. '%s' is a type",
+       /* 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)
+                       elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
+                                RelationGetRelationName(rel));
+               if (rel->rd_rel->relkind == RELKIND_VIEW)
+                       elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
+                                RelationGetRelationName(rel));
+               /* else a generic error message will do */
+               elog(ERROR, "TRUNCATE can only be used on tables. '%s' is not a table",
                         RelationGetRelationName(rel));
+       }
 
        if (!allowSystemTableMods && IsSystemRelation(rel))
                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);
 
        /*
-        * First foriegn key found with us as the reference
+        * First foreign 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",
+               if (con->contype == 'f' && con->conrelid != relid)
+                       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));
        }
 
        systable_endscan(fkeyScan);
        heap_close(fkeyRel, AccessShareLock);
 
+       toastrelid = rel->rd_rel->reltoastrelid;
+
        /* Keep the lock until transaction commit */
        heap_close(rel, NoLock);
 
+       /* Truncate the table proper */
        heap_truncate(relid);
+
+       /* If it has a toast table, truncate that too */
+       if (OidIsValid(toastrelid))
+               heap_truncate(toastrelid);
 }
 
 /*----------
index 19300f63a360d2d44ce8439a503a3bf4c753036d..8751b1fdb7df701135850e2118a44601293ba621 100644 (file)
@@ -27,7 +27,7 @@ SELECT * FROM truncate_a;
 (1 row)
 
 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;
  col1 
 ------