]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix nasty TRUNCATE bug reported by Darrin Ladd. RelationTruncateIndexes
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 30 Sep 2000 18:28:53 +0000 (18:28 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 30 Sep 2000 18:28:53 +0000 (18:28 +0000)
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.

src/backend/catalog/heap.c

index 1e4dca2b304874b533159d771e14e9a17400a35c..e7935b48714b5cb25861ef2fae5642d9eba86520 100644 (file)
@@ -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);
 }