*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.40 2000/01/26 05:55:57 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.41 2000/02/18 09:29:16 inoue Exp $
*
*-------------------------------------------------------------------------
*/
{
HeapTuple tuple;
HeapScanDesc scan = NULL;
+ bool cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized();
- if (!IsBootstrapProcessingMode())
+ if (cachesearch)
{
tuple = SearchSysCacheTuple(OPEROID,
ObjectIdGetDatum(operatorObjectId),
if (!HeapTupleIsValid(tuple))
{
- if (IsBootstrapProcessingMode())
+ if (!cachesearch)
heap_endscan(scan);
elog(ERROR, "OperatorObjectIdFillScanKeyEntry: unknown operator %u",
operatorObjectId);
fmgr_info(entry->sk_procedure, &entry->sk_func);
entry->sk_nargs = entry->sk_func.fn_nargs;
- if (IsBootstrapProcessingMode())
+ if (!cachesearch)
heap_endscan(scan);
if (!RegProcedureIsValid(entry->sk_procedure))
AttrNumber attributeNumber;
int attributeIndex;
Oid operatorClassObjectId[INDEX_MAX_KEYS];
+ bool cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized();
- if (!IsBootstrapProcessingMode())
+ if (cachesearch)
{
tuple = SearchSysCacheTuple(INDEXRELID,
ObjectIdGetDatum(indexObjectId),
operatorClassObjectId[attributeIndex] = iform->indclass[attributeIndex];
}
- if (IsBootstrapProcessingMode())
+ if (!cachesearch)
{
heap_endscan(scan);
heap_close(relation, AccessShareLock);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.52 2000/01/26 05:55:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.53 2000/02/18 09:29:54 inoue Exp $
*
*-------------------------------------------------------------------------
*/
{
Oid hrelid = RelationGetRelid(heap);
Oid irelid = RelationGetRelid(index);
+ bool inplace = IsReindexProcessing();
heap_close(heap, NoLock);
index_close(index);
+ /*
UpdateStats(hrelid, nhtups, true);
UpdateStats(irelid, nitups, false);
+ */
+ UpdateStats(hrelid, nhtups, inplace);
+ UpdateStats(irelid, nitups, inplace);
if (oldPred != NULL)
{
if (nitups == nhtups)
pred = NULL;
- UpdateIndexPredicate(irelid, oldPred, pred);
+ if (!inplace)
+ UpdateIndexPredicate(irelid, oldPred, pred);
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.60 2000/01/29 16:58:29 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.61 2000/02/18 09:30:20 inoue Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
#include "access/nbtree.h"
#include "catalog/heap.h"
+#include "catalog/index.h"
#include "commands/async.h"
#include "commands/sequence.h"
#include "commands/vacuum.h"
*/
s->state = TRANS_START;
+ SetReindexProcessing(false);
/* ----------------
* generate a new transaction id
* ----------------
AtAbort_Notify();
CloseSequences();
AtEOXact_portals();
- if (VacuumRunning)
- vc_abort();
+ if (CommonSpecialPortalIsOpen())
+ CommonSpecialPortalClose();
RecordTransactionAbort();
RelationPurgeLocalRelation(false);
DropNoNameRels();
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.79 2000/01/26 05:56:07 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.80 2000/02/18 09:28:39 inoue Exp $
*
*-------------------------------------------------------------------------
*/
dbName = argv[optind];
SetProcessingMode(BootstrapProcessing);
+ IgnoreSystemIndexes(true);
if (!DataDir)
{
*
*
* 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
if (temp_relname)
create_temp_relation(temp_relname, tup);
- if (!IsBootstrapProcessingMode())
+ if (!IsIgnoringSystemIndexes())
{
/*
* First, open the catalog indices and insert index tuples for the
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.
* remove indexes if necessary
* ----------------
*/
- if (rel->rd_rel->relhasindex)
- RelationRemoveIndexes(rel);
+ /* should ignore relhasindex */
+ RelationRemoveIndexes(rel);
/* ----------------
* remove rules if necessary
*
*
* 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
#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.
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
* 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);
(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);
* 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);
* check parameters
* ----------------
*/
+ SetReindexProcessing(false);
if (numatts < 1)
elog(ERROR, "must index at least one attribute");
}
+/* --------------------------------------------
+ * 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;
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
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),
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");
* 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;
* 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
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);
{
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);
}
}
}
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;
+}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
int i;
+ if (IsIgnoringSystemIndexes())
+ return;
for (i = 0; i < nIndices; i++)
idescs[i] = index_openr(names[i]);
}
{
int i;
+ if (IsIgnoringSystemIndexes())
+ return;
for (i = 0; i < nIndices; i++)
index_close(idescs[i]);
}
*finfoP;
int i;
+ if (IsIgnoringSystemIndexes())
+ return;
heapDescriptor = RelationGetDescr(heapRelation);
for (i = 0; i < nIndices; i++)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.20 2000/01/26 05:56:13 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.21 2000/02/18 09:29:37 inoue Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/genam.h"
#include "access/heapam.h"
+#include "catalog/catname.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "catalog/pg_database.h"
+#include "catalog/pg_shadow.h"
#include "commands/defrem.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
+#include "miscadmin.h" /* ReindexDatabase() */
+#include "utils/portal.h" /* ReindexDatabase() */
+#include "catalog/catalog.h" /* ReindexDatabase() */
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL)
CheckPredicate(cnfPred, rangetable, relationId);
}
+ if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
+ elog(ERROR, "existent indexes are inactive. REINDEX first");
if (IsFuncIndex(attributeList))
{
IndexElem *funcIndex = lfirst(attributeList);
classObjectId, parameterCount, parameterA, (Node *) cnfPred,
lossy, unique, primary);
}
+ setRelhasindexInplace(relationId, true, false);
}
index_drop(tuple->t_data->t_oid);
}
+
+/*
+ * Reindex
+ * Recreate an index.
+ *
+ * Exceptions:
+ * "ERROR" if index nonexistent.
+ * ...
+ */
+void
+ReindexIndex(const char *name, bool force /* currently unused */)
+{
+ HeapTuple tuple;
+
+ tuple = SearchSysCacheTuple(RELNAME,
+ PointerGetDatum(name),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "index \"%s\" nonexistent", name);
+
+ if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
+ {
+ elog(ERROR, "relation \"%s\" is of type \"%c\"",
+ name,
+ ((Form_pg_class) GETSTRUCT(tuple))->relkind);
+ }
+
+ reindex_index(tuple->t_data->t_oid, force);
+}
+
+/*
+ * ReindexTable
+ * Recreate indexes of a table.
+ *
+ * Exceptions:
+ * "ERROR" if table nonexistent.
+ * ...
+ */
+void
+ReindexTable(const char *name, bool force)
+{
+ HeapTuple tuple;
+
+ tuple = SearchSysCacheTuple(RELNAME,
+ PointerGetDatum(name),
+ 0, 0, 0);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "table \"%s\" nonexistent", name);
+
+ if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION)
+ {
+ elog(ERROR, "relation \"%s\" is of type \"%c\"",
+ name,
+ ((Form_pg_class) GETSTRUCT(tuple))->relkind);
+ }
+
+ reindex_relation(tuple->t_data->t_oid, force);
+}
+
+/*
+ * ReindexDatabase
+ * Recreate indexes of a database.
+ *
+ * Exceptions:
+ * "ERROR" if table nonexistent.
+ * ...
+ */
+extern Oid MyDatabaseId;
+void
+ReindexDatabase(const char *dbname, bool force, bool all)
+{
+ Relation relation, relationRelation;
+ HeapTuple usertuple, dbtuple, tuple;
+ HeapScanDesc scan;
+ int4 user_id, db_owner;
+ bool superuser;
+ Oid db_id;
+ char *username;
+ ScanKeyData scankey;
+ PortalVariableMemory pmem;
+ MemoryContext old;
+ int relcnt, relalc, i, oncealc = 200;
+ Oid *relids = (Oid *) NULL;
+
+ AssertArg(dbname);
+
+ username = GetPgUserName();
+ usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(usertuple))
+ elog(ERROR, "Current user '%s' is invalid.", username);
+ user_id = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid;
+ superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
+
+ relation = heap_openr(DatabaseRelationName, AccessShareLock);
+ ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
+ F_NAMEEQ, NameGetDatum(dbname));
+ scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
+ dbtuple = heap_getnext(scan, 0);
+ if (!HeapTupleIsValid(dbtuple))
+ elog(ERROR, "Database '%s' doesn't exist", dbname);
+ db_id = dbtuple->t_data->t_oid;
+ db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+ heap_endscan(scan);
+ if (user_id != db_owner && !superuser)
+ elog(ERROR, "REINDEX DATABASE: Permission denied.");
+
+ if (db_id != MyDatabaseId)
+ elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
+
+ heap_close(relation, NoLock);
+ /** reindex_database(db_id, force, !all); **/
+
+ CommonSpecialPortalOpen();
+ pmem = CommonSpecialPortalGetMemory();
+ relationRelation = heap_openr(RelationRelationName, AccessShareLock);
+ scan = heap_beginscan(relationRelation, false, SnapshotNow, 0, NULL);
+ relcnt = relalc = 0;
+ while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+ {
+ if (!all)
+ {
+ if (!IsSystemRelationName(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname)))
+ continue;
+ if (((Form_pg_class) GETSTRUCT(tuple))->relhasrules)
+ continue;
+ }
+ if (((Form_pg_class) GETSTRUCT(tuple))->relkind == RELKIND_RELATION)
+ {
+ old = MemoryContextSwitchTo((MemoryContext) pmem);
+ if (relcnt == 0)
+ {
+ relalc = oncealc;
+ relids = palloc(sizeof(Oid) * relalc);
+ }
+ else if (relcnt >= relalc)
+ {
+ relalc *= 2;
+ relids = repalloc(relids, sizeof(Oid) * relalc);
+ }
+ MemoryContextSwitchTo(old);
+ relids[relcnt] = tuple->t_data->t_oid;
+ relcnt++;
+ }
+ }
+ heap_endscan(scan);
+ heap_close(relationRelation, AccessShareLock);
+
+ CommitTransactionCommand();
+ for (i = 0; i < relcnt; i++)
+ {
+ StartTransactionCommand();
+ reindex_relation(relids[i], force);
+ CommitTransactionCommand();
+ }
+ CommonSpecialPortalClose();
+ StartTransactionCommand();
+}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.60 2000/02/13 13:21:10 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.61 2000/02/18 09:29:37 inoue Exp $
*
*-------------------------------------------------------------------------
*/
Trigger *build;
Relation tgrel;
Form_pg_trigger pg_trigger;
- Relation irel;
+ Relation irel = (Relation) NULL;
ScanKeyData skey;
HeapTupleData tuple;
- IndexScanDesc sd;
+ IndexScanDesc sd = (IndexScanDesc) NULL;
+ HeapScanDesc tgscan = (HeapScanDesc) NULL;
+ HeapTuple htup;
RetrieveIndexResult indexRes;
Buffer buffer;
struct varlena *val;
bool isnull;
int found;
+ bool hasindex;
MemSet(trigdesc, 0, sizeof(TriggerDesc));
ObjectIdGetDatum(RelationGetRelid(relation)));
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
- irel = index_openr(TriggerRelidIndex);
- sd = index_beginscan(irel, false, 1, &skey);
+ hasindex = (tgrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
+ if (hasindex)
+ {
+ irel = index_openr(TriggerRelidIndex);
+ sd = index_beginscan(irel, false, 1, &skey);
+ }
+ else
+ tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &skey);
for (found = 0;;)
{
- indexRes = index_getnext(sd, ForwardScanDirection);
- if (!indexRes)
- break;
+ if (hasindex)
+ {
+ indexRes = index_getnext(sd, ForwardScanDirection);
+ if (!indexRes)
+ break;
- tuple.t_self = indexRes->heap_iptr;
- heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
- pfree(indexRes);
- if (!tuple.t_data)
- continue;
+ tuple.t_self = indexRes->heap_iptr;
+ heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
+ pfree(indexRes);
+ if (!tuple.t_data)
+ continue;
+ htup = &tuple;
+ }
+ else
+ {
+ htup = heap_getnext(tgscan, 0);
+ if (!HeapTupleIsValid(htup))
+ break;
+ }
if (found == ntrigs)
elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %s",
RelationGetRelationName(relation));
- pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);
+ pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
if (triggers == NULL)
triggers = (Trigger *) palloc(sizeof(Trigger));
triggers = (Trigger *) repalloc(triggers, (found + 1) * sizeof(Trigger));
build = &(triggers[found]);
- build->tgoid = tuple.t_data->t_oid;
+ build->tgoid = htup->t_data->t_oid;
build->tgname = nameout(&pg_trigger->tgname);
build->tgfoid = pg_trigger->tgfoid;
build->tgfunc.fn_addr = NULL;
build->tginitdeferred = pg_trigger->tginitdeferred;
build->tgnargs = pg_trigger->tgnargs;
memcpy(build->tgattr, &(pg_trigger->tgattr), FUNC_MAX_ARGS * sizeof(int16));
- val = (struct varlena *) fastgetattr(&tuple,
+ val = (struct varlena *) fastgetattr(htup,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
if (isnull)
char *p;
int i;
- val = (struct varlena *) fastgetattr(&tuple,
+ val = (struct varlena *) fastgetattr(htup,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
if (isnull)
build->tgargs = NULL;
found++;
- ReleaseBuffer(buffer);
+ if (hasindex)
+ ReleaseBuffer(buffer);
}
if (found < ntrigs)
ntrigs - found,
RelationGetRelationName(relation));
- index_endscan(sd);
- index_close(irel);
+ if (hasindex)
+ {
+ index_endscan(sd);
+ index_close(irel);
+ }
+ else
+ heap_endscan(tgscan);
heap_close(tgrel, AccessShareLock);
/* Build trigdesc */
DeferredTriggerSetState(ConstraintsSetStmt *stmt)
{
Relation tgrel;
- Relation irel;
+ Relation irel = (Relation) NULL;
List *l;
List *ls;
List *lnext;
MemoryContext oldcxt;
bool found;
DeferredTriggerStatus state;
+ bool hasindex;
/* ----------
* Handle SET CONSTRAINTS ALL ...
* ----------
*/
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
- irel = index_openr(TriggerConstrNameIndex);
+ hasindex = (tgrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
+ if (hasindex)
+ irel = index_openr(TriggerConstrNameIndex);
foreach (l, stmt->constraints)
{
ScanKeyData skey;
HeapTupleData tuple;
- IndexScanDesc sd;
+ IndexScanDesc sd = (IndexScanDesc) NULL;
+ HeapScanDesc tgscan = (HeapScanDesc) NULL;
+ HeapTuple htup;
RetrieveIndexResult indexRes;
Buffer buffer;
Form_pg_trigger pg_trigger;
(RegProcedure) F_NAMEEQ,
PointerGetDatum((char *)lfirst(l)));
- sd = index_beginscan(irel, false, 1, &skey);
+ if (hasindex)
+ sd = index_beginscan(irel, false, 1, &skey);
+ else
+ tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &skey);
/* ----------
* ... and search for the constraint trigger row
found = false;
for (;;)
{
- indexRes = index_getnext(sd, ForwardScanDirection);
- if (!indexRes)
- break;
+ if (hasindex)
+ {
+ indexRes = index_getnext(sd, ForwardScanDirection);
+ if (!indexRes)
+ break;
- tuple.t_self = indexRes->heap_iptr;
- heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
- pfree(indexRes);
- if (!tuple.t_data)
+ tuple.t_self = indexRes->heap_iptr;
+ heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
+ pfree(indexRes);
+ if (!tuple.t_data)
+ {
+ continue;
+ }
+ htup = &tuple;
+ }
+ else
{
- ReleaseBuffer(buffer);
- continue;
+ htup = heap_getnext(tgscan, 0);
+ if (!HeapTupleIsValid(htup))
+ break;
}
/* ----------
* If we found some, check that they fit the deferrability
* ----------
*/
- pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);
+ pg_trigger = (Form_pg_trigger) GETSTRUCT(htup);
if (stmt->deferred & !pg_trigger->tgdeferrable)
elog(ERROR, "Constraint '%s' is not deferrable",
(char *)lfirst(l));
- constr_oid = tuple.t_data->t_oid;
+ constr_oid = htup->t_data->t_oid;
loid = lappend(loid, (Node *)constr_oid);
found = true;
- ReleaseBuffer(buffer);
+ if (hasindex)
+ ReleaseBuffer(buffer);
}
/* ----------
if (!found)
elog(ERROR, "Constraint '%s' does not exist", (char *)lfirst(l));
- index_endscan(sd);
+ if (hasindex)
+ index_endscan(sd);
+ else
+ heap_endscan(tgscan);
}
- index_close(irel);
+ if (hasindex)
+ index_close(irel);
heap_close(tgrel, AccessShareLock);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.138 2000/01/26 05:56:13 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.139 2000/02/18 09:29:37 inoue Exp $
*
*-------------------------------------------------------------------------
*/
#endif
-bool VacuumRunning = false;
+bool CommonSpecialPortalInUse = false;
static Portal vc_portal;
static char *vc_show_rusage(struct rusage * ru0);
+/*
+ * This routines handle a special cross-transaction portal.
+ * However it is automatically closed in case of abort.
+ */
+void CommonSpecialPortalOpen(void)
+{
+ char *pname;
+
+ /*
+ * Create a portal for safe memory across transactions. We need to
+ * palloc the name space for it because our hash function expects the
+ * name to be on a longword boundary. CreatePortal copies the name to
+ * safe storage for us.
+ */
+ pname = pstrdup(VACPNAME);
+ vc_portal = CreatePortal(pname);
+ pfree(pname);
+
+ /*
+ * Set flag to indicate that vc_portal must be removed after an error.
+ * This global variable is checked in the transaction manager on xact
+ * abort, and the routine CommonSpecialPortalClose() is called if
+ * necessary.
+ */
+ CommonSpecialPortalInUse = true;
+}
+
+void CommonSpecialPortalClose(void)
+{
+ /* Clear flag first, to avoid recursion if PortalDrop elog's */
+ CommonSpecialPortalInUse = false;
+
+ /*
+ * Release our portal for cross-transaction memory.
+ */
+ PortalDrop(&vc_portal);
+}
+
+PortalVariableMemory CommonSpecialPortalGetMemory(void)
+{
+ return PortalGetVariableMemory(vc_portal);
+}
+bool CommonSpecialPortalIsOpen(void)
+{
+ return CommonSpecialPortalInUse;
+}
+
void
vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
{
strcpy(NameStr(VacRel), vacrel);
/* must also copy the column list, if any, to safe storage */
- pmem = PortalGetVariableMemory(vc_portal);
+ pmem = CommonSpecialPortalGetMemory();
old = MemoryContextSwitchTo((MemoryContext) pmem);
foreach(le, va_spec)
{
static void
vc_init()
{
- char *pname;
-
- /*
- * Create a portal for safe memory across transactions. We need to
- * palloc the name space for it because our hash function expects the
- * name to be on a longword boundary. CreatePortal copies the name to
- * safe storage for us.
- */
- pname = pstrdup(VACPNAME);
- vc_portal = CreatePortal(pname);
- pfree(pname);
-
- /*
- * Set flag to indicate that vc_portal must be removed after an error.
- * This global variable is checked in the transaction manager on xact
- * abort, and the routine vc_abort() is called if necessary.
- */
- VacuumRunning = true;
+ CommonSpecialPortalOpen();
/* matches the StartTransaction in PostgresMain() */
CommitTransactionCommand();
*/
unlink(RELCACHE_INIT_FILENAME);
- /*
- * Release our portal for cross-transaction memory.
- */
- PortalDrop(&vc_portal);
-
- /* okay, we're done */
- VacuumRunning = false;
+ CommonSpecialPortalClose();
/* matches the CommitTransaction in PostgresMain() */
StartTransactionCommand();
}
-void
-vc_abort()
-{
- /* Clear flag first, to avoid recursion if PortalDrop elog's */
- VacuumRunning = false;
-
- /*
- * Release our portal for cross-transaction memory.
- */
- PortalDrop(&vc_portal);
-}
-
/*
* vc_vacuum() -- vacuum the database.
*
F_CHAREQ, CharGetDatum('r'));
}
- portalmem = PortalGetVariableMemory(vc_portal);
+ portalmem = CommonSpecialPortalGetMemory();
vrl = cur = (VRelList) NULL;
rel = heap_openr(RelationRelationName, AccessShareLock);
int32 nindices,
i;
VRelStats *vacrelstats;
+ bool reindex = false;
StartTransactionCommand();
GetXmaxRecent(&XmaxRecent);
/* scan it */
+ reindex = false;
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
vc_scanheap(vacrelstats, onerel, &vacuum_pages, &fraged_pages);
+ if (IsIgnoringSystemIndexes() && IsSystemRelationName(RelationGetRelationName(onerel)))
+ reindex = true;
/* Now open indices */
+ nindices = 0;
Irel = (Relation *) NULL;
vc_getindices(vacrelstats->relid, &nindices, &Irel);
-
+ if (!Irel)
+ reindex = false;
+ else if (!RelationGetForm(onerel)->relhasindex)
+ reindex = true;
if (nindices > 0)
vacrelstats->hasindex = true;
else
vacrelstats->hasindex = false;
+ if (reindex)
+ {
+ for (i = 0; i < nindices; i++)
+ index_close(Irel[i]);
+ Irel = (Relation *) NULL;
+ activate_indexes_of_a_table(relid, false);
+ }
/* Clean/scan index relation(s) */
if (Irel != (Relation *) NULL)
* vacuum_pages list */
vc_vacheap(vacrelstats, onerel, &vacuum_pages);
}
+ if (reindex)
+ activate_indexes_of_a_table(relid, true);
/* ok - free vacuum_pages list of reaped pages */
if (vacuum_pages.vpl_num_pages > 0)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.53 2000/01/26 05:56:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.54 2000/02/18 09:29:57 inoue Exp $
*
*-------------------------------------------------------------------------
*/
#include "catalog/catname.h"
#include "catalog/index.h"
#include "catalog/pg_index.h"
+#include "catalog/catalog.h"
#include "executor/execdebug.h"
#include "executor/executor.h"
+#include "miscadmin.h"
static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
PredInfo *predicate;
int i;
+ resultRelationInfo->ri_NumIndices = 0;
+ if (!RelationGetForm(resultRelationInfo->ri_RelationDesc)->relhasindex)
+ return;
+ if (IsIgnoringSystemIndexes() &&
+ IsSystemRelationName(RelationGetRelationName(resultRelationInfo->ri_RelationDesc)))
+ return;
/* ----------------
* open pg_index
* ----------------
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.46 2000/02/05 23:19:44 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.47 2000/02/18 09:29:57 inoue Exp $
*
*-------------------------------------------------------------------------
*/
¤tRelation, /* return: rel desc */
(Pointer *) ¤tScanDesc); /* return: scan desc */
+if (!RelationGetForm(currentRelation)->relhasindex)
+{
+ elog(ERROR, "indexes of the relation %u was inactivated", reloid);
+}
scanstate->css_currentRelation = currentRelation;
scanstate->css_currentScanDesc = currentScanDesc;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.48 2000/02/17 03:39:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.49 2000/02/18 09:30:09 inoue Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/plancat.h"
#include "parser/parsetree.h"
#include "utils/syscache.h"
+#include "catalog/catalog.h"
+#include "miscadmin.h"
/*
relationObjectId);
relation = (Form_pg_class) GETSTRUCT(relationTuple);
- *hasindex = (relation->relhasindex) ? true : false;
+ if (IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(relation->relname)))
+ *hasindex = false;
+ else
+ *hasindex = (relation->relhasindex) ? true : false;
*pages = relation->relpages;
*tuples = relation->reltuples;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.143 2000/02/16 17:24:36 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.144 2000/02/18 09:29:40 inoue Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
CreatePLangStmt, DropPLangStmt,
IndexStmt, ListenStmt, UnlistenStmt, LockStmt, OptimizableStmt,
- ProcedureStmt, RemoveAggrStmt, RemoveOperStmt,
+ ProcedureStmt, ReindexStmt, RemoveAggrStmt, RemoveOperStmt,
RemoveFuncStmt, RemoveStmt,
RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
CreatedbStmt, DropdbStmt, VacuumStmt, CursorStmt, SubSelect,
%type <ival> createdb_opt_encoding
%type <ival> opt_lock, lock_type
-%type <boolean> opt_lmode
+%type <boolean> opt_lmode, opt_force
%type <ival> user_createdb_clause, user_createuser_clause
%type <str> user_passwd_clause
opt_with_copy, index_opt_unique, opt_verbose, opt_analyze
%type <boolean> opt_cursor
-%type <ival> copy_dirn, def_type, direction, remove_type,
+%type <ival> copy_dirn, def_type, direction, reindex_type, remove_type,
opt_column, event, comment_type, comment_cl,
comment_ag, comment_fn, comment_op, comment_tg
CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
DATABASE, DELIMITERS, DO,
EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
- FORWARD, FUNCTION, HANDLER,
+ FORCE, FORWARD, FUNCTION, HANDLER,
INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
LANCOMPILER, LIMIT, LISTEN, LOAD, LOCATION, LOCK_P,
MAXVALUE, MINVALUE, MODE, MOVE,
NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
- RENAME, RESET, RETURNS, ROW, RULE,
+ REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID,
TRUNCATE, TRUSTED,
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
| UnlistenStmt
| LockStmt
| ProcedureStmt
+ | ReindexStmt
| RemoveAggrStmt
| RemoveOperStmt
| RemoveFuncStmt
;
+/*****************************************************************************
+ *
+ * QUERY:
+ *
+ * REINDEX type <typename> [FORCE] [ALL]
+ *
+ *****************************************************************************/
+
+ReindexStmt: REINDEX reindex_type name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ if (IsTransactionBlock())
+ elog(ERROR,"REINDEX command could only be used outside begin/end transaction blocks");
+ n->reindexType = $2;
+ n->name = $3;
+ n->force = $4;
+ $$ = (Node *)n;
+ }
+ ;
+
+reindex_type: INDEX { $$ = INDEX; }
+ | TABLE { $$ = TABLE; }
+ | DATABASE { $$ = DATABASE; }
+ ;
+opt_force: FORCE { $$ = TRUE; }
+ | /* EMPTY */ { $$ = FALSE; }
+ ;
+
+
/*****************************************************************************
*
* QUERY:
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.66 2000/02/15 03:26:38 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.67 2000/02/18 09:29:40 inoue Exp $
*
*-------------------------------------------------------------------------
*/
{"fetch", FETCH},
{"float", FLOAT},
{"for", FOR},
+ {"force", FORCE},
{"foreign", FOREIGN},
{"forward", FORWARD},
{"from", FROM},
{"public", PUBLIC},
{"read", READ},
{"references", REFERENCES},
+ {"reindex", REINDEX},
{"relative", RELATIVE},
{"rename", RENAME},
{"reset", RESET},
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.135 2000/01/26 05:56:48 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.136 2000/02/18 09:28:44 inoue Exp $
*
* NOTES
*
DataDir = getenv("PGDATA"); /* default value */
opterr = 0;
+ IgnoreSystemIndexes(false);
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:ilm:MN:no:p:Ss")) != EOF)
{
switch (opt)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.141 2000/01/26 05:57:07 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.142 2000/02/18 09:29:27 inoue Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
optind = 1; /* reset after postmaster's usage */
while ((flag = getopt(argc, argv,
- "A:B:CD:d:EeFf:iK:LNOo:p:QS:sT:t:v:W:x:"))
+ "A:B:CD:d:EeFf:iK:LNOPo:p:QS:sT:t:v:W:x:"))
!= EOF)
switch (flag)
{
allowSystemTableMods = true;
break;
+ case 'P':
+ /* --------------------
+ * ignore system indexes
+ * --------------------
+ */
+ if (secure) /* XXX safe to allow from client??? */
+ IgnoreSystemIndexes(true);
+ break;
+
case 'o':
/* ----------------
* o - send output (stdout and stderr) to the given file
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.141 $ $Date: 2000/01/26 05:57:07 $\n");
+ puts("$Revision: 1.142 $ $Date: 2000/02/18 09:29:27 $\n");
}
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.82 2000/01/29 16:58:38 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.83 2000/02/18 09:29:31 inoue Exp $
*
*-------------------------------------------------------------------------
*/
DropGroup((DropGroupStmt *) parsetree);
break;
+ case T_ReindexStmt:
+ {
+ ReindexStmt *stmt = (ReindexStmt *) parsetree;
+
+ PS_SET_STATUS(commandTag = "REINDEX");
+ CHECK_IF_ABORTED();
+
+ switch (stmt->reindexType)
+ {
+ case INDEX:
+ relname = stmt->name;
+ if (IsSystemRelationName(relname))
+ {
+ if (!allowSystemTableMods && IsSystemRelationName(relname))
+ elog(ERROR, "class \"%s\" is a system catalog index",
+ relname);
+ if (!IsIgnoringSystemIndexes())
+ elog(ERROR, "class \"%s\" is a system catalog index",
+ relname);
+ }
+#ifndef NO_SECURITY
+ if (!pg_ownercheck(userName, relname, RELNAME))
+ elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+#endif
+ ReindexIndex(relname, stmt->force);
+ break;
+ case TABLE:
+ relname = stmt->name;
+ if (IsSystemRelationName(relname))
+ {
+ if (!allowSystemTableMods && IsSystemRelationName(relname))
+ elog(ERROR, "class \"%s\" is a system catalog index",
+ relname);
+ if (!IsIgnoringSystemIndexes())
+ elog(ERROR, "class \"%s\" is a system catalog index",
+ relname);
+ }
+#ifndef NO_SECURITY
+ if (!pg_ownercheck(userName, relname, RELNAME))
+ elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+#endif
+ ReindexTable(relname, stmt->force);
+ break;
+ case DATABASE:
+ relname = stmt->name;
+ if (!allowSystemTableMods)
+ elog(ERROR, "-O option is needed");
+ if (!IsIgnoringSystemIndexes())
+ elog(ERROR, "-P option is needed");
+ ReindexDatabase(relname, stmt->force, false);
+ break;
+ }
+ break;
+ }
+ break;
/*
* ******************************** default ********************************
*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.51 2000/01/26 05:57:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.52 2000/02/18 09:28:48 inoue Exp $
*
*-------------------------------------------------------------------------
*/
if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
return InvalidOid;
- if (!IsBootstrapProcessingMode())
+ if (!IsIgnoringSystemIndexes())
{
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.60 2000/02/04 03:16:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.61 2000/02/18 09:28:53 inoue Exp $
*
*-------------------------------------------------------------------------
*/
*/
if (cache->cc_indname != NULL && cache->indexId == InvalidOid)
{
- if (RelationGetForm(relation)->relhasindex)
+ if (!IsIgnoringSystemIndexes() && RelationGetForm(relation)->relhasindex)
{
/*
if (!OidIsValid(indexSelfOid))
{
+ ScanKeyData key;
+ HeapScanDesc sd;
/* Find oid of pg_index_indexrelid_index */
rel = heap_openr(RelationRelationName, AccessShareLock);
- ntp = ClassNameIndexScan(rel, IndexRelidIndex);
+ ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname,
+ F_NAMEEQ, PointerGetDatum(IndexRelidIndex));
+ sd = heap_beginscan(rel, false, SnapshotNow, 1, &key);
+ ntp = heap_getnext(sd, 0);
if (!HeapTupleIsValid(ntp))
elog(ERROR, "SearchSelfReferences: %s not found in %s",
IndexRelidIndex, RelationRelationName);
indexSelfOid = ntp->t_data->t_oid;
- heap_freetuple(ntp);
+ heap_endscan(sd);
heap_close(rel, AccessShareLock);
}
/* Looking for something other than pg_index_indexrelid_index? */
CACHE1_elog(DEBUG, "SearchSysCache: performing scan");
if ((RelationGetForm(relation))->relhasindex
- && !IsBootstrapProcessingMode())
+ && !IsIgnoringSystemIndexes())
{
/* ----------
* Switch back to old memory context so memory not freed
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.89 2000/01/31 04:35:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.90 2000/02/18 09:28:55 inoue Exp $
*
*-------------------------------------------------------------------------
*/
static void AttrDefaultFetch(Relation relation);
static void RelCheckFetch(Relation relation);
+static bool criticalRelcacheBuild = false;
/* ----------------------------------------------------------------
* RelationIdGetRelation() and RelationNameGetRelation()
* support functions
* can, and do.
*/
- if (IsBootstrapProcessingMode())
+ if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
return scan_pg_rel_seq(buildinfo);
else
return scan_pg_rel_ind(buildinfo);
* can, and do.
*/
- if (IsBootstrapProcessingMode())
+ if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
build_tupdesc_seq(buildinfo, relation, natts);
else
build_tupdesc_ind(buildinfo, relation, natts);
}
+static void
+SetConstrOfRelation(Relation relation, TupleConstr *constr, int ndef, AttrDefault *attrdef)
+{
+ if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
+ {
+ relation->rd_att->constr = constr;
+
+ if (ndef > 0) /* DEFAULTs */
+ {
+ if (ndef < relation->rd_rel->relnatts)
+ constr->defval = (AttrDefault *)
+ repalloc(attrdef, ndef * sizeof(AttrDefault));
+ else
+ constr->defval = attrdef;
+ constr->num_defval = ndef;
+ AttrDefaultFetch(relation);
+ }
+ else
+ constr->num_defval = 0;
+
+ if (relation->rd_rel->relchecks > 0) /* CHECKs */
+ {
+ constr->num_check = relation->rd_rel->relchecks;
+ constr->check = (ConstrCheck *) palloc(constr->num_check *
+ sizeof(ConstrCheck));
+ MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck));
+ RelCheckFetch(relation);
+ }
+ else
+ constr->num_check = 0;
+ }
+ else
+ {
+ pfree(constr);
+ relation->rd_att->constr = NULL;
+ }
+}
+
static void
build_tupdesc_seq(RelationBuildDescInfo buildinfo,
Relation relation,
Form_pg_attribute attp;
ScanKeyData key;
int need;
+ TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
+ AttrDefault *attrdef = NULL;
+ int ndef = 0;
+ constr->has_not_null = false;
/* ----------------
* form a scan key
* ----------------
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
need--;
+ /* Update if this attribute have a constraint */
+ if (attp->attnotnull)
+ constr->has_not_null = true;
+
+ if (attp->atthasdef)
+ {
+ if (attrdef == NULL)
+ {
+ attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts *
+ sizeof(AttrDefault));
+ MemSet(attrdef, 0,
+ relation->rd_rel->relnatts * sizeof(AttrDefault));
+ }
+ attrdef[ndef].adnum = attp->attnum;
+ attrdef[ndef].adbin = NULL;
+ ndef++;
+ }
}
pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0);
}
*/
heap_endscan(pg_attribute_scan);
heap_close(pg_attribute_desc, AccessShareLock);
+
+ SetConstrOfRelation(relation, constr, ndef, attrdef);
}
static void
heap_close(attrel, AccessShareLock);
- if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
- {
- relation->rd_att->constr = constr;
-
- if (ndef > 0) /* DEFAULTs */
- {
- if (ndef < relation->rd_rel->relnatts)
- constr->defval = (AttrDefault *)
- repalloc(attrdef, ndef * sizeof(AttrDefault));
- else
- constr->defval = attrdef;
- constr->num_defval = ndef;
- AttrDefaultFetch(relation);
- }
- else
- constr->num_defval = 0;
-
- if (relation->rd_rel->relchecks > 0) /* CHECKs */
- {
- constr->num_check = relation->rd_rel->relchecks;
- constr->check = (ConstrCheck *) palloc(constr->num_check *
- sizeof(ConstrCheck));
- MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck));
- RelCheckFetch(relation);
- }
- else
- constr->num_check = 0;
- }
- else
- {
- pfree(constr);
- relation->rd_att->constr = NULL;
- }
+ SetConstrOfRelation(relation, constr, ndef, attrdef);
}
AttrDefault *attrdef = relation->rd_att->constr->defval;
int ndef = relation->rd_att->constr->num_defval;
Relation adrel;
- Relation irel;
+ Relation irel = (Relation) NULL;
ScanKeyData skey;
HeapTupleData tuple;
+ HeapTuple htup;
Form_pg_attrdef adform;
- IndexScanDesc sd;
+ IndexScanDesc sd = (IndexScanDesc) NULL;
+ HeapScanDesc adscan = (HeapScanDesc) NULL;
RetrieveIndexResult indexRes;
struct varlena *val;
bool isnull;
int found;
int i;
+ bool hasindex;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
ObjectIdGetDatum(RelationGetRelid(relation)));
adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
- irel = index_openr(AttrDefaultIndex);
- sd = index_beginscan(irel, false, 1, &skey);
+ hasindex = (adrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
+ if (hasindex)
+ {
+ irel = index_openr(AttrDefaultIndex);
+ sd = index_beginscan(irel, false, 1, &skey);
+ }
+ else
+ adscan = heap_beginscan(adrel, false, SnapshotNow, 1, &skey);
tuple.t_datamcxt = NULL;
tuple.t_data = NULL;
{
Buffer buffer;
- indexRes = index_getnext(sd, ForwardScanDirection);
- if (!indexRes)
- break;
-
- tuple.t_self = indexRes->heap_iptr;
- heap_fetch(adrel, SnapshotNow, &tuple, &buffer);
- pfree(indexRes);
- if (tuple.t_data == NULL)
- continue;
+ if (hasindex)
+ {
+ indexRes = index_getnext(sd, ForwardScanDirection);
+ if (!indexRes)
+ break;
+
+ tuple.t_self = indexRes->heap_iptr;
+ heap_fetch(adrel, SnapshotNow, &tuple, &buffer);
+ pfree(indexRes);
+ if (tuple.t_data == NULL)
+ continue;
+ htup = &tuple;
+ }
+ else
+ {
+ htup = heap_getnext(adscan, 0);
+ if (!HeapTupleIsValid(htup))
+ break;
+ }
found++;
- adform = (Form_pg_attrdef) GETSTRUCT(&tuple);
+ adform = (Form_pg_attrdef) GETSTRUCT(htup);
for (i = 0; i < ndef; i++)
{
if (adform->adnum != attrdef[i].adnum)
NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
RelationGetRelationName(relation));
- val = (struct varlena *) fastgetattr(&tuple,
+ val = (struct varlena *) fastgetattr(htup,
Anum_pg_attrdef_adbin,
adrel->rd_att, &isnull);
if (isnull)
attrdef[i].adbin = textout(val);
break;
}
- ReleaseBuffer(buffer);
+ if (hasindex)
+ ReleaseBuffer(buffer);
if (i >= ndef)
elog(NOTICE, "AttrDefaultFetch: unexpected record found for attr %d in rel %s",
elog(NOTICE, "AttrDefaultFetch: %d record not found for rel %s",
ndef - found, RelationGetRelationName(relation));
- index_endscan(sd);
- index_close(irel);
+ if (hasindex)
+ {
+ index_endscan(sd);
+ index_close(irel);
+ }
+ else
+ heap_endscan(adscan);
heap_close(adrel, AccessShareLock);
}
ConstrCheck *check = relation->rd_att->constr->check;
int ncheck = relation->rd_att->constr->num_check;
Relation rcrel;
- Relation irel;
+ Relation irel = (Relation)NULL;
ScanKeyData skey;
HeapTupleData tuple;
- IndexScanDesc sd;
+ HeapTuple htup;
+ IndexScanDesc sd = (IndexScanDesc)NULL;
+ HeapScanDesc rcscan = (HeapScanDesc)NULL;
RetrieveIndexResult indexRes;
Name rcname;
struct varlena *val;
bool isnull;
int found;
+ bool hasindex;
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
ObjectIdGetDatum(RelationGetRelid(relation)));
rcrel = heap_openr(RelCheckRelationName, AccessShareLock);
- irel = index_openr(RelCheckIndex);
- sd = index_beginscan(irel, false, 1, &skey);
+ hasindex = (rcrel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
+ if (hasindex)
+ {
+ irel = index_openr(RelCheckIndex);
+ sd = index_beginscan(irel, false, 1, &skey);
+ }
+ else
+ rcscan = heap_beginscan(rcrel, false, SnapshotNow, 1, &skey);
tuple.t_datamcxt = NULL;
tuple.t_data = NULL;
{
Buffer buffer;
- indexRes = index_getnext(sd, ForwardScanDirection);
- if (!indexRes)
- break;
-
- tuple.t_self = indexRes->heap_iptr;
- heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);
- pfree(indexRes);
- if (tuple.t_data == NULL)
- continue;
+ if (hasindex)
+ {
+ indexRes = index_getnext(sd, ForwardScanDirection);
+ if (!indexRes)
+ break;
+
+ tuple.t_self = indexRes->heap_iptr;
+ heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);
+ pfree(indexRes);
+ if (tuple.t_data == NULL)
+ continue;
+ htup = &tuple;
+ }
+ else
+ {
+ htup = heap_getnext(rcscan, 0);
+ if (!HeapTupleIsValid(htup))
+ break;
+ }
if (found == ncheck)
elog(ERROR, "RelCheckFetch: unexpected record found for rel %s",
RelationGetRelationName(relation));
- rcname = (Name) fastgetattr(&tuple,
+ rcname = (Name) fastgetattr(htup,
Anum_pg_relcheck_rcname,
rcrel->rd_att, &isnull);
if (isnull)
elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s",
RelationGetRelationName(relation));
check[found].ccname = pstrdup(NameStr(*rcname));
- val = (struct varlena *) fastgetattr(&tuple,
+ val = (struct varlena *) fastgetattr(htup,
Anum_pg_relcheck_rcbin,
rcrel->rd_att, &isnull);
if (isnull)
RelationGetRelationName(relation));
check[found].ccbin = textout(val);
found++;
- ReleaseBuffer(buffer);
+ if (hasindex)
+ ReleaseBuffer(buffer);
}
if (found < ncheck)
elog(ERROR, "RelCheckFetch: %d record not found for rel %s",
ncheck - found, RelationGetRelationName(relation));
- index_endscan(sd);
- index_close(irel);
+ if (hasindex)
+ {
+ index_endscan(sd);
+ index_close(irel);
+ }
+ else
+ heap_endscan(rcscan);
heap_close(rcrel, AccessShareLock);
}
RelationCacheInsert(ird);
}
+ criticalRelcacheBuild = true;
}
static void
Form_pg_class relform;
IndexStrategy strat;
RegProcedure *support;
- ProcessingMode oldmode;
int i;
int relno;
RelationBuildDescInfo bi;
* descriptors, nail them into cache so we never lose them.
*/
+ /* Removed the following ProcessingMode change -- inoue
+ * At this point
+ * 1) Catalog Cache isn't initialized
+ * 2) Relation Cache for the following critical indexes aren't built
oldmode = GetProcessingMode();
SetProcessingMode(BootstrapProcessing);
+ */
bi.infotype = INFO_RELNAME;
bi.i.info_name = AttributeRelidNumIndex;
irel[2] = RelationBuildDesc(bi, NULL);
irel[2]->rd_isnailed = true;
+ criticalRelcacheBuild = true;
+ /* Removed the following ProcessingMode -- inoue
SetProcessingMode(oldmode);
+ */
/*
* Write out the index reldescs to the special cache file.
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.48 2000/01/26 05:57:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.49 2000/02/18 09:28:56 inoue Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
#include "catalog/pg_type.h"
#include "utils/catcache.h"
#include "utils/temprel.h"
+#include "miscadmin.h"
extern bool AMI_OVERRIDE; /* XXX style */
static struct catcache *SysCache[lengthof(cacheinfo)];
static int32 SysCacheSize = lengthof(cacheinfo);
+static bool CacheInitialized = false;
+extern bool IsCacheInitialized(void)
+{
+ return CacheInitialized;
+}
/*
}
}
+ CacheInitialized = true;
}
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.43 2000/01/26 05:57:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.44 2000/02/18 09:28:58 inoue Exp $
*
*-------------------------------------------------------------------------
*/
ProcessingMode Mode = InitProcessing;
+/* ----------------------------------------------------------------
+ * ignoring system indexes support stuff
+ * ----------------------------------------------------------------
+ */
+
+static bool isIgnoringSystemIndexes = false;
+
+/*
+ * IsIgnoringSystemIndexes
+ * True if ignoring system indexes.
+ */
+bool
+IsIgnoringSystemIndexes()
+{
+ return isIgnoringSystemIndexes;
+}
+
+/*
+ * IgnoreSystemIndexes
+ * Set true or false whether PostgreSQL ignores system indexes.
+ *
+ */
+void
+IgnoreSystemIndexes(bool mode)
+{
+ isIgnoringSystemIndexes = mode;
+}
/* ----------------------------------------------------------------
* database path / name support stuff
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: index.h,v 1.21 2000/01/26 05:57:56 momjian Exp $
+ * $Id: index.h,v 1.22 2000/02/18 09:29:19 inoue Exp $
*
*-------------------------------------------------------------------------
*/
TupleDesc heapDescriptor, Datum *datum,
char *nullv, FuncIndexInfoPtr fInfo);
-extern void UpdateStats(Oid relid, long reltuples, bool hasindex);
+extern void UpdateStats(Oid relid, long reltuples, bool inplace);
+extern bool IndexesAreActive(Oid relid, bool comfirmCommitted);
+extern void setRelhasindexInplace(Oid relid, bool hasindex, bool immediate);
+extern bool SetReindexProcessing(bool processing);
+extern bool IsReindexProcessing(void);
extern void FillDummyExprContext(ExprContext *econtext, TupleTableSlot *slot,
TupleDesc tupdesc, Buffer buffer);
extern bool IndexIsUnique(Oid indexId);
extern bool IndexIsUniqueNoCache(Oid indexId);
+extern bool activate_index(Oid indexId, bool activate);
+extern bool reindex_index(Oid indexId, bool force);
+extern bool activate_indexes_of_a_table(Oid relid, bool activate);
+extern bool reindex_relation(Oid relid, bool force);
#endif /* INDEX_H */
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: defrem.h,v 1.18 2000/01/26 05:58:00 momjian Exp $
+ * $Id: defrem.h,v 1.19 2000/02/18 09:29:49 inoue Exp $
*
*-------------------------------------------------------------------------
*/
Expr *predicate,
List *rangetable);
extern void RemoveIndex(char *name);
+extern void ReindexIndex(const char *indexRelationName, bool force);
+extern void ReindexTable(const char *relationName, bool force);
+extern void ReindexDatabase(const char *databaseName, bool force, bool all);
/*
* prototypes in define.c
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: miscadmin.h,v 1.50 2000/01/26 05:57:46 momjian Exp $
+ * $Id: miscadmin.h,v 1.51 2000/02/18 09:29:06 inoue Exp $
*
* NOTES
* some of the information in this file will be moved to
#define GetProcessingMode() Mode
+extern void IgnoreSystemIndexes(bool mode);
+extern bool IsIgnoringSystemIndexes(void);
+extern bool IsCacheInitialized(void);
/*
* "postmaster.pid" is a file containing postmaster's pid, being
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.64 2000/02/15 20:49:24 tgl Exp $
+ * $Id: nodes.h,v 1.65 2000/02/18 09:29:43 inoue Exp $
*
*-------------------------------------------------------------------------
*/
T_DeleteStmt,
T_UpdateStmt,
T_SelectStmt,
- T_AlterTableStmt,
+ T_AlterTableStmt,
T_AggregateStmt,
T_ChangeACLStmt,
T_ClosePortalStmt,
T_DropUserStmt,
T_LockStmt,
T_ConstraintsSetStmt,
- T_CreateGroupStmt,
- T_AlterGroupStmt,
- T_DropGroupStmt,
+ T_CreateGroupStmt,
+ T_AlterGroupStmt,
+ T_DropGroupStmt,
+ T_ReindexStmt,
T_A_Expr = 700,
T_Attr,
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.99 2000/02/15 20:49:24 tgl Exp $
+ * $Id: parsenodes.h,v 1.100 2000/02/18 09:29:44 inoue Exp $
*
*-------------------------------------------------------------------------
*/
bool deferred;
} ConstraintsSetStmt;
+/* ----------------------
+ * REINDEX Statement
+ * ----------------------
+ */
+typedef struct ReindexStmt
+{
+ NodeTag type;
+ int reindexType; /* INDEX|TABLE|DATABASE */
+ const char *name; /* name to reindex */
+ bool force;
+ bool all;
+} ReindexStmt;
+
/*****************************************************************************
* Optimizable Statements
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: portal.h,v 1.21 2000/01/26 05:58:38 momjian Exp $
+ * $Id: portal.h,v 1.22 2000/02/18 09:30:16 inoue Exp $
*
*-------------------------------------------------------------------------
*/
extern void PortalResetHeapMemory(Portal portal);
extern PortalVariableMemory PortalGetVariableMemory(Portal portal);
extern PortalHeapMemory PortalGetHeapMemory(Portal portal);
+extern void CommonSpecialPortalOpen(void);
+extern void CommonSpecialPortalClose(void);
+extern PortalVariableMemory CommonSpecialPortalGetMemory(void);
+extern bool CommonSpecialPortalIsOpen(void);
/* estimate of the maximum number of open portals a user would have,
* used in initially sizing the PortalHashTable in EnablePortalManager()