88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.31 2002/08/2204:51:05 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.32 2002/08/2214:23:36 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -332,6 +332,7 @@ TruncateRelation(const RangeVar *relation)
332332{
333333Relation rel ;
334334Oid relid ;
335+ Oid toastrelid ;
335336ScanKeyData key ;
336337Relation fkeyRel ;
337338SysScanDesc fkeyScan ;
@@ -341,17 +342,20 @@ TruncateRelation(const RangeVar *relation)
341342rel = heap_openrv (relation ,AccessExclusiveLock );
342343relid = RelationGetRelid (rel );
343344
344- if (rel -> rd_rel -> relkind == RELKIND_SEQUENCE )
345- elog (ERROR ,"TRUNCATE cannot be used on sequences. '%s' is a sequence" ,
346- RelationGetRelationName (rel ));
347-
348- if (rel -> rd_rel -> relkind == RELKIND_VIEW )
349- elog (ERROR ,"TRUNCATE cannot be used on views. '%s' is a view" ,
350- RelationGetRelationName (rel ));
351-
352- if (rel -> rd_rel -> relkind == RELKIND_COMPOSITE_TYPE )
353- elog (ERROR ,"TRUNCATE cannot be used on type relations. '%s' is a type" ,
345+ /* Only allow truncate on regular tables */
346+ if (rel -> rd_rel -> relkind != RELKIND_RELATION )
347+ {
348+ /* special errors for backwards compatibility */
349+ if (rel -> rd_rel -> relkind == RELKIND_SEQUENCE )
350+ elog (ERROR ,"TRUNCATE cannot be used on sequences. '%s' is a sequence" ,
351+ RelationGetRelationName (rel ));
352+ if (rel -> rd_rel -> relkind == RELKIND_VIEW )
353+ elog (ERROR ,"TRUNCATE cannot be used on views. '%s' is a view" ,
354+ RelationGetRelationName (rel ));
355+ /* else a generic error message will do */
356+ elog (ERROR ,"TRUNCATE can only be used on tables. '%s' is not a table" ,
354357RelationGetRelationName (rel ));
358+ }
355359
356360if (!allowSystemTableMods && IsSystemRelation (rel ))
357361elog (ERROR ,"TRUNCATE cannot be used on system tables. '%s' is a system table" ,
@@ -375,25 +379,33 @@ TruncateRelation(const RangeVar *relation)
375379SnapshotNow ,1 ,& key );
376380
377381/*
378- * Firstforiegn key found with us as the reference
382+ * Firstforeign key found with us as the reference
379383 * should throw an error.
380384 */
381385while (HeapTupleIsValid (tuple = systable_getnext (fkeyScan )))
382386{
383387Form_pg_constraint con = (Form_pg_constraint )GETSTRUCT (tuple );
384388
385- if (con -> contype == 'f' )
386- elog (ERROR ,"TRUNCATE cannot be used as other tables reference this one via foreign key constraint %s" ,
389+ if (con -> contype == 'f' && con -> conrelid != relid )
390+ elog (ERROR ,"TRUNCATE cannot be used as table %s references this one via foreign key constraint %s" ,
391+ get_rel_name (con -> conrelid ),
387392NameStr (con -> conname ));
388393}
389394
390395systable_endscan (fkeyScan );
391396heap_close (fkeyRel ,AccessShareLock );
392397
398+ toastrelid = rel -> rd_rel -> reltoastrelid ;
399+
393400/* Keep the lock until transaction commit */
394401heap_close (rel ,NoLock );
395402
403+ /* Truncate the table proper */
396404heap_truncate (relid );
405+
406+ /* If it has a toast table, truncate that too */
407+ if (OidIsValid (toastrelid ))
408+ heap_truncate (toastrelid );
397409}
398410
399411/*----------