diff options
Diffstat (limited to 'src/backend/catalog/heap.c')
-rw-r--r-- | src/backend/catalog/heap.c | 102 |
1 files changed, 39 insertions, 63 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index f2df9c3c07c..2c4a9e515b2 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.150 2000/10/22 23:32:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.151 2000/11/08 22:09:56 tgl Exp $ * * * INTERFACE ROUTINES @@ -289,8 +289,7 @@ heap_create(char *relname, */ rel = (Relation) palloc(sizeof(RelationData)); MemSet((char *) rel, 0, sizeof(RelationData)); - rel->rd_fd = -1; /* table is not open */ - rel->rd_unlinked = true; /* table is not created yet */ + rel->rd_fd = -1; /* physical file is not open */ RelationSetReferenceCount(rel, 1); @@ -345,8 +344,6 @@ heap_create(char *relname, * have the storage manager create the relation. * ---------------- */ - - /* smgrcreate() is moved to heap_storage_create() */ if (storage_create) heap_storage_create(rel); @@ -355,18 +352,12 @@ heap_create(char *relname, return rel; } -bool +void heap_storage_create(Relation rel) { - bool smgrcall = false; - - if (rel->rd_unlinked) - { - rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel); - rel->rd_unlinked = false; - smgrcall = true; - } - return smgrcall; + Assert(rel->rd_fd < 0); + rel->rd_fd = smgrcreate(DEFAULT_SMGR, rel); + Assert(rel->rd_fd >= 0); } /* ---------------------------------------------------------------- @@ -1062,7 +1053,11 @@ RelationRemoveIndexes(Relation relation) &entry); while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) + { index_drop(((Form_pg_index) GETSTRUCT(tuple))->indexrelid); + /* advance cmd counter to make catalog changes visible */ + CommandCounterIncrement(); + } heap_endscan(scan); heap_close(indexRelation, RowExclusiveLock); @@ -1165,10 +1160,10 @@ RelationTruncateIndexes(Oid heapId) LockRelation(currentIndex, AccessExclusiveLock); /* - * Release any buffers associated with this index. If they're + * Drop any buffers associated with this index. If they're * dirty, they're just dropped without bothering to flush to disk. */ - ReleaseRelationBuffers(currentIndex); + DropRelationBuffers(currentIndex); /* Now truncate the actual data and set blocks to zero */ smgrtruncate(DEFAULT_SMGR, currentIndex, 0); @@ -1212,24 +1207,19 @@ heap_truncate(char *relname) /* ---------------- * TRUNCATE TABLE within a transaction block is dangerous, because * if the transaction is later rolled back we have no way to - * undo truncation of the relation's physical file. For now, allow it - * but emit a warning message. - * Someday we might want to consider postponing the physical truncate - * until transaction commit, but that's a lot of work... - * The only case that actually works right is for relations created - * in the current transaction, since the post-abort state would be that - * they don't exist anyway. So, no warning in that case. + * undo truncation of the relation's physical file. Disallow it + * except for a rel created in the current xact (which would be deleted + * on abort, anyway). * ---------------- */ if (IsTransactionBlock() && !rel->rd_myxactonly) - elog(NOTICE, "Caution: TRUNCATE TABLE cannot be rolled back, so don't abort now"); + elog(ERROR, "TRUNCATE TABLE cannot run inside a BEGIN/END block"); /* * Release any buffers associated with this relation. If they're * dirty, they're just dropped without bothering to flush to disk. */ - - ReleaseRelationBuffers(rel); + DropRelationBuffers(rel); /* Now truncate the actual data and set blocks to zero */ @@ -1416,8 +1406,9 @@ heap_drop_with_catalog(const char *relname, { Relation rel; Oid rid; - bool istemp = (get_temp_rel_by_username(relname) != NULL); bool has_toasttable; + bool istemp = (get_temp_rel_by_username(relname) != NULL); + int i; /* ---------------- * Open and lock the relation. @@ -1425,6 +1416,7 @@ heap_drop_with_catalog(const char *relname, */ rel = heap_openr(relname, AccessExclusiveLock); rid = RelationGetRelid(rel); + has_toasttable = rel->rd_rel->reltoastrelid != InvalidOid; /* ---------------- * prevent deletion of system relations @@ -1433,46 +1425,40 @@ heap_drop_with_catalog(const char *relname, /* allow temp of pg_class? Guess so. */ if (!istemp && !allow_system_table_mods && IsSystemRelationName(RelationGetRelationName(rel))) - elog(ERROR, "System relation '%s' cannot be destroyed", + elog(ERROR, "System relation \"%s\" may not be dropped", RelationGetRelationName(rel)); /* ---------------- - * DROP TABLE within a transaction block is dangerous, because - * if the transaction is later rolled back there will be no way to - * undo the unlink of the relation's physical file. For now, allow it - * but emit a warning message. - * Someday we might want to consider postponing the physical unlink - * until transaction commit, but that's a lot of work... - * The only case that actually works right is for relations created - * in the current transaction, since the post-abort state would be that - * they don't exist anyway. So, no warning in that case. + * Release all buffers that belong to this relation, after writing + * any that are dirty * ---------------- */ - if (IsTransactionBlock() && !rel->rd_myxactonly) - elog(NOTICE, "Caution: DROP TABLE cannot be rolled back, so don't abort now"); + i = FlushRelationBuffers(rel, (BlockNumber) 0); + if (i < 0) + elog(ERROR, "heap_drop_with_catalog: FlushRelationBuffers returned %d", + i); /* ---------------- - * remove inheritance information + * remove rules if necessary * ---------------- */ - RelationRemoveInheritance(rel); + if (rel->rd_rules != NULL) + RelationRemoveRules(rid); + + /* triggers */ + RelationRemoveTriggers(rel); /* ---------------- - * remove indexes if necessary + * remove inheritance information * ---------------- */ - /* should ignore relhasindex */ - RelationRemoveIndexes(rel); + RelationRemoveInheritance(rel); /* ---------------- - * remove rules if necessary + * remove indexes if necessary * ---------------- */ - if (rel->rd_rules != NULL) - RelationRemoveRules(rid); - - /* triggers */ - RelationRemoveTriggers(rel); + RelationRemoveIndexes(rel); /* ---------------- * delete attribute tuples @@ -1502,23 +1488,12 @@ heap_drop_with_catalog(const char *relname, */ DeleteRelationTuple(rel); - /* - * release dirty buffers of this relation; don't bother to write them - */ - ReleaseRelationBuffers(rel); - /* ---------------- * unlink the relation's physical file and finish up. * ---------------- */ - if (rel->rd_rel->relkind != RELKIND_VIEW && ! rel->rd_unlinked) + if (rel->rd_rel->relkind != RELKIND_VIEW) smgrunlink(DEFAULT_SMGR, rel); - rel->rd_unlinked = true; - - /* - * Remember if there is a toast relation for below - */ - has_toasttable = rel->rd_rel->reltoastrelid != InvalidOid; /* * Close relcache entry, but *keep* AccessExclusiveLock on the @@ -1533,6 +1508,7 @@ heap_drop_with_catalog(const char *relname, */ RelationForgetRelation(rid); + /* and from the temp-table map */ if (istemp) remove_temp_rel_by_relid(rid); |