*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.95 1999/11/16 04:13:55 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.96 1999/11/21 20:01:10 tgl Exp $
*
*
* INTERFACE ROUTINES
int numberOfAttributes, AttrNumber *attributeNumber,
IndexStrategy indexStrategy, uint16 parameterCount,
Datum *parameter, FuncIndexInfoPtr funcInfo, PredInfo *predInfo);
+static Oid IndexGetRelation(Oid indexId);
/* ----------------------------------------------------------------
* sysatts is a structure containing attribute tuple forms
void
index_destroy(Oid indexId)
{
- Relation userindexRelation;
+ Relation userHeapRelation;
+ Relation userIndexRelation;
Relation indexRelation;
Relation relationRelation;
Relation attributeRelation;
Assert(OidIsValid(indexId));
- userindexRelation = index_open(indexId);
-
- /*
- * Get exclusive lock to ensure no one else is scanning this index.
+ /* ----------------
+ * To drop an index safely, we must grab exclusive lock on its parent
+ * table; otherwise there could be other backends using the index!
+ * Exclusive lock on the index alone is insufficient because the index
+ * access routines are a little slipshod about obtaining adequate locking
+ * (see ExecOpenIndices()). We do grab exclusive lock on the index too,
+ * just to be safe. Both locks must be held till end of transaction,
+ * else other backends will still see this index in pg_index.
+ * ----------------
*/
- LockRelation(userindexRelation, AccessExclusiveLock);
+ userHeapRelation = heap_open(IndexGetRelation(indexId),
+ AccessExclusiveLock);
+
+ userIndexRelation = index_open(indexId);
+ LockRelation(userIndexRelation, AccessExclusiveLock);
/* ----------------
* DROP INDEX within a transaction block is dangerous, because
* they don't exist anyway. So, no warning in that case.
* ----------------
*/
- if (IsTransactionBlock() && ! userindexRelation->rd_myxactonly)
+ if (IsTransactionBlock() && ! userIndexRelation->rd_myxactonly)
elog(NOTICE, "Caution: DROP INDEX cannot be rolled back, so don't abort now");
/* ----------------
* fix DESCRIPTION relation
* ----------------
*/
-
DeleteComments(indexId);
/* ----------------
heap_close(indexRelation, RowExclusiveLock);
/*
- * flush cache and physically remove the file
+ * flush buffer cache and physically remove the file
*/
- ReleaseRelationBuffers(userindexRelation);
+ ReleaseRelationBuffers(userIndexRelation);
- if (smgrunlink(DEFAULT_SMGR, userindexRelation) != SM_SUCCESS)
+ if (smgrunlink(DEFAULT_SMGR, userIndexRelation) != SM_SUCCESS)
elog(ERROR, "index_destroy: unlink: %m");
- index_close(userindexRelation);
+ /*
+ * Close rels, but keep locks
+ */
+ index_close(userIndexRelation);
+ heap_close(userHeapRelation, NoLock);
RelationForgetRelation(indexId);
predInfo);
}
+/*
+ * IndexGetRelation: given an index's relation OID, get the OID of the
+ * relation it is an index on. Uses the system cache.
+ */
+static Oid
+IndexGetRelation(Oid indexId)
+{
+ HeapTuple tuple;
+ Form_pg_index index;
+
+ tuple = SearchSysCacheTuple(INDEXRELID,
+ ObjectIdGetDatum(indexId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ {
+ elog(ERROR, "IndexGetRelation: can't find index id %u",
+ indexId);
+ }
+ index = (Form_pg_index) GETSTRUCT(tuple);
+ Assert(index->indexrelid == indexId);
+
+ return index->indrelid;
+}
+
/*
* IndexIsUnique: given an index's relation OID, see if it
* is unique using the system cache.