@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $ Header : / cvsroot / pgsql / src / backend / catalog / index . c , v 1.216 2003 / 09 / 23 01 : 51 : 09 inoue Exp $
* $ Header : / cvsroot / pgsql / src / backend / catalog / index . c , v 1.217 2003 / 09 / 24 18 : 54 : 01 tgl Exp $
*
*
*
*
* INTERFACE ROUTINES
* INTERFACE ROUTINES
@ -76,27 +76,8 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
Oid * classOids ,
Oid * classOids ,
bool primary ) ;
bool primary ) ;
static Oid IndexGetRelation ( Oid indexId ) ;
static Oid IndexGetRelation ( Oid indexId ) ;
static bool activate_index ( Oid indexId , bool activate , bool inplace ) ;
static bool reindexing = false ;
bool
SetReindexProcessing ( bool reindexmode )
{
bool old = reindexing ;
reindexing = reindexmode ;
return old ;
}
bool
IsReindexProcessing ( void )
{
return reindexing ;
}
/*
/*
* ConstructTupleDescriptor
* ConstructTupleDescriptor
*
*
@ -498,8 +479,6 @@ index_create(Oid heapRelationId,
Oid indexoid ;
Oid indexoid ;
int i ;
int i ;
SetReindexProcessing ( false ) ;
/*
/*
* Only SELECT . . . FOR UPDATE are allowed while doing this
* Only SELECT . . . FOR UPDATE are allowed while doing this
*/
*/
@ -973,46 +952,6 @@ FormIndexDatum(IndexInfo *indexInfo,
}
}
/* ---------------------------------------------
* Indexes of the relation active ?
*
* Caller must hold an adequate lock on the relation to ensure the
* answer won ' t be changing .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
bool
IndexesAreActive ( Relation heaprel )
{
bool isactive ;
Relation indexRelation ;
HeapScanDesc scan ;
ScanKeyData entry ;
if ( heaprel - > rd_rel - > relkind ! = RELKIND_RELATION & &
heaprel - > rd_rel - > relkind ! = RELKIND_TOASTVALUE )
ereport ( ERROR ,
( errcode ( ERRCODE_WRONG_OBJECT_TYPE ) ,
errmsg ( " relation \" %s \" isn't an indexable relation " ,
RelationGetRelationName ( heaprel ) ) ) ) ;
/* If pg_class.relhasindex is set, indexes are active */
isactive = heaprel - > rd_rel - > relhasindex ;
if ( isactive )
return isactive ;
/* Otherwise, look to see if there are any indexes */
indexRelation = heap_openr ( IndexRelationName , AccessShareLock ) ;
ScanKeyEntryInitialize ( & entry , 0 ,
Anum_pg_index_indrelid , F_OIDEQ ,
ObjectIdGetDatum ( RelationGetRelid ( heaprel ) ) ) ;
scan = heap_beginscan ( indexRelation , SnapshotNow , 1 , & entry ) ;
if ( heap_getnext ( scan , ForwardScanDirection ) = = NULL )
isactive = true ; /* no indexes, so report "active" */
heap_endscan ( scan ) ;
heap_close ( indexRelation , AccessShareLock ) ;
return isactive ;
}
/* ----------------
/* ----------------
* set relhasindex of relation ' s pg_class entry
* set relhasindex of relation ' s pg_class entry
*
*
@ -1038,12 +977,13 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
HeapScanDesc pg_class_scan = NULL ;
HeapScanDesc pg_class_scan = NULL ;
/*
/*
* Find the tuple to update in pg_class .
* Find the tuple to update in pg_class . In bootstrap mode we can ' t
* use heap_update , so cheat and overwrite the tuple in - place . In
* normal processing , make a copy to scribble on .
*/
*/
pg_class = heap_openr ( RelationRelationName , RowExclusiveLock ) ;
pg_class = heap_openr ( RelationRelationName , RowExclusiveLock ) ;
if ( ! IsIgnoringSystemIndexes ( ) & &
if ( ! IsBootstrapProcessingMode ( ) )
( ! IsReindexProcessing ( ) | | pg_class - > rd_rel - > relhasindex ) )
{
{
tuple = SearchSysCacheCopy ( RELOID ,
tuple = SearchSysCacheCopy ( RELOID ,
ObjectIdGetDatum ( relid ) ,
ObjectIdGetDatum ( relid ) ,
@ -1064,15 +1004,13 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
if ( ! HeapTupleIsValid ( tuple ) )
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " could not find tuple for relation %u " , relid ) ;
elog ( ERROR , " could not find tuple for relation %u " , relid ) ;
classtuple = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
/* Apply required updates */
/*
* Update fields in the pg_class tuple .
*/
if ( pg_class_scan )
if ( pg_class_scan )
LockBuffer ( pg_class_scan - > rs_cbuf , BUFFER_LOCK_EXCLUSIVE ) ;
LockBuffer ( pg_class_scan - > rs_cbuf , BUFFER_LOCK_EXCLUSIVE ) ;
classtuple = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
if ( classtuple - > relhasindex ! = hasindex )
if ( classtuple - > relhasindex ! = hasindex )
{
{
classtuple - > relhasindex = hasindex ;
classtuple - > relhasindex = hasindex ;
@ -1141,80 +1079,48 @@ setNewRelfilenode(Relation relation)
Relation pg_class ;
Relation pg_class ;
HeapTuple tuple ;
HeapTuple tuple ;
Form_pg_class rd_rel ;
Form_pg_class rd_rel ;
HeapScanDesc pg_class_scan = NULL ;
bool in_place_upd ;
RelationData workrel ;
RelationData workrel ;
Assert ( ! IsSystemRelation ( relation ) | | IsToastRelation ( relation ) | |
/* Can't change relfilenode for nailed tables (indexes ok though) */
Assert ( ! relation - > rd_isnailed | |
relation - > rd_rel - > relkind = = RELKIND_INDEX ) ;
relation - > rd_rel - > relkind = = RELKIND_INDEX ) ;
/* Can't change for shared tables or indexes */
Assert ( ! relation - > rd_rel - > relisshared ) ;
/* Allocate a new relfilenode */
/* Allocate a new relfilenode */
newrelfilenode = newoid ( ) ;
newrelfilenode = newoid ( ) ;
/*
/*
* Find the RELATION relation tuple for the given relation .
* Find the pg_class tuple for the given relation . This is not used
* during bootstrap , so okay to use heap_update always .
*/
*/
pg_class = heap_openr ( RelationRelationName , RowExclusiveLock ) ;
pg_class = heap_openr ( RelationRelationName , RowExclusiveLock ) ;
in_place_upd = IsIgnoringSystemIndexes ( ) ;
tuple = SearchSysCacheCopy ( RELOID ,
ObjectIdGetDatum ( RelationGetRelid ( relation ) ) ,
if ( ! in_place_upd )
0 , 0 , 0 ) ;
{
tuple = SearchSysCacheCopy ( RELOID ,
ObjectIdGetDatum ( RelationGetRelid ( relation ) ) ,
0 , 0 , 0 ) ;
}
else
{
ScanKeyData key [ 1 ] ;
ScanKeyEntryInitialize ( & key [ 0 ] , 0 ,
ObjectIdAttributeNumber ,
F_OIDEQ ,
ObjectIdGetDatum ( RelationGetRelid ( relation ) ) ) ;
pg_class_scan = heap_beginscan ( pg_class , SnapshotNow , 1 , key ) ;
tuple = heap_getnext ( pg_class_scan , ForwardScanDirection ) ;
}
if ( ! HeapTupleIsValid ( tuple ) )
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " could not find tuple for relation %u " ,
elog ( ERROR , " could not find tuple for relation %u " ,
RelationGetRelid ( relation ) ) ;
RelationGetRelid ( relation ) ) ;
rd_rel = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
rd_rel = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
/* schedule unlinking old relfilenode */
smgrunlink ( DEFAULT_SMGR , relation ) ;
/* create another storage file. Is it a little ugly ? */
/* create another storage file. Is it a little ugly ? */
/* NOTE: any conflict in relfilenode value will be caught here */
memcpy ( ( char * ) & workrel , relation , sizeof ( RelationData ) ) ;
memcpy ( ( char * ) & workrel , relation , sizeof ( RelationData ) ) ;
workrel . rd_fd = - 1 ;
workrel . rd_fd = - 1 ;
workrel . rd_node . relNode = newrelfilenode ;
workrel . rd_node . relNode = newrelfilenode ;
heap_storage_create ( & workrel ) ;
heap_storage_create ( & workrel ) ;
smgrclose ( DEFAULT_SMGR , & workrel ) ;
smgrclose ( DEFAULT_SMGR , & workrel ) ;
/* schedule unlinking old relfilenode */
smgrunlink ( DEFAULT_SMGR , relation ) ;
/* update the pg_class row */
/* update the pg_class row */
if ( in_place_upd )
rd_rel - > relfilenode = newrelfilenode ;
{
simple_heap_update ( pg_class , & tuple - > t_self , tuple ) ;
LockBuffer ( pg_class_scan - > rs_cbuf , BUFFER_LOCK_EXCLUSIVE ) ;
CatalogUpdateIndexes ( pg_class , tuple ) ;
rd_rel - > relfilenode = newrelfilenode ;
LockBuffer ( pg_class_scan - > rs_cbuf , BUFFER_LOCK_UNLOCK ) ;
WriteNoReleaseBuffer ( pg_class_scan - > rs_cbuf ) ;
BufferSync ( ) ;
/* Send out shared cache inval if necessary */
if ( ! IsBootstrapProcessingMode ( ) )
CacheInvalidateHeapTuple ( pg_class , tuple ) ;
}
else
{
rd_rel - > relfilenode = newrelfilenode ;
simple_heap_update ( pg_class , & tuple - > t_self , tuple ) ;
CatalogUpdateIndexes ( pg_class , tuple ) ;
}
if ( ! pg_class_scan )
heap_freetuple ( tuple ) ;
heap_freetuple ( tuple ) ;
else
heap_endscan ( pg_class_scan ) ;
heap_close ( pg_class , RowExclusiveLock ) ;
heap_close ( pg_class , RowExclusiveLock ) ;
@ -1264,11 +1170,21 @@ UpdateStats(Oid relid, double reltuples)
whichRel = relation_open ( relid , ShareLock ) ;
whichRel = relation_open ( relid , ShareLock ) ;
/*
/*
* Find the RELATION relation tuple for the given relation .
* Find the tuple to update in pg_class . Normally we make a copy of
* the tuple using the syscache , modify it , and apply heap_update .
* But in bootstrap mode we can ' t use heap_update , so we cheat and
* overwrite the tuple in - place .
*
* We also must cheat if reindexing pg_class itself , because the
* target index may presently not be part of the set of indexes that
* CatalogUpdateIndexes would update ( see reindex_relation ) . In this
* case the stats updates will not be WAL - logged and so could be lost
* in a crash . This seems OK considering VACUUM does the same thing .
*/
*/
pg_class = heap_openr ( RelationRelationName , RowExclusiveLock ) ;
pg_class = heap_openr ( RelationRelationName , RowExclusiveLock ) ;
in_place_upd = ( IsIgnoringSystemIndexes ( ) | | IsReindexProcessing ( ) ) ;
in_place_upd = IsBootstrapProcessingMode ( ) | |
ReindexIsProcessingHeap ( RelationGetRelid ( pg_class ) ) ;
if ( ! in_place_upd )
if ( ! in_place_upd )
{
{
@ -1291,6 +1207,7 @@ UpdateStats(Oid relid, double reltuples)
if ( ! HeapTupleIsValid ( tuple ) )
if ( ! HeapTupleIsValid ( tuple ) )
elog ( ERROR , " could not find tuple for relation %u " , relid ) ;
elog ( ERROR , " could not find tuple for relation %u " , relid ) ;
rd_rel = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
/*
/*
* Figure values to insert .
* Figure values to insert .
@ -1331,18 +1248,12 @@ UpdateStats(Oid relid, double reltuples)
* also reduces the window wherein concurrent CREATE INDEX commands
* also reduces the window wherein concurrent CREATE INDEX commands
* may conflict . )
* may conflict . )
*/
*/
rd_rel = ( Form_pg_class ) GETSTRUCT ( tuple ) ;
if ( rd_rel - > relpages ! = ( int32 ) relpages | |
if ( rd_rel - > relpages ! = ( int32 ) relpages | |
rd_rel - > reltuples ! = ( float4 ) reltuples )
rd_rel - > reltuples ! = ( float4 ) reltuples )
{
{
if ( in_place_upd )
if ( in_place_upd )
{
{
/*
/* Bootstrap or reindex case: overwrite fields in place. */
* At bootstrap time , we don ' t need to worry about concurrency
* or visibility of changes , so we cheat . Also cheat if
* REINDEX .
*/
LockBuffer ( pg_class_scan - > rs_cbuf , BUFFER_LOCK_EXCLUSIVE ) ;
LockBuffer ( pg_class_scan - > rs_cbuf , BUFFER_LOCK_EXCLUSIVE ) ;
rd_rel - > relpages = ( int32 ) relpages ;
rd_rel - > relpages = ( int32 ) relpages ;
rd_rel - > reltuples = ( float4 ) reltuples ;
rd_rel - > reltuples = ( float4 ) reltuples ;
@ -1562,10 +1473,13 @@ IndexBuildHeapScan(Relation heapRelation,
* should not see any tuples inserted by open
* should not see any tuples inserted by open
* transactions - - - unless it ' s our own transaction .
* transactions - - - unless it ' s our own transaction .
* ( Consider INSERT followed by CREATE INDEX within a
* ( Consider INSERT followed by CREATE INDEX within a
* transaction . )
* transaction . ) An exception occurs when reindexing
* a system catalog , because we often release lock on
* system catalogs before committing .
*/
*/
if ( ! TransactionIdIsCurrentTransactionId (
if ( ! TransactionIdIsCurrentTransactionId (
HeapTupleHeaderGetXmin ( heapTuple - > t_data ) ) )
HeapTupleHeaderGetXmin ( heapTuple - > t_data ) )
& & ! IsSystemRelation ( heapRelation ) )
elog ( ERROR , " concurrent insert in progress " ) ;
elog ( ERROR , " concurrent insert in progress " ) ;
indexIt = true ;
indexIt = true ;
tupleIsAlive = true ;
tupleIsAlive = true ;
@ -1577,10 +1491,13 @@ IndexBuildHeapScan(Relation heapRelation,
* should not see any tuples deleted by open
* should not see any tuples deleted by open
* transactions - - - unless it ' s our own transaction .
* transactions - - - unless it ' s our own transaction .
* ( Consider DELETE followed by CREATE INDEX within a
* ( Consider DELETE followed by CREATE INDEX within a
* transaction . )
* transaction . ) An exception occurs when reindexing
* a system catalog , because we often release lock on
* system catalogs before committing .
*/
*/
if ( ! TransactionIdIsCurrentTransactionId (
if ( ! TransactionIdIsCurrentTransactionId (
HeapTupleHeaderGetXmax ( heapTuple - > t_data ) ) )
HeapTupleHeaderGetXmax ( heapTuple - > t_data ) )
& & ! IsSystemRelation ( heapRelation ) )
elog ( ERROR , " concurrent delete in progress " ) ;
elog ( ERROR , " concurrent delete in progress " ) ;
indexIt = true ;
indexIt = true ;
tupleIsAlive = false ;
tupleIsAlive = false ;
@ -1690,81 +1607,57 @@ IndexGetRelation(Oid indexId)
return result ;
return result ;
}
}
/* ---------------------------------
/*
* activate_index - - activate / deactivate the specified index .
* reindex_index - This routine is used to recreate a single index
* Note that currently PostgreSQL doesn ' t hold the
* status per index
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
static bool
activate_index ( Oid indexId , bool activate , bool inplace )
{
if ( ! activate ) /* Currently does nothing */
return true ;
return reindex_index ( indexId , false , inplace ) ;
}
/* --------------------------------
* reindex_index - This routine is used to recreate an index
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
bool
void
reindex_index ( Oid indexId , bool force , bool inplace )
reindex_index ( Oid indexId )
{
{
Relation iRel ,
Relation iRel ,
heapRelation ;
heapRelation ;
IndexInfo * indexInfo ;
IndexInfo * indexInfo ;
Oid heapId ;
Oid heapId ;
bool old ;
bool inplace ;
/*
/*
* Open our index relation and get an exclusive lock on it .
* Open our index relation and get an exclusive lock on it .
*
*
* Note : doing this before opening the parent heap relation means there ' s
* Note : for REINDEX INDEX , doing this before opening the parent heap
* a possibility for deadlock failure against another xact that is
* relation means there ' s a possibility for deadlock failure against
* doing normal accesses to the heap and index . However , it ' s not
* another xact that is doing normal accesses to the heap and index .
* real clear why you ' d be needing to do REINDEX on a table that ' s in
* However , it ' s not real clear why you ' d be wanting to do REINDEX INDEX
* active use , so I ' d rather have the protection of making sure the
* on a table that ' s in active use , so I ' d rather have the protection of
* index is locked down .
* making sure the index is locked down . In the REINDEX TABLE and
* REINDEX DATABASE cases , there is no problem because caller already
* holds exclusive lock on the parent table .
*/
*/
iRel = index_open ( indexId ) ;
iRel = index_open ( indexId ) ;
LockRelation ( iRel , AccessExclusiveLock ) ;
LockRelation ( iRel , AccessExclusiveLock ) ;
old = SetReindexProcessing ( true ) ;
/* Get OID of index's parent table */
/* Get OID of index's parent table */
heapId = iRel - > rd_index - > indrelid ;
heapId = iRel - > rd_index - > indrelid ;
/* Open the parent heap relation */
/* Open and lock the parent heap relation */
heapRelation = heap_open ( heapId , AccessExclusiveLock ) ;
heapRelation = heap_open ( heapId , AccessExclusiveLock ) ;
SetReindexProcessing ( heapId , indexId ) ;
/*
/*
* If it ' s a shared index , we must do inplace processing ( because we
* If it ' s a shared index , we must do inplace processing ( because we
* have no way to update relfilenode in other databases ) . Also , if
* have no way to update relfilenode in other databases ) . Otherwise
* it ' s a nailed - in - cache index , we must do inplace processing because
* we can do it the normal transaction - safe way .
* the relcache can ' t cope with changing its relfilenode .
*
*
* In either of these cases , we are definitely processing a system index ,
* Since inplace processing isn ' t crash - safe , we only allow it in a
* so we ' d better be ignoring system indexes .
* standalone backend . ( In the REINDEX TABLE and REINDEX DATABASE cases ,
* the caller should have detected this . )
*/
*/
if ( iRel - > rd_rel - > relisshared )
inplace = iRel - > rd_rel - > relisshared ;
{
if ( ! IsIgnoringSystemIndexes ( ) )
if ( inplace & & IsUnderPostmaster )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ) ,
( errcode ( ERRCODE_INSUFFICIENT_PRIVILEGE ) ,
errmsg ( " the target relation %u is shared " , indexId ) ) ) ;
errmsg ( " shared index \" %s \" can only be reindexed in standalone mode " ,
inplace = true ;
RelationGetRelationName ( iRel ) ) ) ) ;
}
# ifndef ENABLE_REINDEX_NAILED_RELATIONS
if ( iRel - > rd_isnailed )
{
if ( ! IsIgnoringSystemIndexes ( ) )
ereport ( ERROR ,
( errcode ( ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ) ,
errmsg ( " the target relation %u is nailed " , indexId ) ) ) ;
inplace = true ;
}
# endif /* ENABLE_REINDEX_NAILED_RELATIONS */
/* Fetch info needed for index_build */
/* Fetch info needed for index_build */
indexInfo = BuildIndexInfo ( iRel ) ;
indexInfo = BuildIndexInfo ( iRel ) ;
@ -1797,160 +1690,94 @@ reindex_index(Oid indexId, bool force, bool inplace)
* index_build will close both the heap and index relations ( but not
* index_build will close both the heap and index relations ( but not
* give up the locks we hold on them ) . So we ' re done .
* give up the locks we hold on them ) . So we ' re done .
*/
*/
SetReindexProcessing ( InvalidOid , InvalidOid ) ;
SetReindexProcessing ( old ) ;
return true ;
}
}
/*
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* reindex_relation - This routine is used to recreate all indexes
* activate_indexes_of_a_table
* of a relation ( and its toast relation too , if any ) .
* activate / deactivate indexes of the specified table .
*
*
* Caller must already hold exclusive lock on the table .
* Returns true if any indexes were rebuilt .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
bool
bool
activate_indexes_of_a_table ( Relation heaprel , bool activate )
reindex_relation ( Oid relid )
{
{
if ( IndexesAreActive ( heaprel ) )
{
if ( ! activate )
setRelhasindex ( RelationGetRelid ( heaprel ) , false , false ,
InvalidOid ) ;
else
return false ;
}
else
{
if ( activate )
reindex_relation ( RelationGetRelid ( heaprel ) , false ) ;
else
return false ;
}
return true ;
}
/* --------------------------------
* reindex_relation - This routine is used to recreate indexes
* of a relation .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
bool
reindex_relation ( Oid relid , bool force )
{
Relation indexRelation ;
ScanKeyData entry ;
HeapScanDesc scan ;
HeapTuple indexTuple ;
bool old ,
reindexed ;
bool deactivate_needed ,
overwrite ;
Relation rel ;
Relation rel ;
Oid toast_relid ;
overwrite = deactivate_needed = false ;
bool is_pg_class ;
bool result ;
List * indexIds ,
* doneIndexes ,
* indexId ;
/*
/*
* Ensure to hold an exclusive lock throughout the transaction . The
* Ensure to hold an exclusive lock throughout the transaction . The
* lock could be less intensive ( in the non - overwrite path ) but for
* lock could perhaps be less intensive ( in the non - overwrite case )
* now it ' s AccessExclusiveLock for simplicity .
* but for now it ' s AccessExclusiveLock for simplicity .
*/
*/
rel = heap_open ( relid , AccessExclusiveLock ) ;
rel = heap_open ( relid , AccessExclusiveLock ) ;
toast_relid = rel - > rd_rel - > reltoastrelid ;
/*
/*
* ignore the indexes of the target system relation while processing
* Get the list of index OIDs for this relation . ( We trust to the
* reindex .
* relcache to get this with a sequential scan if ignoring system
* indexes . )
*/
*/
if ( ! IsIgnoringSystemIndexes ( ) & &
indexIds = RelationGetIndexList ( rel ) ;
IsSystemRelation ( rel ) & & ! IsToastRelation ( rel ) )
deactivate_needed = true ;
/*
/*
* Shared system indexes must be overwritten because it ' s impossible
* reindex_index will attempt to update the pg_class rows for the
* to update pg_class tuples of all databases .
* relation and index . If we are processing pg_class itself , we
* want to make sure that the updates do not try to insert index
* entries into indexes we have not processed yet . ( When we are
* trying to recover from corrupted indexes , that could easily
* cause a crash . ) We can accomplish this because CatalogUpdateIndexes
* will use the relcache ' s index list to know which indexes to update .
* We just force the index list to be only the stuff we ' ve processed .
*
* It is okay to not insert entries into the indexes we have not
* processed yet because all of this is transaction - safe . If we fail
* partway through , the updated rows are dead and it doesn ' t matter
* whether they have index entries . Also , a new pg_class index will
* be created with an entry for its own pg_class row because we do
* setNewRelfilenode ( ) before we do index_build ( ) .
*/
*/
if ( rel - > rd_rel - > relisshared )
is_pg_class = ( RelationGetRelid ( rel ) = = RelOid_pg_class ) ;
doneIndexes = NIL ;
/* Reindex all the indexes. */
foreach ( indexId , indexIds )
{
{
if ( IsIgnoringSystemIndexes ( ) )
Oid indexOid = lfirsto ( indexId ) ;
{
overwrite = true ;
deactivate_needed = true ;
}
else
ereport ( ERROR ,
( errcode ( ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE ) ,
errmsg ( " the target relation %u is shared " , relid ) ) ) ;
}
old = SetReindexProcessing ( true ) ;
if ( is_pg_class )
RelationSetIndexList ( rel , doneIndexes ) ;
if ( deactivate_needed )
reindex_index ( indexOid ) ;
{
if ( IndexesAreActive ( rel ) )
CommandCounterIncrement ( ) ;
{
if ( ! force )
if ( is_pg_class )
{
doneIndexes = lappendo ( doneIndexes , indexOid ) ;
SetReindexProcessing ( old ) ;
heap_close ( rel , NoLock ) ;
return false ;
}
activate_indexes_of_a_table ( rel , false ) ;
CommandCounterIncrement ( ) ;
}
}
}
if ( is_pg_class )
RelationSetIndexList ( rel , indexIds ) ;
/*
/*
* Continue to hold the lock .
* Close rel , but continue to hold the lock .
*/
*/
heap_close ( rel , NoLock ) ;
heap_close ( rel , NoLock ) ;
indexRelation = heap_openr ( IndexRelationName , AccessShareLock ) ;
result = ( indexIds ! = NIL ) ;
ScanKeyEntryInitialize ( & entry , 0 , Anum_pg_index_indrelid ,
F_OIDEQ , ObjectIdGetDatum ( relid ) ) ;
scan = heap_beginscan ( indexRelation , SnapshotNow , 1 , & entry ) ;
reindexed = false ;
while ( ( indexTuple = heap_getnext ( scan , ForwardScanDirection ) ) ! = NULL )
{
Form_pg_index index = ( Form_pg_index ) GETSTRUCT ( indexTuple ) ;
if ( activate_index ( index - > indexrelid , true , overwrite ) )
reindexed = true ;
else
{
reindexed = false ;
break ;
}
}
heap_endscan ( scan ) ;
heap_close ( indexRelation , AccessShareLock ) ;
if ( reindexed )
{
/*
* Ok , we could use the reindexed indexes of the target system
* relation now .
*/
if ( deactivate_needed )
{
if ( ! overwrite & & relid = = RelOid_pg_class )
{
/*
* For pg_class , relhasindex should be set to true here in
* place .
*/
setRelhasindex ( relid , true , false , InvalidOid ) ;
CommandCounterIncrement ( ) ;
/*
/*
* However the following setRelhasindex ( ) is needed to
* If the relation has a secondary toast rel , reindex that too while we
* keep consistency with WAL .
* still hold the lock on the master table .
*/
*/
}
if ( toast_relid ! = InvalidOid )
setRelhasindex ( relid , true , false , InvalidOid ) ;
result | = reindex_relation ( toast_relid ) ;
}
}
SetReindexProcessing ( old ) ;
return reindexed ;
return result ;
}
}