/* * IndexSpoolEnd - Flush and delete spools. */ void IndexSpoolEnd(Spooler *self, bool reindex) { BTSpool **spools = self->spools; int i; RelationPtr indices = self->relinfo->ri_IndexRelationDescs; Assert(spools != NULL); Assert(self->relinfo != NULL); for (i = 0; i < self->relinfo->ri_NumIndices; i++) { if (spools[i] != NULL) { _bt_mergebuild(self, spools[i]); _bt_spooldestroy(spools[i]); } else if (reindex) { Oid indexOid = RelationGetRelid(indices[i]); /* Close index before reindex to pass CheckTableNotInUse. */ relation_close(indices[i], NoLock); indices[i] = NULL; reindex_index(indexOid, false); CommandCounterIncrement(); BULKLOAD_PROFILE(&prof_reindex); } else { /* We already done using index_insert. */ } } pfree(spools); }
/* * reindex_relation - This routine is used to recreate all indexes * of a relation (and its toast relation too, if any). * * Returns true if any indexes were rebuilt. */ bool reindex_relation(Oid relid) { Relation rel; Oid toast_relid; bool is_pg_class; bool result; List *indexIds, *doneIndexes, *indexId; /* * Ensure to hold an exclusive lock throughout the transaction. The * lock could perhaps be less intensive (in the non-overwrite case) * but for now it's AccessExclusiveLock for simplicity. */ rel = heap_open(relid, AccessExclusiveLock); toast_relid = rel->rd_rel->reltoastrelid; /* * Get the list of index OIDs for this relation. (We trust to the * relcache to get this with a sequential scan if ignoring system * indexes.) */ indexIds = RelationGetIndexList(rel); /* * reindex_index will attempt to update the pg_class rows for the * 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(). */ is_pg_class = (RelationGetRelid(rel) == RelOid_pg_class); doneIndexes = NIL; /* Reindex all the indexes. */ foreach(indexId, indexIds) { Oid indexOid = lfirsto(indexId); if (is_pg_class) RelationSetIndexList(rel, doneIndexes); reindex_index(indexOid); CommandCounterIncrement(); if (is_pg_class) doneIndexes = lappendo(doneIndexes, indexOid); }