diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c
index ef188d0e41257997264bceb9eb19718cdae1ee8c..fe956ead378aa133c6bc8650239103283b4712ce 100644
--- a/src/backend/access/index/istrat.c
+++ b/src/backend/access/index/istrat.c
@@ -9,7 +9,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -477,8 +477,9 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
 {
 	HeapTuple	tuple;
 	HeapScanDesc scan = NULL;
+	bool	cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized();
 
-	if (!IsBootstrapProcessingMode())
+	if (cachesearch)
 	{
 		tuple = SearchSysCacheTuple(OPEROID,
 									ObjectIdGetDatum(operatorObjectId),
@@ -501,7 +502,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
 
 	if (!HeapTupleIsValid(tuple))
 	{
-		if (IsBootstrapProcessingMode())
+		if (!cachesearch)
 			heap_endscan(scan);
 		elog(ERROR, "OperatorObjectIdFillScanKeyEntry: unknown operator %u",
 			 operatorObjectId);
@@ -512,7 +513,7 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation,
 	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))
@@ -546,8 +547,9 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
 	AttrNumber	attributeNumber;
 	int			attributeIndex;
 	Oid			operatorClassObjectId[INDEX_MAX_KEYS];
+	bool	cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized();
 
-	if (!IsBootstrapProcessingMode())
+	if (cachesearch)
 	{
 		tuple = SearchSysCacheTuple(INDEXRELID,
 									ObjectIdGetDatum(indexObjectId),
@@ -589,7 +591,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
 		operatorClassObjectId[attributeIndex] = iform->indclass[attributeIndex];
 	}
 
-	if (IsBootstrapProcessingMode())
+	if (!cachesearch)
 	{
 		heap_endscan(scan);
 		heap_close(relation, AccessShareLock);
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index fa8decce1300fb89596d44413ee9e88e35dcf12e..da5dd70332e5b07a5552b309a98d52828298f684 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -310,16 +310,22 @@ btbuild(Relation heap,
 	{
 		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);
 		}
 	}
 
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 58e17445586d454ca7bfb77f62180e62f54c3027..e5b521b67cfc158ea1ec3049a863e6dc959f6883 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -8,7 +8,7 @@
  *
  *
  * 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:
@@ -147,6 +147,7 @@
 
 #include "access/nbtree.h"
 #include "catalog/heap.h"
+#include "catalog/index.h"
 #include "commands/async.h"
 #include "commands/sequence.h"
 #include "commands/vacuum.h"
@@ -850,6 +851,7 @@ StartTransaction()
 	 */
 	s->state = TRANS_START;
 
+	SetReindexProcessing(false);
 	/* ----------------
 	 *	generate a new transaction id
 	 * ----------------
@@ -1046,8 +1048,8 @@ AbortTransaction()
 	AtAbort_Notify();
 	CloseSequences();
 	AtEOXact_portals();
-	if (VacuumRunning)
-		vc_abort();
+	if (CommonSpecialPortalIsOpen())
+		CommonSpecialPortalClose();
 	RecordTransactionAbort();
 	RelationPurgeLocalRelation(false);
 	DropNoNameRels();
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index e8afa33de2cf7afd5447c0bc1804115034480b6b..8e129a460a9e56cb6b33ba66f5f1d17d98215f39 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -292,6 +292,7 @@ BootstrapMain(int argc, char *argv[])
 		dbName = argv[optind];
 
 	SetProcessingMode(BootstrapProcessing);
+	IgnoreSystemIndexes(true);
 
 	if (!DataDir)
 	{
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 2840e40633f5c63319bc405a6de8161c4e55f281..271dc3ed9789ba2423782ee8dcaadddcbf011769 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -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
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 6040d09f24a09c89b98f69440c1b5f5b06ebb0af..b7d49ed3bc8c6f927cd989bbc17a9b01a5c52514 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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;
+}
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 2afd6b69097d44a80f13515ac4d6331c974689a1..41337da77f8a469b682fc764b24d857fc97a18fd 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -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++)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index f5de425b2bb95b97237933a468228a7c34157e47..cbd7b26ae8ad2370693b03d1fd624bb7d8972bb2 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,12 +17,15 @@
 
 #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"
@@ -30,6 +33,9 @@
 #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)
 
@@ -149,6 +155,8 @@ DefineIndex(char *heapRelationName,
 		CheckPredicate(cnfPred, rangetable, relationId);
 	}
 
+	if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
+		elog(ERROR, "existent indexes are inactive. REINDEX first");
 	if (IsFuncIndex(attributeList))
 	{
 		IndexElem  *funcIndex = lfirst(attributeList);
@@ -195,6 +203,7 @@ DefineIndex(char *heapRelationName,
 			 classObjectId, parameterCount, parameterA, (Node *) cnfPred,
 					 lossy, unique, primary);
 	}
+	setRelhasindexInplace(relationId, true, false);
 }
 
 
@@ -570,3 +579,163 @@ RemoveIndex(char *name)
 
 	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();
+}
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 0b0b3cf2ece8e25a0b74b9d95eb79d5619076c00..9a4286a500ac4633c03b25f56a34c742d52c88e0 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -433,15 +433,18 @@ RelationBuildTriggers(Relation relation)
 	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));
 
@@ -452,25 +455,41 @@ RelationBuildTriggers(Relation relation)
 						   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));
@@ -478,7 +497,7 @@ RelationBuildTriggers(Relation relation)
 			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;
@@ -489,7 +508,7 @@ RelationBuildTriggers(Relation relation)
 		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)
@@ -500,7 +519,7 @@ RelationBuildTriggers(Relation relation)
 			char	   *p;
 			int			i;
 
-			val = (struct varlena *) fastgetattr(&tuple,
+			val = (struct varlena *) fastgetattr(htup,
 												 Anum_pg_trigger_tgargs,
 												 tgrel->rd_att, &isnull);
 			if (isnull)
@@ -518,7 +537,8 @@ RelationBuildTriggers(Relation relation)
 			build->tgargs = NULL;
 
 		found++;
-		ReleaseBuffer(buffer);
+		if (hasindex)
+			ReleaseBuffer(buffer);
 	}
 
 	if (found < ntrigs)
@@ -526,8 +546,13 @@ RelationBuildTriggers(Relation relation)
 			 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 */
@@ -1460,7 +1485,7 @@ void
 DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 {
 	Relation				tgrel;
-	Relation				irel;
+	Relation				irel = (Relation) NULL;
 	List					*l;
 	List					*ls;
 	List					*lnext;
@@ -1468,6 +1493,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 	MemoryContext			oldcxt;
 	bool					found;
 	DeferredTriggerStatus	state;
+	bool			hasindex;
 
 	/* ----------
 	 * Handle SET CONSTRAINTS ALL ...
@@ -1548,13 +1574,17 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 	 * ----------
 	 */
 	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;
@@ -1577,7 +1607,10 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 							   (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
@@ -1586,33 +1619,43 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 		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);
 		}
 
 		/* ----------
@@ -1622,9 +1665,13 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 		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);
 
 
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 5274be3bdf3536f1ccd87c238e38534e4c1db15c..ef84459a7145033663f753530a345badb891802b 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,7 +51,7 @@
 #endif
 
 
-bool		VacuumRunning = false;
+bool		CommonSpecialPortalInUse = false;
 
 static Portal vc_portal;
 
@@ -99,6 +99,53 @@ static bool vc_enough_space(VPageDescr vpd, Size len);
 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)
 {
@@ -136,7 +183,7 @@ 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)
 	{
@@ -179,24 +226,7 @@ vacuum(char *vacrel, bool verbose, bool analyze, List *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();
@@ -219,30 +249,12 @@ vc_shutdown()
 	 */
 	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.
  *
@@ -302,7 +314,7 @@ vc_getrels(NameData *VacRelP)
 							   F_CHAREQ, CharGetDatum('r'));
 	}
 
-	portalmem = PortalGetVariableMemory(vc_portal);
+	portalmem = CommonSpecialPortalGetMemory();
 	vrl = cur = (VRelList) NULL;
 
 	rel = heap_openr(RelationRelationName, AccessShareLock);
@@ -379,6 +391,7 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
 	int32		nindices,
 				i;
 	VRelStats  *vacrelstats;
+	bool	   reindex = false;
 
 	StartTransactionCommand();
 
@@ -552,17 +565,31 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
 	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)
