88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.130 2000/11/16 22:30:17 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.131 2000/12/08 06:17:57 inoue Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -76,7 +76,7 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation,
7676IndexInfo * indexInfo ,Node * oldPred ,
7777IndexStrategy indexStrategy );
7878static Oid IndexGetRelation (Oid indexId );
79- static bool activate_index (Oid indexId ,bool activate );
79+ static bool activate_index (Oid indexId ,bool activate , bool inplace );
8080
8181
8282static bool reindexing = false;
@@ -1430,7 +1430,11 @@ setRelhasindex(Oid relid, bool hasindex)
14301430 */
14311431pg_class = heap_openr (RelationRelationName ,RowExclusiveLock );
14321432
1433+ #ifdef OLD_FILE_NAMING
14331434if (!IsIgnoringSystemIndexes ())
1435+ #else
1436+ if (!IsIgnoringSystemIndexes ()&& (!IsReindexProcessing ()|| pg_class -> rd_rel -> relhasindex ))
1437+ #endif /* OLD_FILE_NAMING */
14341438{
14351439tuple = SearchSysCacheCopy (RELOID ,
14361440ObjectIdGetDatum (relid ),
@@ -1462,7 +1466,11 @@ setRelhasindex(Oid relid, bool hasindex)
14621466 *Update hasindex in pg_class.
14631467 * ----------------
14641468 */
1469+ if (pg_class_scan )
1470+ LockBuffer (pg_class_scan -> rs_cbuf ,BUFFER_LOCK_EXCLUSIVE );
14651471((Form_pg_class )GETSTRUCT (tuple ))-> relhasindex = hasindex ;
1472+ if (pg_class_scan )
1473+ LockBuffer (pg_class_scan -> rs_cbuf ,BUFFER_LOCK_UNLOCK );
14661474
14671475if (pg_class_scan )
14681476{
@@ -1471,6 +1479,7 @@ setRelhasindex(Oid relid, bool hasindex)
14711479/* Send out shared cache inval if necessary */
14721480if (!IsBootstrapProcessingMode ())
14731481RelationInvalidateHeapTuple (pg_class ,tuple );
1482+ BufferSync ();
14741483}
14751484else
14761485{
@@ -1496,6 +1505,75 @@ setRelhasindex(Oid relid, bool hasindex)
14961505heap_close (pg_class ,RowExclusiveLock );
14971506}
14981507
1508+ #ifndef OLD_FILE_NAMING
1509+ void
1510+ setNewRelfilenode (Relation relation )
1511+ {
1512+ Relation pg_class ,idescs [Num_pg_class_indices ];
1513+ Oid newrelfilenode ;
1514+ bool in_place_update = false;
1515+ HeapTupleData lockTupleData ;
1516+ HeapTuple classTuple ;
1517+ Buffer buffer ;
1518+ RelationData workrel ;
1519+
1520+ Assert (!IsSystemRelationName (NameStr (relation -> rd_rel -> relname ))|| relation -> rd_rel -> relkind == RELKIND_INDEX );
1521+
1522+ pg_class = heap_openr (RelationRelationName ,RowExclusiveLock );
1523+ /* Fetch and lock the classTuple associated with this relation */
1524+ if (!LockClassinfoForUpdate (relation -> rd_id ,& lockTupleData ,& buffer , true))
1525+ elog (ERROR ,"setNewRelfilenode impossible to lock class tuple" );
1526+ if (IsIgnoringSystemIndexes ())
1527+ in_place_update = true;
1528+ /* Allocate a new relfilenode */
1529+ newrelfilenode = newoid ();
1530+ /* update pg_class tuple with new relfilenode */
1531+ if (!in_place_update )
1532+ {
1533+ classTuple = heap_copytuple (& lockTupleData );
1534+ ReleaseBuffer (buffer );
1535+ ((Form_pg_class )GETSTRUCT (classTuple ))-> relfilenode = newrelfilenode ;
1536+ heap_update (pg_class ,& classTuple -> t_self ,classTuple ,NULL );
1537+ }
1538+ /* unlink old relfilenode */
1539+ DropRelationBuffers (relation );
1540+ smgrunlink (DEFAULT_SMGR ,relation );
1541+ /* cleanup pg_internal.init if necessary */
1542+ if (relation -> rd_isnailed )
1543+ unlink (RELCACHE_INIT_FILENAME );
1544+ /* create another storage file. Is it a little ugly ? */
1545+ memcpy ((char * )& workrel ,relation ,sizeof (RelationData ));
1546+ workrel .rd_node .relNode = newrelfilenode ;
1547+ heap_storage_create (& workrel );
1548+ /* update pg_class tuple with new relfilenode in place */
1549+ if (in_place_update )
1550+ {
1551+ classTuple = & lockTupleData ;
1552+ /* Send out shared cache inval if necessary */
1553+ if (!IsBootstrapProcessingMode ())
1554+ RelationInvalidateHeapTuple (pg_class ,classTuple );
1555+ /* Update the buffer in-place */
1556+ LockBuffer (buffer ,BUFFER_LOCK_EXCLUSIVE );
1557+ ((Form_pg_class )GETSTRUCT (classTuple ))-> relfilenode = newrelfilenode ;
1558+ LockBuffer (buffer ,BUFFER_LOCK_UNLOCK );
1559+ WriteBuffer (buffer );
1560+ BufferSync ();
1561+ }
1562+ /* Keep the catalog indices up to date */
1563+ if (!in_place_update && pg_class -> rd_rel -> relhasindex )
1564+ {
1565+ CatalogOpenIndices (Num_pg_class_indices ,Name_pg_class_indices ,
1566+ idescs );
1567+ CatalogIndexInsert (idescs ,Num_pg_class_indices ,pg_class ,classTuple );
1568+ CatalogCloseIndices (Num_pg_class_indices ,idescs );
1569+ heap_freetuple (classTuple );
1570+ }
1571+ heap_close (pg_class ,NoLock );
1572+ /* Make sure the relfilenode change */
1573+ CommandCounterIncrement ();
1574+ }
1575+ #endif /* OLD_FILE_NAMING */
1576+
14991577/* ----------------
15001578 *UpdateStats
15011579 * ----------------
@@ -1552,7 +1630,12 @@ UpdateStats(Oid relid, long reltuples)
15521630 */
15531631pg_class = heap_openr (RelationRelationName ,RowExclusiveLock );
15541632
1633+ #ifdef OLD_FILE_NAMING
15551634in_place_upd = (IsReindexProcessing ()|| IsBootstrapProcessingMode ());
1635+ #else
1636+ in_place_upd = (IsIgnoringSystemIndexes ()|| (IsReindexProcessing ()&&
1637+ relid == RelOid_pg_class ));
1638+ #endif /* OLD_FILE_NAMING */
15561639
15571640if (!in_place_upd )
15581641{
@@ -1631,8 +1714,10 @@ UpdateStats(Oid relid, long reltuples)
16311714 * visibility of changes, so we cheat. Also cheat if REINDEX.
16321715 */
16331716rd_rel = (Form_pg_class )GETSTRUCT (tuple );
1717+ LockBuffer (pg_class_scan -> rs_cbuf ,BUFFER_LOCK_EXCLUSIVE );
16341718rd_rel -> relpages = relpages ;
16351719rd_rel -> reltuples = reltuples ;
1720+ LockBuffer (pg_class_scan -> rs_cbuf ,BUFFER_LOCK_UNLOCK );
16361721WriteNoReleaseBuffer (pg_class_scan -> rs_cbuf );
16371722if (!IsBootstrapProcessingMode ())
16381723RelationInvalidateHeapTuple (pg_class ,tuple );
@@ -1924,19 +2009,19 @@ IndexGetRelation(Oid indexId)
19242009 * ---------------------------------
19252010 */
19262011static bool
1927- activate_index (Oid indexId ,bool activate )
2012+ activate_index (Oid indexId ,bool activate , bool inplace )
19282013{
19292014if (!activate )/* Currently does nothing */
19302015return true;
1931- return reindex_index (indexId , false);
2016+ return reindex_index (indexId , false, inplace );
19322017}
19332018
19342019/* --------------------------------
19352020 * reindex_index - This routine is used to recreate an index
19362021 * --------------------------------
19372022 */
19382023bool
1939- reindex_index (Oid indexId ,bool force )
2024+ reindex_index (Oid indexId ,bool force , bool inplace )
19402025{
19412026Relation iRel ,
19422027indexRelation ,
@@ -1996,18 +2081,25 @@ reindex_index(Oid indexId, bool force)
19962081if (iRel == NULL )
19972082elog (ERROR ,"reindex_index: can't open index relation" );
19982083
2084+ #ifndef OLD_FILE_NAMING
2085+ if (!inplace )
2086+ setNewRelfilenode (iRel );
2087+ #endif /* OLD_FILE_NAMING */
19992088/* Obtain exclusive lock on it, just to be sure */
20002089LockRelation (iRel ,AccessExclusiveLock );
20012090
2002- /*
2003- * Release any buffers associated with this index.If they're dirty,
2004- * they're just dropped without bothering to flush to disk.
2005- */
2006- DropRelationBuffers (iRel );
2007-
2008- /* Now truncate the actual data and set blocks to zero */
2009- smgrtruncate (DEFAULT_SMGR ,iRel ,0 );
2010- iRel -> rd_nblocks = 0 ;
2091+ if (inplace )
2092+ {
2093+ /*
2094+ * Release any buffers associated with this index.If they're dirty,
2095+ * they're just dropped without bothering to flush to disk.
2096+ */
2097+ DropRelationBuffers (iRel );
2098+
2099+ /* Now truncate the actual data and set blocks to zero */
2100+ smgrtruncate (DEFAULT_SMGR ,iRel ,0 );
2101+ iRel -> rd_nblocks = 0 ;
2102+ }
20112103
20122104/* Initialize the index and rebuild */
20132105InitIndexStrategy (indexInfo -> ii_NumIndexAttrs ,iRel ,accessMethodId );
@@ -2064,15 +2156,57 @@ reindex_relation(Oid relid, bool force)
20642156bool old ,
20652157reindexed ;
20662158
2159+ bool deactivate_needed ,overwrite ,upd_pg_class_inplace ;
2160+ #ifdef OLD_FILE_NAMING
2161+ overwrite = upd_pg_class_inplace = deactivate_needed = true;
2162+ #else
2163+ Relation rel ;
2164+ overwrite = upd_pg_class_inplace = deactivate_needed = false;
2165+ /*
2166+ * avoid heap_update() pg_class tuples while processing
2167+ * reindex for pg_class.
2168+ */
2169+ if (IsIgnoringSystemIndexes ())
2170+ upd_pg_class_inplace = true;
2171+ /*
2172+ * ignore the indexes of the target system relation while processing
2173+ * reindex.
2174+ */
2175+ rel = RelationIdGetRelation (relid );
2176+ if (!IsIgnoringSystemIndexes ()&& IsSystemRelationName (NameStr (rel -> rd_rel -> relname )))
2177+ deactivate_needed = true;
2178+ #ifndef ENABLE_REINDEX_NAILED_RELATIONS
2179+ /*
2180+ * nailed relations are never updated.
2181+ * We couldn't keep the consistency between the relation
2182+ * descriptors and pg_class tuples.
2183+ */
2184+ if (rel -> rd_isnailed )
2185+ {
2186+ if (IsIgnoringSystemIndexes ())
2187+ {
2188+ overwrite = true;
2189+ deactivate_needed = true;
2190+ }
2191+ else
2192+ elog (ERROR ,"the target relation %u is nailed" ,relid );
2193+ }
2194+ #endif /* ENABLE_REINDEX_NAILED_RELATIONS */
2195+ RelationClose (rel );
2196+ #endif /* OLD_FILE_NAMING */
20672197old = SetReindexProcessing (true);
2068- if (IndexesAreActive ( relid , true) )
2198+ if (deactivate_needed )
20692199{
2070- if (! force )
2200+ if (IndexesAreActive ( relid , upd_pg_class_inplace ) )
20712201{
2072- SetReindexProcessing (old );
2073- return false;
2202+ if (!force )
2203+ {
2204+ SetReindexProcessing (old );
2205+ return false;
2206+ }
2207+ activate_indexes_of_a_table (relid , false);
2208+ CommandCounterIncrement ();
20742209}
2075- activate_indexes_of_a_table (relid , false);
20762210}
20772211
20782212indexRelation = heap_openr (IndexRelationName ,AccessShareLock );
@@ -2085,7 +2219,7 @@ reindex_relation(Oid relid, bool force)
20852219{
20862220Form_pg_index index = (Form_pg_index )GETSTRUCT (indexTuple );
20872221
2088- if (activate_index (index -> indexrelid , true))
2222+ if (activate_index (index -> indexrelid , true, overwrite ))
20892223reindexed = true;
20902224else
20912225{
@@ -2096,7 +2230,30 @@ reindex_relation(Oid relid, bool force)
20962230heap_endscan (scan );
20972231heap_close (indexRelation ,AccessShareLock );
20982232if (reindexed )
2099- setRelhasindex (relid , true);
2233+ /*
2234+ * Ok,we could use the reindexed indexes of the target
2235+ * system relation now.
2236+ */
2237+ {
2238+ if (deactivate_needed )
2239+ {
2240+ if (!overwrite && relid == RelOid_pg_class )
2241+ {
2242+ /*
2243+ * For pg_class, relhasindex should be set
2244+ * to true here in place.
2245+ */
2246+ setRelhasindex (relid , true);
2247+ CommandCounterIncrement ();
2248+ /*
2249+ * However the following setRelhasindex()
2250+ * is needed to keep consistency with WAL.
2251+ */
2252+ }
2253+ setRelhasindex (relid , true);
2254+ }
2255+ }
21002256SetReindexProcessing (old );
2257+
21012258return reindexed ;
21022259}