aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-09-30 18:28:53 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-09-30 18:28:53 +0000
commit36786a815005b3f1e686540976489d6ea8b6757d (patch)
treef1429a762e83af45a7b5a2e4df18b37660b840a2 /src
parent0ba77c14aafcc43ba1c77900a0452564bf9bff18 (diff)
downloadpostgresql-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.c52
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);
}