@@ -590,6 +617,8 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
 												 * 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)
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 11cde461b417fed9087fd0997e57b60b6a10dcc9..8f15ac1ed180b18493ecb850d2bf5c9c47fa8a55 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,8 +48,10 @@
 #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);
@@ -770,6 +772,12 @@ ExecOpenIndices(Oid resultRelationOid,
 	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
 	 * ----------------
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index e5f7642c85cc6e2de127c0f9673c07557614d9d7..b1d1c578f385503fd110177e57d959da22467ed6 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -1048,6 +1048,10 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 				  &currentRelation,		/* return: rel desc */
 				  (Pointer *) &currentScanDesc);		/* 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;
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index e3a60c2c7f04be74e8f0949a0882514cd9ea2791..716c31ab0f132b7756457f30ba066a1e41b10a30 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,6 +29,8 @@
 #include "optimizer/plancat.h"
 #include "parser/parsetree.h"
 #include "utils/syscache.h"
+#include "catalog/catalog.h"
+#include "miscadmin.h"
 
 
 /*
@@ -55,7 +57,10 @@ relation_info(Query *root, Index relid,
 			 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;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 4babad9524a12b07ce8f1e3522162d15996b7f8d..b6962f8fad6f4be3f6ee42519f55a9304f167aae 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * 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
@@ -124,7 +124,7 @@ static Node *doNegate(Node *n);
 		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,
@@ -141,7 +141,7 @@ static Node *doNegate(Node *n);
 %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
@@ -211,7 +211,7 @@ static Node *doNegate(Node *n);
 				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
 
@@ -339,13 +339,13 @@ static Node *doNegate(Node *n);
 		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
@@ -440,6 +440,7 @@ stmt :	AlterTableStmt
 		| UnlistenStmt
 		| LockStmt
 		| ProcedureStmt
+		| ReindexStmt
 		| RemoveAggrStmt
 		| RemoveOperStmt
 		| RemoveFuncStmt
@@ -2445,6 +2446,35 @@ oper_argtypes:	name
 		;
 
 
+/*****************************************************************************
+ *
+ *		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:
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index e1c9424e37a358b8dff742b8ca32bfbfc9a9f040..d971e95762dcfd008d5c8681734968068df45e1e 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -107,6 +107,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"fetch", FETCH},
 	{"float", FLOAT},
 	{"for", FOR},
+	{"force", FORCE},
 	{"foreign", FOREIGN},
 	{"forward", FORWARD},
 	{"from", FROM},
@@ -196,6 +197,7 @@ static ScanKeyword ScanKeywords[] = {
 	{"public", PUBLIC},
 	{"read", READ},
 	{"references", REFERENCES},
+	{"reindex", REINDEX},
 	{"relative", RELATIVE},
 	{"rename", RENAME},
 	{"reset", RESET},
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3059e8b8289c4335a2eaf9e60aa091472bec9e64..c455d1cbd2a5004005adbdb26425cada12306518 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -11,7 +11,7 @@
  *
  *
  * 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
  *
@@ -430,6 +430,7 @@ PostmasterMain(int argc, char *argv[])
 	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)
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 123d70af9b439305e3f54faa667b596fa5b712a3..77422deb386c1c535cbab82f3ab215d771878be5 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * 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
@@ -963,7 +963,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 	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)
 		{
@@ -1116,6 +1116,15 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 					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
@@ -1516,7 +1525,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 	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");
 	}
 
 	/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 66acb230f2e5072395cec1d0bbea4556dfc3f1c3..427bf7b4d41279895c507c6b88ffcb39857d62fb 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -846,6 +846,61 @@ ProcessUtility(Node *parsetree,
             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 ********************************
 			 *
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 732569fa8f5c7232ac81704b0c60b642982f976f..8094addc7d673f3d8eaa6baca907c408b5f5959e 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,7 +45,7 @@ regprocin(char *pro_name_or_oid)
 	if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
 		return InvalidOid;
 
-	if (!IsBootstrapProcessingMode())
+	if (!IsIgnoringSystemIndexes())
 	{
 
 		/*
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 1f224e56cfedba7714a1c60b848f7b60374e1aaa..c6c8763c706bfc284179cefac681d6baed5cb38a 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -233,7 +233,7 @@ CatalogCacheInitializeCache(struct catcache * cache,
 	 */
 	if (cache->cc_indname != NULL && cache->indexId == InvalidOid)
 	{
-		if (RelationGetForm(relation)->relhasindex)
+		if (!IsIgnoringSystemIndexes() && RelationGetForm(relation)->relhasindex)
 		{
 
 			/*
@@ -817,14 +817,19 @@ SearchSelfReferences(struct catcache * cache)
 
 		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? */
@@ -1031,7 +1036,7 @@ SearchSysCache(struct catcache * cache,
 	CACHE1_elog(DEBUG, "SearchSysCache: performing scan");
 
 	if ((RelationGetForm(relation))->relhasindex
-		&& !IsBootstrapProcessingMode())
+		&& !IsIgnoringSystemIndexes())
 	{
 		/* ----------
 		 *	Switch back to old memory context so memory not freed
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 7c993d3d73f12c6c675ffe608bc55d60c1fbe488..161576291542c6dcb373f1003e8f1b220741e24e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -229,6 +229,7 @@ static void IndexedAccessMethodInitialize(Relation relation);
 static void AttrDefaultFetch(Relation relation);
 static void RelCheckFetch(Relation relation);
 
+static bool	criticalRelcacheBuild = false;
 /* ----------------------------------------------------------------
  *		RelationIdGetRelation() and RelationNameGetRelation()
  *						support functions
@@ -254,7 +255,7 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
 	 * can, and do.
 	 */
 
-	if (IsBootstrapProcessingMode())
+	if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
 		return scan_pg_rel_seq(buildinfo);
 	else
 		return scan_pg_rel_ind(buildinfo);
@@ -424,12 +425,50 @@ RelationBuildTupleDesc(RelationBuildDescInfo 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,
@@ -441,7 +480,11 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 	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
 	 * ----------------
@@ -478,6 +521,23 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 					(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);
 	}
@@ -492,6 +552,8 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
 	 */
 	heap_endscan(pg_attribute_scan);
 	heap_close(pg_attribute_desc, AccessShareLock);
+
+	SetConstrOfRelation(relation, constr, ndef, attrdef);
 }
 
 static void
@@ -549,39 +611,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 
 	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);
 
 }
 
