mirror of
https://github.com/postgres/postgres.git
synced 2025-11-16 15:02:33 +03:00
Implement reindex command
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.121 2000/02/15 03:36:34 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.122 2000/02/18 09:28:40 inoue Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -713,7 +713,7 @@ AddNewRelationTuple(Relation pg_class_desc,
|
||||
if (temp_relname)
|
||||
create_temp_relation(temp_relname, tup);
|
||||
|
||||
if (!IsBootstrapProcessingMode())
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
/*
|
||||
* First, open the catalog indices and insert index tuples for the
|
||||
@@ -1263,8 +1263,7 @@ heap_truncate(char *relname)
|
||||
rel->rd_nblocks = 0;
|
||||
|
||||
/* If this relation has indexes, truncate the indexes too */
|
||||
if (rel->rd_rel->relhasindex)
|
||||
RelationTruncateIndexes(rel);
|
||||
RelationTruncateIndexes(rel);
|
||||
|
||||
/*
|
||||
* Close the relation, but keep exclusive lock on it until commit.
|
||||
@@ -1491,8 +1490,8 @@ heap_drop_with_catalog(const char *relname)
|
||||
* remove indexes if necessary
|
||||
* ----------------
|
||||
*/
|
||||
if (rel->rd_rel->relhasindex)
|
||||
RelationRemoveIndexes(rel);
|
||||
/* should ignore relhasindex */
|
||||
RelationRemoveIndexes(rel);
|
||||
|
||||
/* ----------------
|
||||
* remove rules if necessary
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.104 2000/01/26 05:56:10 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.105 2000/02/18 09:28:41 inoue Exp $
|
||||
*
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "utils/relcache.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/temprel.h"
|
||||
#include "utils/inval.h"
|
||||
|
||||
/*
|
||||
* macros used in guessing how many tuples are on a page.
|
||||
@@ -75,6 +76,17 @@ static void DefaultBuild(Relation heapRelation, Relation indexRelation,
|
||||
Datum *parameter, FuncIndexInfoPtr funcInfo, PredInfo *predInfo);
|
||||
static Oid IndexGetRelation(Oid indexId);
|
||||
|
||||
static bool reindexing = false;
|
||||
extern bool SetReindexProcessing(bool reindexmode)
|
||||
{
|
||||
bool old = reindexing;
|
||||
reindexing = reindexmode;
|
||||
return old;
|
||||
}
|
||||
extern bool IsReindexProcessing(void)
|
||||
{
|
||||
return reindexing;
|
||||
}
|
||||
/* ----------------------------------------------------------------
|
||||
* sysatts is a structure containing attribute tuple forms
|
||||
* for system attributes (numbered -1, -2, ...). This really
|
||||
@@ -484,7 +496,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
|
||||
* just before exiting.
|
||||
*/
|
||||
|
||||
if (!IsBootstrapProcessingMode())
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, tuple);
|
||||
@@ -569,7 +581,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
|
||||
(char *) (indexRelation->rd_att->attrs[0]));
|
||||
|
||||
hasind = false;
|
||||
if (!IsBootstrapProcessingMode() && pg_attribute->rd_rel->relhasindex)
|
||||
if (!IsIgnoringSystemIndexes() && pg_attribute->rd_rel->relhasindex)
|
||||
{
|
||||
hasind = true;
|
||||
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
|
||||
@@ -758,7 +770,7 @@ UpdateIndexRelation(Oid indexoid,
|
||||
* insert the index tuple into the pg_index
|
||||
* ----------------
|
||||
*/
|
||||
if (!IsBootstrapProcessingMode())
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
CatalogOpenIndices(Num_pg_index_indices, Name_pg_index_indices, idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_index_indices, pg_index, tuple);
|
||||
@@ -956,6 +968,7 @@ index_create(char *heapRelationName,
|
||||
* check parameters
|
||||
* ----------------
|
||||
*/
|
||||
SetReindexProcessing(false);
|
||||
if (numatts < 1)
|
||||
elog(ERROR, "must index at least one attribute");
|
||||
|
||||
@@ -1271,12 +1284,217 @@ FormIndexDatum(int numberOfAttributes,
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------
|
||||
* Lock class info for update
|
||||
* --------------------------------------------
|
||||
*/
|
||||
static
|
||||
bool LockClassinfoForUpdate(Oid relid, HeapTuple rtup, Buffer *buffer, bool confirmCommitted)
|
||||
{
|
||||
HeapTuple classTuple;
|
||||
Form_pg_class pgcform;
|
||||
bool test;
|
||||
Relation relationRelation;
|
||||
|
||||
classTuple = SearchSysCacheTuple(RELOID, PointerGetDatum(relid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(classTuple))
|
||||
return false;
|
||||
rtup->t_self = classTuple->t_self;
|
||||
pgcform = (Form_pg_class) GETSTRUCT(classTuple);
|
||||
relationRelation = heap_openr(RelationRelationName, RowShareLock);
|
||||
test = heap_mark4update(relationRelation, rtup, buffer);
|
||||
switch (test)
|
||||
{
|
||||
case HeapTupleSelfUpdated:
|
||||
case HeapTupleMayBeUpdated:
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "LockStatsForUpdate couldn't lock relid %u", relid);
|
||||
return false;
|
||||
}
|
||||
RelationInvalidateHeapTuple(relationRelation, rtup);
|
||||
if (confirmCommitted)
|
||||
{
|
||||
HeapTupleHeader th = rtup->t_data;
|
||||
if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
|
||||
elog(ERROR, "The tuple isn't committed");
|
||||
if (th->t_infomask & HEAP_XMAX_COMMITTED)
|
||||
if (!(th->t_infomask & HEAP_MARKED_FOR_UPDATE))
|
||||
elog(ERROR, "The tuple is already deleted");
|
||||
}
|
||||
heap_close(relationRelation, NoLock);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------
|
||||
* Indexes of the relation active ?
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
bool IndexesAreActive(Oid relid, bool confirmCommitted)
|
||||
{
|
||||
HeapTupleData tuple;
|
||||
Relation indexRelation;
|
||||
Buffer buffer;
|
||||
HeapScanDesc scan;
|
||||
ScanKeyData entry;
|
||||
bool isactive;
|
||||
|
||||
if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
|
||||
elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
|
||||
if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION)
|
||||
elog(ERROR, "relation %u isn't an relation", relid);
|
||||
isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
|
||||
ReleaseBuffer(buffer);
|
||||
if (isactive)
|
||||
return isactive;
|
||||
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
|
||||
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
|
||||
F_OIDEQ, ObjectIdGetDatum(relid));
|
||||
scan = heap_beginscan(indexRelation, false, SnapshotNow,
|
||||
1, &entry);
|
||||
if (!heap_getnext(scan, 0))
|
||||
isactive = true;
|
||||
heap_endscan(scan);
|
||||
heap_close(indexRelation, NoLock);
|
||||
return isactive;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* set relhasindex of pg_class in place
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
setRelhasindexInplace(Oid relid, bool hasindex, bool immediate)
|
||||
{
|
||||
Relation whichRel;
|
||||
Relation pg_class;
|
||||
HeapTuple tuple;
|
||||
Form_pg_class rd_rel;
|
||||
HeapScanDesc pg_class_scan = NULL;
|
||||
|
||||
/* ----------------
|
||||
* This routine handles updates for only the heap relation
|
||||
* hasindex. In order to guarantee that we're able to *see* the index
|
||||
* relation tuple, we bump the command counter id here.
|
||||
* ----------------
|
||||
*/
|
||||
CommandCounterIncrement();
|
||||
|
||||
/* ----------------
|
||||
* CommandCounterIncrement() flushes invalid cache entries, including
|
||||
* those for the heap and index relations for which we're updating
|
||||
* statistics. Now that the cache is flushed, it's safe to open the
|
||||
* relation again. We need the relation open in order to figure out
|
||||
* how many blocks it contains.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
whichRel = heap_open(relid, ShareLock);
|
||||
|
||||
if (!RelationIsValid(whichRel))
|
||||
elog(ERROR, "setRelhasindexInplace: cannot open relation id %u", relid);
|
||||
|
||||
/* ----------------
|
||||
* Find the RELATION relation tuple for the given relation.
|
||||
* ----------------
|
||||
*/
|
||||
pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
|
||||
if (!RelationIsValid(pg_class))
|
||||
elog(ERROR, "setRelhasindexInplace: could not open RELATION relation");
|
||||
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||
ObjectIdGetDatum(relid), 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScanKeyData key[1];
|
||||
|
||||
ScanKeyEntryInitialize(&key[0], 0,
|
||||
ObjectIdAttributeNumber,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(relid));
|
||||
|
||||
pg_class_scan = heap_beginscan(pg_class, 0, SnapshotNow, 1, key);
|
||||
tuple = heap_getnext(pg_class_scan, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
if (pg_class_scan)
|
||||
heap_endscan(pg_class_scan);
|
||||
heap_close(pg_class, RowExclusiveLock);
|
||||
elog(ERROR, "setRelhasindexInplace: cannot scan RELATION relation");
|
||||
}
|
||||
/*
|
||||
* Confirm that target tuple is locked by this transaction
|
||||
* in case of immedaite updation.
|
||||
*/
|
||||
if (immediate)
|
||||
{
|
||||
HeapTupleHeader th = tuple->t_data;
|
||||
if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
|
||||
elog(ERROR, "Immediate hasindex updation can be done only for committed tuples %x", th->t_infomask);
|
||||
if (th->t_infomask & HEAP_XMAX_INVALID)
|
||||
elog(ERROR, "Immediate hasindex updation can be done only for locked tuples %x", th->t_infomask);
|
||||
if (th->t_infomask & HEAP_XMAX_COMMITTED)
|
||||
elog(ERROR, "Immediate hasindex updation can be done only for locked tuples %x", th->t_infomask);
|
||||
if (!(th->t_infomask & HEAP_MARKED_FOR_UPDATE))
|
||||
elog(ERROR, "Immediate hasindex updation can be done only for locked tuples %x", th->t_infomask);
|
||||
if (!(TransactionIdIsCurrentTransactionId(th->t_xmax)))
|
||||
elog(ERROR, "The updating tuple is already locked by another backend");
|
||||
}
|
||||
|
||||
/*
|
||||
* We shouldn't have to do this, but we do... Modify the reldesc in
|
||||
* place with the new values so that the cache contains the latest
|
||||
* copy.
|
||||
*/
|
||||
whichRel->rd_rel->relhasindex = hasindex;
|
||||
|
||||
/* ----------------
|
||||
* Update hasindex in pg_class.
|
||||
* ----------------
|
||||
*/
|
||||
if (pg_class_scan)
|
||||
{
|
||||
|
||||
if (!IsBootstrapProcessingMode())
|
||||
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
||||
rd_rel->relhasindex = hasindex;
|
||||
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapTupleData htup;
|
||||
Buffer buffer;
|
||||
|
||||
htup.t_self = tuple->t_self;
|
||||
heap_fetch(pg_class, SnapshotNow, &htup, &buffer);
|
||||
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||
rd_rel = (Form_pg_class) GETSTRUCT(&htup);
|
||||
rd_rel->relhasindex = hasindex;
|
||||
WriteBuffer(buffer);
|
||||
}
|
||||
|
||||
if (!pg_class_scan)
|
||||
heap_freetuple(tuple);
|
||||
else
|
||||
heap_endscan(pg_class_scan);
|
||||
|
||||
heap_close(pg_class, NoLock);
|
||||
heap_close(whichRel, NoLock);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* UpdateStats
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
UpdateStats(Oid relid, long reltuples, bool inplace)
|
||||
{
|
||||
Relation whichRel;
|
||||
Relation pg_class;
|
||||
@@ -1289,7 +1507,8 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
Datum values[Natts_pg_class];
|
||||
char nulls[Natts_pg_class];
|
||||
char replace[Natts_pg_class];
|
||||
HeapScanDesc pg_class_scan = NULL;
|
||||
HeapScanDesc pg_class_scan = NULL;
|
||||
bool in_place_upd;
|
||||
|
||||
/* ----------------
|
||||
* This routine handles updates for both the heap and index relation
|
||||
@@ -1327,7 +1546,8 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
if (!RelationIsValid(pg_class))
|
||||
elog(ERROR, "UpdateStats: could not open RELATION relation");
|
||||
|
||||
if (!IsBootstrapProcessingMode())
|
||||
in_place_upd = (inplace || IsBootstrapProcessingMode());
|
||||
if (!in_place_upd)
|
||||
{
|
||||
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||
ObjectIdGetDatum(relid),
|
||||
@@ -1348,7 +1568,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
if (IsBootstrapProcessingMode())
|
||||
if (pg_class_scan)
|
||||
heap_endscan(pg_class_scan);
|
||||
heap_close(pg_class, RowExclusiveLock);
|
||||
elog(ERROR, "UpdateStats: cannot scan RELATION relation");
|
||||
@@ -1389,7 +1609,6 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
* place with the new values so that the cache contains the latest
|
||||
* copy.
|
||||
*/
|
||||
whichRel->rd_rel->relhasindex = hasindex;
|
||||
whichRel->rd_rel->relpages = relpages;
|
||||
whichRel->rd_rel->reltuples = reltuples;
|
||||
|
||||
@@ -1397,17 +1616,18 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
* Update statistics in pg_class.
|
||||
* ----------------
|
||||
*/
|
||||
if (IsBootstrapProcessingMode())
|
||||
if (in_place_upd)
|
||||
{
|
||||
|
||||
/*
|
||||
* At bootstrap time, we don't need to worry about concurrency or
|
||||
* visibility of changes, so we cheat.
|
||||
*/
|
||||
if (!IsBootstrapProcessingMode())
|
||||
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
|
||||
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
||||
rd_rel->relpages = relpages;
|
||||
rd_rel->reltuples = reltuples;
|
||||
rd_rel->relhasindex = hasindex;
|
||||
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
|
||||
}
|
||||
else
|
||||
@@ -1425,18 +1645,18 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
||||
values[Anum_pg_class_relpages - 1] = (Datum) relpages;
|
||||
replace[Anum_pg_class_reltuples - 1] = 'r';
|
||||
values[Anum_pg_class_reltuples - 1] = (Datum) reltuples;
|
||||
replace[Anum_pg_class_relhasindex - 1] = 'r';
|
||||
values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
|
||||
|
||||
newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
|
||||
heap_update(pg_class, &tuple->t_self, newtup, NULL);
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
|
||||
CatalogCloseIndices(Num_pg_class_indices, idescs);
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
|
||||
CatalogCloseIndices(Num_pg_class_indices, idescs);
|
||||
}
|
||||
heap_freetuple(newtup);
|
||||
}
|
||||
|
||||
if (!IsBootstrapProcessingMode())
|
||||
if (!pg_class_scan)
|
||||
heap_freetuple(tuple);
|
||||
else
|
||||
heap_endscan(pg_class_scan);
|
||||
@@ -1668,16 +1888,18 @@ DefaultBuild(Relation heapRelation,
|
||||
{
|
||||
Oid hrelid = RelationGetRelid(heapRelation);
|
||||
Oid irelid = RelationGetRelid(indexRelation);
|
||||
bool inplace = IsReindexProcessing();
|
||||
|
||||
heap_close(heapRelation, NoLock);
|
||||
index_close(indexRelation);
|
||||
UpdateStats(hrelid, reltuples, true);
|
||||
UpdateStats(irelid, indtuples, false);
|
||||
UpdateStats(hrelid, reltuples, inplace);
|
||||
UpdateStats(irelid, indtuples, inplace);
|
||||
if (oldPred != NULL)
|
||||
{
|
||||
if (indtuples == reltuples)
|
||||
predicate = NULL;
|
||||
UpdateIndexPredicate(irelid, oldPred, predicate);
|
||||
if (!inplace)
|
||||
UpdateIndexPredicate(irelid, oldPred, predicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1826,3 +2048,226 @@ IndexIsUniqueNoCache(Oid indexId)
|
||||
heap_close(pg_index, AccessShareLock);
|
||||
return isunique;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------
|
||||
* activate_index -- activate/deactivate the specified index.
|
||||
* Note that currelntly PostgreSQL doesn't hold the
|
||||
* status per index
|
||||
* ---------------------------------
|
||||
*/
|
||||
bool
|
||||
activate_index(Oid indexId, bool activate)
|
||||
{
|
||||
if (!activate) /* Currently does nothing */
|
||||
return true;
|
||||
return reindex_index(indexId, false);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* reindex_index - This routine is used to recreate an index
|
||||
* --------------------------------
|
||||
*/
|
||||
bool
|
||||
reindex_index(Oid indexId, bool force)
|
||||
{
|
||||
Relation iRel, indexRelation, heapRelation;
|
||||
ScanKeyData entry;
|
||||
HeapScanDesc scan;
|
||||
HeapTuple indexTuple, procTuple, classTuple;
|
||||
Form_pg_index index;
|
||||
Oid heapId, procId, accessMethodId;
|
||||
Node *oldPred = NULL;
|
||||
PredInfo *predInfo;
|
||||
List *cnfPred = NULL;
|
||||
AttrNumber *attributeNumberA;
|
||||
FuncIndexInfo fInfo, *funcInfo = NULL;
|
||||
int i, numberOfAttributes;
|
||||
char *predString;
|
||||
bool old;
|
||||
|
||||
old = SetReindexProcessing(true);
|
||||
/* Scan pg_index to find indexes on heapRelation */
|
||||
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
|
||||
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indexrelid, F_OIDEQ,
|
||||
ObjectIdGetDatum(indexId));
|
||||
scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
|
||||
indexTuple = heap_getnext(scan, 0);
|
||||
if (!HeapTupleIsValid(indexTuple))
|
||||
elog(ERROR, "reindex_index index %d tuple is invalid", indexId);
|
||||
|
||||
/*
|
||||
* For the index, fetch index attributes so we can apply index_build
|
||||
*/
|
||||
index = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||
heapId = index->indrelid;
|
||||
procId = index->indproc;
|
||||
|
||||
for (i = 0; i < INDEX_MAX_KEYS; i++)
|
||||
{
|
||||
if (index->indkey[i] == InvalidAttrNumber)
|
||||
break;
|
||||
}
|
||||
numberOfAttributes = i;
|
||||
|
||||
/* If a valid where predicate, compute predicate Node */
|
||||
if (VARSIZE(&index->indpred) != 0)
|
||||
{
|
||||
predString = fmgr(F_TEXTOUT, &index->indpred);
|
||||
oldPred = stringToNode(predString);
|
||||
pfree(predString);
|
||||
}
|
||||
predInfo = (PredInfo *) palloc(sizeof(PredInfo));
|
||||
predInfo->pred = (Node *) cnfPred;
|
||||
predInfo->oldPred = oldPred;
|
||||
|
||||
/* Assign Index keys to attributes array */
|
||||
attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * sizeof(AttrNumber));
|
||||
for (i = 0; i < numberOfAttributes; i++)
|
||||
attributeNumberA[i] = index->indkey[i];
|
||||
|
||||
/* If this is a procedural index, initialize our FuncIndexInfo */
|
||||
if (procId != InvalidOid)
|
||||
{
|
||||
funcInfo = &fInfo;
|
||||
FIsetnArgs(funcInfo, numberOfAttributes);
|
||||
procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(procTuple))
|
||||
elog(ERROR, "RelationTruncateIndexes: index procedure not found");
|
||||
namecpy(&(funcInfo->funcName),
|
||||
&(((Form_pg_proc) GETSTRUCT(procTuple))->proname));
|
||||
FIsetProcOid(funcInfo, procTuple->t_data->t_oid);
|
||||
}
|
||||
|
||||
/* Fetch the classTuple associated with this index */
|
||||
classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), 0, 0, 0);
|
||||
if (!HeapTupleIsValid(classTuple))
|
||||
elog(ERROR, "RelationTruncateIndexes: index access method not found");
|
||||
accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
|
||||
|
||||
/* Open our index relation */
|
||||
iRel = index_open(indexId);
|
||||
if (iRel == NULL)
|
||||
elog(ERROR, "reindex_index: can't open index relation");
|
||||
heapRelation = heap_open(heapId, ExclusiveLock);
|
||||
if (heapRelation == NULL)
|
||||
elog(ERROR, "reindex_index: can't open heap relation");
|
||||
|
||||
/* Obtain exclusive lock on it, just to be sure */
|
||||
LockRelation(iRel, AccessExclusiveLock);
|
||||
|
||||
/*
|
||||
* Release any buffers associated with this index. If they're dirty,
|
||||
* they're just dropped without bothering to flush to disk.
|
||||
*/
|
||||
ReleaseRelationBuffers(iRel);
|
||||
if (FlushRelationBuffers(iRel, (BlockNumber) 0, false) < 0)
|
||||
elog(ERROR, "reindex_index: unable to flush index from buffer pool");
|
||||
|
||||
/* Now truncate the actual data and set blocks to zero */
|
||||
smgrtruncate(DEFAULT_SMGR, iRel, 0);
|
||||
iRel->rd_nblocks = 0;
|
||||
|
||||
/* Initialize the index and rebuild */
|
||||
InitIndexStrategy(numberOfAttributes, iRel, accessMethodId);
|
||||
index_build(heapRelation, iRel, numberOfAttributes,
|
||||
attributeNumberA, 0, NULL, funcInfo, predInfo);
|
||||
|
||||
/*
|
||||
* index_build will close both the heap and index relations
|
||||
* (but not give up the locks we hold on them). That's fine
|
||||
* for the index, but we need to open the heap again. We need
|
||||
* no new lock, since this backend still has the exclusive lock
|
||||
* grabbed by heap_truncate.
|
||||
*/
|
||||
iRel = index_open(indexId);
|
||||
Assert(iRel != NULL);
|
||||
|
||||
/* Complete the scan and close pg_index */
|
||||
heap_endscan(scan);
|
||||
heap_close(indexRelation, AccessShareLock);
|
||||
SetReindexProcessing(old);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------
|
||||
* activate_indexes_of_a_table
|
||||
* activate/deactivate indexes of the specified table.
|
||||
* ----------------------------
|
||||
*/
|
||||
bool
|
||||
activate_indexes_of_a_table(Oid relid, bool activate)
|
||||
{
|
||||
if (IndexesAreActive(relid, true))
|
||||
{
|
||||
if (!activate)
|
||||
setRelhasindexInplace(relid, false, true);
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activate)
|
||||
reindex_relation(relid, 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;
|
||||
|
||||
old = SetReindexProcessing(true);
|
||||
if (IndexesAreActive(relid, true))
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
SetReindexProcessing(old);
|
||||
return false;
|
||||
}
|
||||
activate_indexes_of_a_table(relid, false);
|
||||
}
|
||||
|
||||
indexRelation = heap_openr(IndexRelationName, AccessShareLock);
|
||||
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid,
|
||||
F_OIDEQ, ObjectIdGetDatum(relid));
|
||||
scan = heap_beginscan(indexRelation, false, SnapshotNow,
|
||||
1, &entry);
|
||||
reindexed = false;
|
||||
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
|
||||
{
|
||||
Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple);
|
||||
if (activate_index(index->indexrelid, true))
|
||||
reindexed = true;
|
||||
else
|
||||
{
|
||||
reindexed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap_endscan(scan);
|
||||
heap_close(indexRelation, AccessShareLock);
|
||||
if (reindexed)
|
||||
{
|
||||
setRelhasindexInplace(relid, true, false);
|
||||
}
|
||||
SetReindexProcessing(old);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.58 2000/01/26 05:56:10 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.59 2000/02/18 09:28:41 inoue Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -92,6 +92,8 @@ CatalogOpenIndices(int nIndices, char **names, Relation *idescs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (IsIgnoringSystemIndexes())
|
||||
return;
|
||||
for (i = 0; i < nIndices; i++)
|
||||
idescs[i] = index_openr(names[i]);
|
||||
}
|
||||
@@ -104,6 +106,8 @@ CatalogCloseIndices(int nIndices, Relation *idescs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (IsIgnoringSystemIndexes())
|
||||
return;
|
||||
for (i = 0; i < nIndices; i++)
|
||||
index_close(idescs[i]);
|
||||
}
|
||||
@@ -131,6 +135,8 @@ CatalogIndexInsert(Relation *idescs,
|
||||
*finfoP;
|
||||
int i;
|
||||
|
||||
if (IsIgnoringSystemIndexes())
|
||||
return;
|
||||
heapDescriptor = RelationGetDescr(heapRelation);
|
||||
|
||||
for (i = 0; i < nIndices; i++)
|
||||
|
||||
Reference in New Issue
Block a user