77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.95 1999/11/16 04:13:55 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.96 1999/11/21 20:01:10 tgl Exp $
1111 *
1212 *
1313 * INTERFACE ROUTINES
@@ -72,6 +72,7 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation,
7272 int numberOfAttributes , AttrNumber * attributeNumber ,
7373 IndexStrategy indexStrategy , uint16 parameterCount ,
7474 Datum * parameter , FuncIndexInfoPtr funcInfo , PredInfo * predInfo );
75+ static Oid IndexGetRelation (Oid indexId );
7576
7677/* ----------------------------------------------------------------
7778 * sysatts is a structure containing attribute tuple forms
@@ -1109,7 +1110,8 @@ index_create(char *heapRelationName,
11091110void
11101111index_destroy (Oid indexId )
11111112{
1112- Relation userindexRelation ;
1113+ Relation userHeapRelation ;
1114+ Relation userIndexRelation ;
11131115 Relation indexRelation ;
11141116 Relation relationRelation ;
11151117 Relation attributeRelation ;
@@ -1118,12 +1120,21 @@ index_destroy(Oid indexId)
11181120
11191121 Assert (OidIsValid (indexId ));
11201122
1121- userindexRelation = index_open (indexId );
1122-
1123- /*
1124- * Get exclusive lock to ensure no one else is scanning this index.
1123+ /* ----------------
1124+ * To drop an index safely, we must grab exclusive lock on its parent
1125+ * table; otherwise there could be other backends using the index!
1126+ * Exclusive lock on the index alone is insufficient because the index
1127+ * access routines are a little slipshod about obtaining adequate locking
1128+ * (see ExecOpenIndices()). We do grab exclusive lock on the index too,
1129+ * just to be safe. Both locks must be held till end of transaction,
1130+ * else other backends will still see this index in pg_index.
1131+ * ----------------
11251132 */
1126- LockRelation (userindexRelation , AccessExclusiveLock );
1133+ userHeapRelation = heap_open (IndexGetRelation (indexId ),
1134+ AccessExclusiveLock );
1135+
1136+ userIndexRelation = index_open (indexId );
1137+ LockRelation (userIndexRelation , AccessExclusiveLock );
11271138
11281139 /* ----------------
11291140 * DROP INDEX within a transaction block is dangerous, because
@@ -1137,14 +1148,13 @@ index_destroy(Oid indexId)
11371148 * they don't exist anyway. So, no warning in that case.
11381149 * ----------------
11391150 */
1140- if (IsTransactionBlock () && ! userindexRelation -> rd_myxactonly )
1151+ if (IsTransactionBlock () && ! userIndexRelation -> rd_myxactonly )
11411152 elog (NOTICE , "Caution: DROP INDEX cannot be rolled back, so don't abort now" );
11421153
11431154 /* ----------------
11441155 * fix DESCRIPTION relation
11451156 * ----------------
11461157 */
1147-
11481158 DeleteComments (indexId );
11491159
11501160 /* ----------------
@@ -1198,14 +1208,18 @@ index_destroy(Oid indexId)
11981208 heap_close (indexRelation , RowExclusiveLock );
11991209
12001210 /*
1201- * flush cache and physically remove the file
1211+ * flush buffer cache and physically remove the file
12021212 */
1203- ReleaseRelationBuffers (userindexRelation );
1213+ ReleaseRelationBuffers (userIndexRelation );
12041214
1205- if (smgrunlink (DEFAULT_SMGR , userindexRelation ) != SM_SUCCESS )
1215+ if (smgrunlink (DEFAULT_SMGR , userIndexRelation ) != SM_SUCCESS )
12061216 elog (ERROR , "index_destroy: unlink: %m" );
12071217
1208- index_close (userindexRelation );
1218+ /*
1219+ * Close rels, but keep locks
1220+ */
1221+ index_close (userIndexRelation );
1222+ heap_close (userHeapRelation , NoLock );
12091223
12101224 RelationForgetRelation (indexId );
12111225
@@ -1720,6 +1734,30 @@ index_build(Relation heapRelation,
17201734 predInfo );
17211735}
17221736
1737+ /*
1738+ * IndexGetRelation: given an index's relation OID, get the OID of the
1739+ * relation it is an index on. Uses the system cache.
1740+ */
1741+ static Oid
1742+ IndexGetRelation (Oid indexId )
1743+ {
1744+ HeapTuple tuple ;
1745+ Form_pg_index index ;
1746+
1747+ tuple = SearchSysCacheTuple (INDEXRELID ,
1748+ ObjectIdGetDatum (indexId ),
1749+ 0 , 0 , 0 );
1750+ if (!HeapTupleIsValid (tuple ))
1751+ {
1752+ elog (ERROR , "IndexGetRelation: can't find index id %u" ,
1753+ indexId );
1754+ }
1755+ index = (Form_pg_index ) GETSTRUCT (tuple );
1756+ Assert (index -> indexrelid == indexId );
1757+
1758+ return index -> indrelid ;
1759+ }
1760+
17231761/*
17241762 * IndexIsUnique: given an index's relation OID, see if it
17251763 * is unique using the system cache.
0 commit comments