8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*
14
14
* INTERFACE ROUTINES
@@ -76,7 +76,7 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation,
76
76
IndexInfo * indexInfo , Node * oldPred ,
77
77
IndexStrategy indexStrategy );
78
78
static Oid IndexGetRelation (Oid indexId );
79
- static bool activate_index (Oid indexId , bool activate );
79
+ static bool activate_index (Oid indexId , bool activate , bool inplace );
80
80
81
81
82
82
static bool reindexing = false;
@@ -1430,7 +1430,11 @@ setRelhasindex(Oid relid, bool hasindex)
1430
1430
*/
1431
1431
pg_class = heap_openr (RelationRelationName , RowExclusiveLock );
1432
1432
1433
+ #ifdef OLD_FILE_NAMING
1433
1434
if (!IsIgnoringSystemIndexes ())
1435
+ #else
1436
+ if (!IsIgnoringSystemIndexes () && (!IsReindexProcessing () || pg_class -> rd_rel -> relhasindex ))
1437
+ #endif /* OLD_FILE_NAMING */
1434
1438
{
1435
1439
tuple = SearchSysCacheCopy (RELOID ,
1436
1440
ObjectIdGetDatum (relid ),
@@ -1462,7 +1466,11 @@ setRelhasindex(Oid relid, bool hasindex)
1462
1466
* Update hasindex in pg_class.
1463
1467
* ----------------
1464
1468
*/
1469
+ if (pg_class_scan )
1470
+ LockBuffer (pg_class_scan -> rs_cbuf , BUFFER_LOCK_EXCLUSIVE );
1465
1471
((Form_pg_class ) GETSTRUCT (tuple ))-> relhasindex = hasindex ;
1472
+ if (pg_class_scan )
1473
+ LockBuffer (pg_class_scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
1466
1474
1467
1475
if (pg_class_scan )
1468
1476
{
@@ -1471,6 +1479,7 @@ setRelhasindex(Oid relid, bool hasindex)
1471
1479
/* Send out shared cache inval if necessary */
1472
1480
if (!IsBootstrapProcessingMode ())
1473
1481
RelationInvalidateHeapTuple (pg_class , tuple );
1482
+ BufferSync ();
1474
1483
}
1475
1484
else
1476
1485
{
@@ -1496,6 +1505,75 @@ setRelhasindex(Oid relid, bool hasindex)
1496
1505
heap_close (pg_class , RowExclusiveLock );
1497
1506
}
1498
1507
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
+
1499
1577
/* ----------------
1500
1578
* UpdateStats
1501
1579
* ----------------
@@ -1552,7 +1630,12 @@ UpdateStats(Oid relid, long reltuples)
1552
1630
*/
1553
1631
pg_class = heap_openr (RelationRelationName , RowExclusiveLock );
1554
1632
1633
+ #ifdef OLD_FILE_NAMING
1555
1634
in_place_upd = (IsReindexProcessing () || IsBootstrapProcessingMode ());
1635
+ #else
1636
+ in_place_upd = (IsIgnoringSystemIndexes () || (IsReindexProcessing () &&
1637
+ relid == RelOid_pg_class ));
1638
+ #endif /* OLD_FILE_NAMING */
1556
1639
1557
1640
if (!in_place_upd )
1558
1641
{
@@ -1631,8 +1714,10 @@ UpdateStats(Oid relid, long reltuples)
1631
1714
* visibility of changes, so we cheat. Also cheat if REINDEX.
1632
1715
*/
1633
1716
rd_rel = (Form_pg_class ) GETSTRUCT (tuple );
1717
+ LockBuffer (pg_class_scan -> rs_cbuf , BUFFER_LOCK_EXCLUSIVE );
1634
1718
rd_rel -> relpages = relpages ;
1635
1719
rd_rel -> reltuples = reltuples ;
1720
+ LockBuffer (pg_class_scan -> rs_cbuf , BUFFER_LOCK_UNLOCK );
1636
1721
WriteNoReleaseBuffer (pg_class_scan -> rs_cbuf );
1637
1722
if (!IsBootstrapProcessingMode ())
1638
1723
RelationInvalidateHeapTuple (pg_class , tuple );
@@ -1924,19 +2009,19 @@ IndexGetRelation(Oid indexId)
1924
2009
* ---------------------------------
1925
2010
*/
1926
2011
static bool
1927
- activate_index (Oid indexId , bool activate )
2012
+ activate_index (Oid indexId , bool activate , bool inplace )
1928
2013
{
1929
2014
if (!activate ) /* Currently does nothing */
1930
2015
return true;
1931
- return reindex_index (indexId , false);
2016
+ return reindex_index (indexId , false, inplace );
1932
2017
}
1933
2018
1934
2019
/* --------------------------------
1935
2020
* reindex_index - This routine is used to recreate an index
1936
2021
* --------------------------------
1937
2022
*/
1938
2023
bool
1939
- reindex_index (Oid indexId , bool force )
2024
+ reindex_index (Oid indexId , bool force , bool inplace )
1940
2025
{
1941
2026
Relation iRel ,
1942
2027
indexRelation ,
@@ -1996,18 +2081,25 @@ reindex_index(Oid indexId, bool force)
1996
2081
if (iRel == NULL )
1997
2082
elog (ERROR , "reindex_index: can't open index relation" );
1998
2083
2084
+ #ifndef OLD_FILE_NAMING
2085
+ if (!inplace )
2086
+ setNewRelfilenode (iRel );
2087
+ #endif /* OLD_FILE_NAMING */
1999
2088
/* Obtain exclusive lock on it, just to be sure */
2000
2089
LockRelation (iRel , AccessExclusiveLock );
2001
2090
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
+ }
2011
2103
2012
2104
/* Initialize the index and rebuild */
2013
2105
InitIndexStrategy (indexInfo -> ii_NumIndexAttrs , iRel , accessMethodId );
@@ -2064,15 +2156,57 @@ reindex_relation(Oid relid, bool force)
2064
2156
bool old ,
2065
2157
reindexed ;
2066
2158
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 */
2067
2197
old = SetReindexProcessing (true);
2068
- if (IndexesAreActive ( relid , true) )
2198
+ if (deactivate_needed )
2069
2199
{
2070
- if (! force )
2200
+ if (IndexesAreActive ( relid , upd_pg_class_inplace ) )
2071
2201
{
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 ();
2074
2209
}
2075
- activate_indexes_of_a_table (relid , false);
2076
2210
}
2077
2211
2078
2212
indexRelation = heap_openr (IndexRelationName , AccessShareLock );
@@ -2085,7 +2219,7 @@ reindex_relation(Oid relid, bool force)
2085
2219
{
2086
2220
Form_pg_index index = (Form_pg_index ) GETSTRUCT (indexTuple );
2087
2221
2088
- if (activate_index (index -> indexrelid , true))
2222
+ if (activate_index (index -> indexrelid , true, overwrite ))
2089
2223
reindexed = true;
2090
2224
else
2091
2225
{
@@ -2096,7 +2230,30 @@ reindex_relation(Oid relid, bool force)
2096
2230
heap_endscan (scan );
2097
2231
heap_close (indexRelation , AccessShareLock );
2098
2232
if (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
+ }
2100
2256
SetReindexProcessing (old );
2257
+
2101
2258
return reindexed ;
2102
2259
}
0 commit comments