diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-09-30 18:28:53 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-09-30 18:28:53 +0000 |
commit | 36786a815005b3f1e686540976489d6ea8b6757d (patch) | |
tree | f1429a762e83af45a7b5a2e4df18b37660b840a2 /src | |
parent | 0ba77c14aafcc43ba1c77900a0452564bf9bff18 (diff) | |
download | postgresql-36786a815005b3f1e686540976489d6ea8b6757d.tar.gz postgresql-36786a815005b3f1e686540976489d6ea8b6757d.zip |
Fix nasty TRUNCATE bug reported by Darrin Ladd. RelationTruncateIndexes
would close and then re-open rel being truncated. Depending on the
luck of the draw, the re-opened relcache entry might or might not be
at the same physical location as before. Unfortunately, if it wasn't
then heap_truncate would crash and burn, because it still had a pointer
at the old location. Fix is to open and then close rel in
RelationTruncateIndexes, so that rel's refcount never goes to zero
until heap_truncate is done.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/heap.c | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 1e4dca2b304..e7935b48714 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.145 2000/09/29 18:21:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.146 2000/09/30 18:28:53 tgl Exp $ * * * INTERFACE ROUTINES @@ -1064,32 +1064,32 @@ DeleteRelationTuple(Relation rel) * RelationTruncateIndexes - This routine is used to truncate all * indices associated with the heap relation to zero tuples. * The routine will truncate and then reconstruct the indices on - * the relation specified by the heapRelation parameter. + * the relation specified by the heapId parameter. * -------------------------------- */ static void -RelationTruncateIndexes(Relation heapRelation) +RelationTruncateIndexes(Oid heapId) { - Relation indexRelation, - currentIndex; + Relation indexRelation; ScanKeyData entry; HeapScanDesc scan; - HeapTuple indexTuple, - classTuple; - IndexInfo *indexInfo; - Oid heapId, - indexId, - accessMethodId; - - heapId = RelationGetRelid(heapRelation); + HeapTuple indexTuple; - /* Scan pg_index to find indexes on heapRelation */ + /* Scan pg_index to find indexes on specified heap */ indexRelation = heap_openr(IndexRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ, ObjectIdGetDatum(heapId)); scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry); + while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0))) { + Oid indexId, + accessMethodId; + IndexInfo *indexInfo; + HeapTuple classTuple; + Relation heapRelation, + currentIndex; + /* * For each index, fetch info needed for index_build */ @@ -1105,10 +1105,16 @@ RelationTruncateIndexes(Relation heapRelation) indexId); accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; + /* + * We have to re-open the heap rel each time through this loop + * because index_build will close it again. We need grab no lock, + * however, because we assume heap_truncate is holding an exclusive + * lock on the heap rel. + */ + heapRelation = heap_open(heapId, NoLock); + /* Open the index relation */ currentIndex = index_open(indexId); - if (currentIndex == NULL) - elog(ERROR, "RelationTruncateIndexes: can't open index relation"); /* Obtain exclusive lock on it, just to be sure */ LockRelation(currentIndex, AccessExclusiveLock); @@ -1127,15 +1133,10 @@ RelationTruncateIndexes(Relation heapRelation) InitIndexStrategy(indexInfo->ii_NumIndexAttrs, currentIndex, accessMethodId); index_build(heapRelation, currentIndex, indexInfo, NULL); - /* * index_build will close both the heap and index relations (but - * not give up the locks we hold on them). That's fine for the - * index, but we need to open the heap again. We need no new - * lock, since this backend still has the exclusive lock grabbed - * by heap_truncate. + * not give up the locks we hold on them). */ - heapRelation = heap_open(heapId, NoLock); } /* Complete the scan and close pg_index */ @@ -1191,17 +1192,12 @@ heap_truncate(char *relname) rel->rd_nblocks = 0; /* If this relation has indexes, truncate the indexes too */ - RelationTruncateIndexes(rel); + RelationTruncateIndexes(rid); /* * Close the relation, but keep exclusive lock on it until commit. */ heap_close(rel, NoLock); - - /* - * Is this really necessary? - */ - RelationForgetRelation(rid); } |