@@ -1806,16 +1836,19 @@ AttrDefaultFetch(Relation relation)
 	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,
@@ -1824,8 +1857,14 @@ AttrDefaultFetch(Relation relation)
 						   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;
 
@@ -1833,17 +1872,27 @@ AttrDefaultFetch(Relation relation)
 	{
 		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)
@@ -1853,7 +1902,7 @@ AttrDefaultFetch(Relation relation)
 				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)
@@ -1863,7 +1912,8 @@ AttrDefaultFetch(Relation relation)
 			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",
@@ -1875,8 +1925,13 @@ AttrDefaultFetch(Relation relation)
 		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);
 }
 
@@ -1886,15 +1941,18 @@ RelCheckFetch(Relation relation)
 	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,
@@ -1903,8 +1961,14 @@ RelCheckFetch(Relation relation)
 						   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;
 
@@ -1912,27 +1976,37 @@ RelCheckFetch(Relation relation)
 	{
 		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)
@@ -1940,15 +2014,21 @@ RelCheckFetch(Relation relation)
 				 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);
 }
 
@@ -2148,6 +2228,7 @@ init_irels(void)
 
 		RelationCacheInsert(ird);
 	}
+	criticalRelcacheBuild = true;
 }
 
 static void
@@ -2162,7 +2243,6 @@ write_irels(void)
 	Form_pg_class relform;
 	IndexStrategy strat;
 	RegProcedure *support;
-	ProcessingMode oldmode;
 	int			i;
 	int			relno;
 	RelationBuildDescInfo bi;
@@ -2186,8 +2266,13 @@ write_irels(void)
 	 * 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;
@@ -2202,7 +2287,10 @@ write_irels(void)
 	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.
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 3cc75198994bc9f8ff1ac5f1d1a1f92f4b39bb2f..087002ab76fe6a5a24f736aa2e9b5e665f14149f 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
  *
  *
  * 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
@@ -39,6 +39,7 @@
 #include "catalog/pg_type.h"
 #include "utils/catcache.h"
 #include "utils/temprel.h"
+#include "miscadmin.h"
 
 extern bool AMI_OVERRIDE;		/* XXX style */
 
@@ -395,6 +396,11 @@ static struct cachedesc cacheinfo[] = {
 
 static struct catcache *SysCache[lengthof(cacheinfo)];
 static int32 SysCacheSize = lengthof(cacheinfo);
+static bool  CacheInitialized = false;
+extern bool  IsCacheInitialized(void)
+{
+	return CacheInitialized;
+}
 
 
 /*
@@ -442,6 +448,7 @@ InitCatalogCache()
 
 		}
 	}
+	CacheInitialized = true;
 }
 
 /*
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index d5ce83dc6c45762364120513a2843602faf26acd..41b4020c713ce10f71bbeeb11dcfa23e731b6fcf 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,33 @@ unsigned char RecodeBackTable[128];
 
 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
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index b6d90c3a12c47fce25153c8aeb496169f0d1c699..b65e2ad98ebaed593881198add8c5d6a61c1ea56 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -7,7 +7,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,7 +47,11 @@ extern void FormIndexDatum(int numberOfAttributes,
 			   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);
@@ -60,4 +64,8 @@ extern void index_build(Relation heapRelation, Relation indexRelation,
 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 */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index f5d69339e7192238af7044fe9685a0f889699391..f0a1e381e1ae383a8ea686eb92b0fe15981a0dd1 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,9 @@ extern void ExtendIndex(char *indexRelationName,
 			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
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 7e47b3a36030b2b1c5561f575506794322008927..df3de38611b0a340124c995380a7e6ad62986c63 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
  * 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
@@ -211,6 +211,9 @@ extern ProcessingMode Mode;
 
 #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
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 161b53c25af97db7ad2d96d18aaccde3f7c75f94..8dd893e3f13cc2ef79b260f6a132d27ca4dec2d1 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -146,7 +146,7 @@ typedef enum NodeTag
 	T_DeleteStmt,
 	T_UpdateStmt,
 	T_SelectStmt,
-    T_AlterTableStmt,
+	T_AlterTableStmt,
 	T_AggregateStmt,
 	T_ChangeACLStmt,
 	T_ClosePortalStmt,
@@ -191,9 +191,10 @@ typedef enum NodeTag
 	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,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index df7bec10f0008912ca33a9ec008fbd73a4d4cf1e..d98398aadecd895c55b3856ba015cc6bdac27795 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -722,6 +722,19 @@ typedef struct ConstraintsSetStmt
 	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
diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h
index 73a53b2a419042c68fc3517f6b11ed0a4fcbf771..d24fd16f1a59dfe28b5f5cde7d26686fc52b2315 100644
--- a/src/include/utils/portal.h
+++ b/src/include/utils/portal.h
@@ -7,7 +7,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,6 +80,10 @@ extern void EndPortalAllocMode(void);
 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()