diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 91b1763d7597f8f93f55bce096757645af944bbd..6e0974ac32d4da717732877b2169a08e964c7096 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.118 2001/06/09 18:16:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.119 2001/06/22 19:16:20 wieck Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -45,6 +45,7 @@
 #include "miscadmin.h"
 #include "utils/inval.h"
 #include "utils/relcache.h"
+#include "pgstat.h"
 
 
 XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
@@ -531,6 +532,10 @@ heap_openr(const char *relationName, LOCKMODE lockmode)
 	if (lockmode != NoLock)
 		LockRelation(r, lockmode);
 
+	pgstat_initstats(&r->pgstat_info, r);
+
+	pgstat_initstats(&r->pgstat_info, r);
+
 	return r;
 }
 
@@ -591,6 +596,12 @@ heap_openr_nofail(const char *relationName)
 	if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
 		elog(ERROR, "%s is an index relation", RelationGetRelationName(r));
 
+	if (RelationIsValid(r))
+		pgstat_initstats(&r->pgstat_info, r);
+
+	if (RelationIsValid(r))
+		pgstat_initstats(&r->pgstat_info, r);
+
 	return r;
 }
 
@@ -668,6 +679,8 @@ heap_beginscan(Relation relation,
 	scan->rs_snapshot = snapshot;
 	scan->rs_nkeys = (short) nkeys;
 
+	pgstat_initstats(&scan->rs_pgstat_info, relation);
+
 	/*
 	 * we do this here instead of in initscan() because heap_rescan also
 	 * calls initscan() and we don't want to allocate memory again
@@ -707,6 +720,8 @@ heap_rescan(HeapScanDesc scan,
 	 * reinitialize scan descriptor
 	 */
 	initscan(scan, scan->rs_rd, scanFromEnd, scan->rs_nkeys, key);
+
+	pgstat_reset_heap_scan(&scan->rs_pgstat_info);
 }
 
 /* ----------------
@@ -828,6 +843,8 @@ heap_getnext(HeapScanDesc scan, int backw)
 		}
 	}
 
+	pgstat_count_heap_scan(&scan->rs_pgstat_info);
+
 	/*
 	 * if we get here it means we have a new current scan tuple, so point
 	 * to the proper return buffer and return the tuple.
@@ -835,6 +852,9 @@ heap_getnext(HeapScanDesc scan, int backw)
 
 	HEAPDEBUG_3;				/* heap_getnext returning tuple */
 
+	if (scan->rs_ctup.t_data != NULL)
+		pgstat_count_heap_getnext(&scan->rs_pgstat_info);
+
 	return ((scan->rs_ctup.t_data == NULL) ? NULL : &(scan->rs_ctup));
 }
 
@@ -855,7 +875,8 @@ void
 heap_fetch(Relation relation,
 		   Snapshot snapshot,
 		   HeapTuple tuple,
-		   Buffer *userbuf)
+		   Buffer *userbuf,
+		   IndexScanDesc iscan)
 {
 	ItemId		lp;
 	Buffer		buffer;
@@ -930,6 +951,11 @@ heap_fetch(Relation relation,
 		 * responsible for releasing the buffer.
 		 */
 		*userbuf = buffer;
+
+		if (iscan != NULL)
+			pgstat_count_heap_fetch(&iscan->xs_pgstat_info);
+		else
+			pgstat_count_heap_fetch(&relation->pgstat_info);
 	}
 }
 
@@ -1081,6 +1107,8 @@ heap_insert(Relation relation, HeapTuple tup)
 	START_CRIT_SECTION();
 	RelationPutHeapTuple(relation, buffer, tup);
 
+	pgstat_count_heap_insert(&relation->pgstat_info);
+
 	/* XLOG stuff */
 	{
 		xl_heap_insert xlrec;
@@ -1269,6 +1297,8 @@ l1:
 		heap_tuple_toast_attrs(relation, NULL, &(tp));
 #endif
 
+	pgstat_count_heap_delete(&relation->pgstat_info);
+
 	/*
 	 * Mark tuple for invalidation from system caches at next command
 	 * boundary. We have to do this before WriteBuffer because we need to
@@ -1528,6 +1558,8 @@ l2:
 		newbuf = buffer;
 	}
 
+	pgstat_count_heap_update(&relation->pgstat_info);
+
 	/*
 	 * At this point newbuf and buffer are both pinned and locked,
 	 * and newbuf has enough space for the new tuple.
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 2a9df577b10c56de723c68ae329e47847849fb71..74f0e06e61c815951dcd48f348bb5e813276d5bc 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.22 2001/05/07 00:43:15 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.23 2001/06/22 19:16:20 wieck Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -936,7 +936,7 @@ toast_delete_datum(Relation rel, Datum value)
 	while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL)
 	{
 		toasttup.t_self = indexRes->heap_iptr;
-		heap_fetch(toastrel, SnapshotAny, &toasttup, &buffer);
+		heap_fetch(toastrel, SnapshotAny, &toasttup, &buffer, toastscan);
 		pfree(indexRes);
 
 		if (!toasttup.t_data)
@@ -1029,7 +1029,7 @@ toast_fetch_datum(varattrib *attr)
 	while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL)
 	{
 		toasttup.t_self = indexRes->heap_iptr;
-		heap_fetch(toastrel, SnapshotAny, &toasttup, &buffer);
+		heap_fetch(toastrel, SnapshotAny, &toasttup, &buffer, toastscan);
 		pfree(indexRes);
 
 		if (toasttup.t_data == NULL)
diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index ee9cea6646ce3cebe89ed04152522c7682be6086..1115fb828b2bc3b490545ace86775103aaed5b8c 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.27 2001/06/09 18:16:56 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.28 2001/06/22 19:16:21 wieck Exp $
  *
  * NOTES
  *	  many of the old access method routines have been turned into
@@ -48,6 +48,7 @@
 #include "postgres.h"
 #include "access/genam.h"
 
+#include "pgstat.h"
 
 /* ----------------------------------------------------------------
  *		general access method routines
@@ -110,6 +111,8 @@ RelationGetIndexScan(Relation relation,
 	ItemPointerSetInvalid(&scan->currentItemData);
 	ItemPointerSetInvalid(&scan->currentMarkData);
 
+	pgstat_initstats(&scan->xs_pgstat_info, relation);
+
 	/*
 	 * mark cached function lookup data invalid; it will be set on first
 	 * use
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 5b12930114873ce73567dd01b158cb25d6f21e66..adeccf5cc84ea4c0022e1aeaca057770e5b64cf8 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.50 2001/06/01 02:41:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.51 2001/06/22 19:16:21 wieck Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relationId
@@ -70,6 +70,7 @@
 #include "access/heapam.h"
 #include "utils/relcache.h"
 
+#include "pgstat.h"
 
 /* ----------------------------------------------------------------
  *					macros used in index_ routines
@@ -135,6 +136,8 @@ index_open(Oid relationId)
 	if (r->rd_rel->relkind != RELKIND_INDEX)
 		elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
 
+	pgstat_initstats(&r->pgstat_info, r);
+
 	return r;
 }
 
@@ -157,6 +160,8 @@ index_openr(char *relationName)
 	if (r->rd_rel->relkind != RELKIND_INDEX)
 		elog(ERROR, "%s is not an index relation", RelationGetRelationName(r));
 
+	pgstat_initstats(&r->pgstat_info, r);
+
 	return r;
 }
 
@@ -256,6 +261,8 @@ index_beginscan(Relation relation,
 										 UInt16GetDatum(numberOfKeys),
 										 PointerGetDatum(key)));
 
+	pgstat_initstats(&scan->xs_pgstat_info, relation);
+
 	/*
 	 * We want to look up the amgettuple procedure just once per scan,
 	 * not once per index_getnext call.  So do it here and save
@@ -283,6 +290,8 @@ index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key)
 					 PointerGetDatum(scan),
 					 BoolGetDatum(scanFromEnd),
 					 PointerGetDatum(key));
+
+	pgstat_reset_index_scan(&scan->xs_pgstat_info);
 }
 
 /* ----------------
@@ -353,6 +362,8 @@ index_getnext(IndexScanDesc scan,
 
 	SCAN_CHECKS;
 
+	pgstat_count_index_scan(&scan->xs_pgstat_info);
+
 	/*
 	 * have the am's gettuple proc do all the work.
 	 * index_beginscan already set up fn_getnext.
@@ -362,6 +373,8 @@ index_getnext(IndexScanDesc scan,
 									  PointerGetDatum(scan),
 									  Int32GetDatum(direction)));
 
+	if (result != NULL)
+		pgstat_count_index_getnext(&scan->xs_pgstat_info);
 	return result;
 }
 
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index f2112de6777d72b1714789ef059ee03f9e953a58..8ffb9b9043cd5126a228f14029decd802c43e466 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.82 2001/03/22 03:59:14 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.83 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -209,7 +209,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
 			if (chtup)
 			{
 				htup.t_self = btitem->bti_itup.t_tid;
-				heap_fetch(heapRel, SnapshotDirty, &htup, &buffer);
+				heap_fetch(heapRel, SnapshotDirty, &htup, &buffer, NULL);
 				if (htup.t_data == NULL)		/* YES! */
 					break;
 				/* Live tuple is being inserted, so continue checking */
@@ -219,7 +219,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
 
 			cbti = (BTItem) PageGetItem(page, PageGetItemId(page, offset));
 			htup.t_self = cbti->bti_itup.t_tid;
-			heap_fetch(heapRel, SnapshotDirty, &htup, &buffer);
+			heap_fetch(heapRel, SnapshotDirty, &htup, &buffer, NULL);
 			if (htup.t_data != NULL)	/* it is a duplicate */
 			{
 				TransactionId xwait =
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 9e048deba6b16186783f868f2234744fba56421c..293980ea5116b68328708b8b8284ea35fd3dc48d 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.103 2001/06/19 19:42:15 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.104 2001/06/22 19:16:21 wieck Exp $
  *
  * NOTES
  *		Transaction aborts can now occur two ways:
@@ -176,6 +176,8 @@
 #include "utils/relcache.h"
 #include "utils/temprel.h"
 
+#include "pgstat.h"
+
 extern bool SharedBufferChanged;
 
 static void AbortTransaction(void);
@@ -1083,6 +1085,9 @@ CommitTransaction(void)
 
 	SharedBufferChanged = false;/* safest place to do it */
 
+	/* Count transaction commit in statistics collector */
+	pgstat_count_xact_commit();
+
 	/*
 	 * done with commit processing, set current transaction state back to
 	 * default
@@ -1163,6 +1168,9 @@ AbortTransaction(void)
 	AtEOXact_portals();
 	RecordTransactionAbort();
 
+	/* Count transaction abort in statistics collector */
+	pgstat_count_xact_rollback();
+
 	RelationPurgeLocalRelation(false);
 	AtEOXact_temp_relations(false);
 	smgrDoPendingDeletes(false);
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 96d3085f7a63746a37102de80944315f7905534d..477c3bac89b794531da273a13f693d77e1461223 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.79 2001/06/16 18:59:31 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.80 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -206,7 +206,7 @@ CatalogIndexFetchTuple(Relation heapRelation,
 	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
 	{
 		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(heapRelation, SnapshotNow, &tuple, &buffer);
+		heap_fetch(heapRelation, SnapshotNow, &tuple, &buffer, sd);
 		pfree(indexRes);
 		if (tuple.t_data != NULL)
 			break;
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
index 2becb34929ffed59ed899acbba69ab69417bbd3c..2ba46238a47f715eb5d136395aaeadeb5bf9bc83 100644
--- a/src/backend/catalog/pg_largeobject.c
+++ b/src/backend/catalog/pg_largeobject.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.8 2001/03/22 03:59:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.9 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,7 +114,7 @@ LargeObjectDrop(Oid loid)
 	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
 	{
 		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer);
+		heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer, sd);
 		pfree(indexRes);
 		if (tuple.t_data != NULL)
 		{
@@ -165,7 +165,7 @@ LargeObjectExists(Oid loid)
 	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
 	{
 		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer);
+		heap_fetch(pg_largeobject, SnapshotNow, &tuple, &buffer, sd);
 		pfree(indexRes);
 		if (tuple.t_data != NULL)
 		{
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index c650ff88a1a27dad25b955b03064aad24b09aae9..08a4f656ff6654db9aade5ba59c395366613f0b3 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.20 2001/06/13 21:44:40 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.21 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -609,7 +609,7 @@ acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
 				goto pageloop;
 			}
 			ItemPointerSet(&targtuple.t_self, targblock, targoffset);
-			heap_fetch(onerel, SnapshotNow, &targtuple, &targbuffer);
+			heap_fetch(onerel, SnapshotNow, &targtuple, &targbuffer, NULL);
 			if (targtuple.t_data != NULL)
 			{
 				/*
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 826407c8eb6c8c83a4bb78dd3a53f4343775e26a..a087012a515dad796f3d1a8fe2599363c7eb4dd1 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.65 2001/03/22 03:59:21 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.66 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -264,7 +264,8 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
 		LocalHeapTuple.t_self = ScanResult->heap_iptr;
 		LocalHeapTuple.t_datamcxt = NULL;
 		LocalHeapTuple.t_data = NULL;
-		heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer);
+		heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer,
+						ScanDesc);
 		if (LocalHeapTuple.t_data != NULL)
 		{
 
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 013221860a2a289cf38e09b9289e99c4247f1974..c6e15fa7af8f19550e3d98bb450a2d62470fa1bb 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.92 2001/06/01 02:41:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.93 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -551,7 +551,7 @@ RelationBuildTriggers(Relation relation)
 				break;
 
 			tuple.t_self = indexRes->heap_iptr;
-			heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
+			heap_fetch(tgrel, SnapshotNow, &tuple, &buffer, sd);
 			pfree(indexRes);
 			if (!tuple.t_data)
 				continue;
@@ -1394,7 +1394,7 @@ DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
 	if (ItemPointerIsValid(&(event->dte_oldctid)))
 	{
 		ItemPointerCopy(&(event->dte_oldctid), &(oldtuple.t_self));
-		heap_fetch(rel, SnapshotAny, &oldtuple, &oldbuffer);
+		heap_fetch(rel, SnapshotAny, &oldtuple, &oldbuffer, NULL);
 		if (!oldtuple.t_data)
 			elog(ERROR, "DeferredTriggerExecute: failed to fetch old tuple");
 	}
@@ -1402,7 +1402,7 @@ DeferredTriggerExecute(DeferredTriggerEvent event, int itemno,
 	if (ItemPointerIsValid(&(event->dte_newctid)))
 	{
 		ItemPointerCopy(&(event->dte_newctid), &(newtuple.t_self));
-		heap_fetch(rel, SnapshotAny, &newtuple, &newbuffer);
+		heap_fetch(rel, SnapshotAny, &newtuple, &newbuffer, NULL);
 		if (!newtuple.t_data)
 			elog(ERROR, "DeferredTriggerExecute: failed to fetch new tuple");
 	}
@@ -1861,7 +1861,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 					break;
 
 				tuple.t_self = indexRes->heap_iptr;
-				heap_fetch(tgrel, SnapshotNow, &tuple, &buffer);
+				heap_fetch(tgrel, SnapshotNow, &tuple, &buffer, sd);
 				pfree(indexRes);
 				if (!tuple.t_data)
 					continue;
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33d5409364ac9166376c83d4c0867f9ba17aca47..c77b2fe8b9061c4488a37044a1303c19202ab561 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.196 2001/06/13 21:44:40 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.197 2001/06/22 19:16:21 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,8 @@
 #include "utils/syscache.h"
 #include "utils/temprel.h"
 
+#include "pgstat.h"
+
 extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
 			   char *unused, int unlen);
 extern XLogRecPtr log_heap_move(Relation reln,
@@ -185,6 +187,11 @@ vacuum(VacuumStmt *vacstmt)
 	if (IsTransactionBlock())
 		elog(ERROR, "%s cannot run inside a BEGIN/END block", stmttype);
 
+	/*
+	 * Send info about dead objects to the statistics collector
+	 */
+	pgstat_vacuum_tabstat();
+
 	if (vacstmt->verbose)
 		MESSAGE_LEVEL = NOTICE;
 	else
@@ -2350,7 +2357,7 @@ vac_update_relstats(Oid relid, long num_pages, double num_tuples,
 	/* get the buffer cache tuple */
 	rtup.t_self = ctup->t_self;
 	ReleaseSysCache(ctup);
-	heap_fetch(rd, SnapshotNow, &rtup, &buffer);
+	heap_fetch(rd, SnapshotNow, &rtup, &buffer, NULL);
 
 	/* overwrite the existing statistics in the tuple */
 	pgcform = (Form_pg_class) GETSTRUCT(&rtup);
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 38c34f03be72c952fa24e7e541be2735da6b2a9a..21342453e1bc5006f49918f2c3094941ab5d634c 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.143 2001/06/01 02:41:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.144 2001/06/22 19:16:22 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1671,7 +1671,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
 	{
 		Buffer		buffer;
 
-		heap_fetch(relation, SnapshotDirty, &tuple, &buffer);
+		heap_fetch(relation, SnapshotDirty, &tuple, &buffer, NULL);
 		if (tuple.t_data != NULL)
 		{
 			TransactionId xwait = SnapshotDirty->xmax;
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 5b8e2d16f0f2433f22b5a6500fd3ffae6108ebce..bd118b876b04cc524d6c9ae453594bf703513a80 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.60 2001/05/27 20:42:18 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.61 2001/06/22 19:16:22 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -173,7 +173,7 @@ IndexNext(IndexScan *node)
 		while ((result = index_getnext(scandesc, direction)) != NULL)
 		{
 			tuple->t_self = result->heap_iptr;
-			heap_fetch(heapRelation, snapshot, tuple, &buffer);
+			heap_fetch(heapRelation, snapshot, tuple, &buffer, scandesc);
 			pfree(result);
 
 			if (tuple->t_data != NULL)
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 0485946938ee4e057e6745d4d113ec293a8bb5a9..29ad660800c7283861381527ceadde51dfe9aa1e 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.17 2001/05/27 20:42:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.18 2001/06/22 19:16:22 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -152,7 +152,7 @@ TidNext(TidScan *node)
 		if (itemptr)
 		{
 			tuple->t_self = *(itemptr);
-			heap_fetch(heapRelation, snapshot, tuple, &buffer);
+			heap_fetch(heapRelation, snapshot, tuple, &buffer, NULL);
 		}
 		if (tuple->t_data != NULL)
 		{
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index ef2adde5cc4024ca0271abd0d754caa4bee8e6ce..120131167599352ff2604731ed0b149a3eee5617 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.108 2001/05/19 01:57:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.109 2001/06/22 19:16:22 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -752,7 +752,7 @@ func_get_candidates(char *funcname, int nargs)
 			tuple.t_datamcxt = NULL;
 			tuple.t_data = NULL;
 			tuple.t_self = indexRes->heap_iptr;
-			heap_fetch(heapRelation, SnapshotNow, &tuple, &buffer);
+			heap_fetch(heapRelation, SnapshotNow, &tuple, &buffer, sd);
 			pfree(indexRes);
 			if (tuple.t_data != NULL)
 			{
diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile
index da9f0d9be3a28f6c902b84053d68bfa9dddd4998..72d46c1b6fe7748e10e5ad8b6bc7093ef106c449 100644
--- a/src/backend/postmaster/Makefile
+++ b/src/backend/postmaster/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for postmaster
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/postmaster/Makefile,v 1.12 2000/08/31 16:10:23 petere Exp $
+#    $Header: /cvsroot/pgsql/src/backend/postmaster/Makefile,v 1.13 2001/06/22 19:16:22 wieck Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/postmaster
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = postmaster.o
+OBJS = postmaster.o pgstat.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 93e225ab4f164f398f6a95fdc696433ab227fbaf..abc5c5ee9952a3817c7d03f6c2ea1c6bfc371e5d 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.225 2001/06/21 16:43:24 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.226 2001/06/22 19:16:22 wieck Exp $
  *
  * NOTES
  *
@@ -105,6 +105,8 @@
 #include "utils/memutils.h"
 #include "bootstrap/bootstrap.h"
 
+#include "pgstat.h"
+
 #define INVALID_SOCK	(-1)
 #define ARGV_SIZE	64
 
@@ -573,6 +575,14 @@ PostmasterMain(int argc, char *argv[])
 		ExitPostmaster(1);
 	}
 
+	/*
+	 * Initialize and startup the statistics collector process
+	 */
+	if (pgstat_init() < 0)
+		ExitPostmaster(1);
+	if (pgstat_start() < 0)
+		ExitPostmaster(1);
+
 	if (DebugLvl > 2)
 	{
 		extern char **environ;
@@ -1465,6 +1475,18 @@ reaper(SIGNAL_ARGS)
 	{
 		exitstatus = status.w_status;
 #endif
+		/*
+		 * Check if this child was the statistics collector. If
+		 * so, start a new one. 
+		 */
+		if (pgstat_ispgstat(pid))
+		{
+			fprintf(stderr, "%s: Performance collector exited with status %d\n",
+					progname, exitstatus);
+			pgstat_start();
+			continue;
+		}
+
 		if (ShutdownPID > 0)
 		{
 			if (pid != ShutdownPID)
@@ -1511,6 +1533,7 @@ reaper(SIGNAL_ARGS)
 			errno = save_errno;
 			return;
 		}
+
 		CleanupProc(pid, exitstatus);
 	}
 
@@ -1609,6 +1632,8 @@ CleanupProc(int pid,
 				GetRedoRecPtr();
 			}
 		}
+		else
+			pgstat_beterm(pid);
 
 		return;
 	}
@@ -1665,6 +1690,13 @@ CleanupProc(int pid,
 		CheckPointPID = 0;
 		checkpointed = 0;
 	}
+	else
+	{
+		/*
+		 * Tell the collector about backend termination
+		 */
+		pgstat_beterm(pid);
+	}
 
 	FatalError = true;
 }
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 06abd2e8675da388c867c6b6e7c93b9c9fbd9dd6..8970c907a8bf903c46ceb83c9650b76ca06f6013 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.112 2001/06/09 18:16:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.113 2001/06/22 19:16:22 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,6 +55,8 @@
 #include "utils/relcache.h"
 #include "catalog/pg_database.h"
 
+#include "pgstat.h"
+
 #define BufferGetLSN(bufHdr)	\
 	(*((XLogRecPtr*)MAKE_PTR((bufHdr)->data)))
 
@@ -147,6 +149,7 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
 	if (isLocalBuf)
 	{
 		ReadLocalBufferCount++;
+		pgstat_count_buffer_read(&reln->pgstat_info, reln);
 		/* Substitute proper block number if caller asked for P_NEW */
 		if (blockNum == P_NEW)
 		{
@@ -156,11 +159,15 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
 		}
 		bufHdr = LocalBufferAlloc(reln, blockNum, &found);
 		if (found)
+		{
 			LocalBufferHitCount++;
+			pgstat_count_buffer_hit(&reln->pgstat_info, reln);
+		}
 	}
 	else
 	{
 		ReadBufferCount++;
+		pgstat_count_buffer_read(&reln->pgstat_info, reln);
 		/* Substitute proper block number if caller asked for P_NEW */
 		if (blockNum == P_NEW)
 		{
@@ -175,7 +182,10 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
 			SpinAcquire(BufMgrLock);
 		bufHdr = BufferAlloc(reln, blockNum, &found);
 		if (found)
+		{
 			BufferHitCount++;
+			pgstat_count_buffer_hit(&reln->pgstat_info, reln);
+		}
 	}
 
 	/* At this point we do NOT hold the bufmgr spinlock. */
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 6f20449d1f118affd545201207d04136039a0804..02b22f618caf52c7880f36059c9cf378fb8e008f 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.87 2001/03/25 23:23:59 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.88 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -227,7 +227,7 @@ inv_getsize(LargeObjectDesc *obj_desc)
 	while ((indexRes = index_getnext(sd, BackwardScanDirection)))
 	{
 		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(obj_desc->heap_r, SnapshotNow, &tuple, &buffer);
+		heap_fetch(obj_desc->heap_r, SnapshotNow, &tuple, &buffer, sd);
 		pfree(indexRes);
 		if (tuple.t_data == NULL)
 			continue;
@@ -339,7 +339,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
 	{
 		tuple.t_self = indexRes->heap_iptr;
-		heap_fetch(obj_desc->heap_r, SnapshotNow, &tuple, &buffer);
+		heap_fetch(obj_desc->heap_r, SnapshotNow, &tuple, &buffer, sd);
 		pfree(indexRes);
 
 		if (tuple.t_data == NULL)
@@ -473,7 +473,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 			while ((indexRes = index_getnext(sd, ForwardScanDirection)))
 			{
 				oldtuple.t_self = indexRes->heap_iptr;
-				heap_fetch(obj_desc->heap_r, SnapshotNow, &oldtuple, &buffer);
+				heap_fetch(obj_desc->heap_r, SnapshotNow, &oldtuple, &buffer, sd);
 				pfree(indexRes);
 				if (oldtuple.t_data != NULL)
 				{
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 476c2f72c3ae5df777a7440f7d8f56527878e052..e75e66b6d10d48c8f7844b299878e3a166b68694 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.223 2001/06/20 18:07:55 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.224 2001/06/22 19:16:23 wieck Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -66,6 +66,7 @@
 #include "mb/pg_wchar.h"
 #endif
 
+#include "pgstat.h"
 
 /* ----------------
  *		global variables
@@ -1710,7 +1711,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.223 $ $Date: 2001/06/20 18:07:55 $\n");
+		puts("$Revision: 1.224 $ $Date: 2001/06/22 19:16:23 $\n");
 	}
 
 	/*
@@ -1727,6 +1728,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 										 ALLOCSET_DEFAULT_INITSIZE,
 										 ALLOCSET_DEFAULT_MAXSIZE);
 
+	/* ----------
+	 * Tell the statistics collector that we're alive and
+	 * to which database we belong.
+	 * ----------
+	 */
+	pgstat_bestart();
+
 	/*
 	 * POSTGRES main processing loop begins here
 	 *
@@ -1812,10 +1820,23 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 		 */
 		ReadyForQuery(whereToSendOutput);
 
+		/* ----------
+		 * Tell the statistics collector what we've collected
+		 * so far.
+		 * ----------
+		 */
+		pgstat_report_tabstat();
+
 		if (IsTransactionBlock())
+		{
 			set_ps_display("idle in transaction");
+			pgstat_report_activity("<IDLE> in transaction");
+		}
 		else
+		{
 			set_ps_display("idle");
+			pgstat_report_activity("<IDLE>");
+		}
 
 		/*
 		 * (2) deal with pending asynchronous NOTIFY from other backends,
@@ -1866,6 +1887,12 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 				 * 'F' indicates a fastpath call.
 				 */
 			case 'F':
+				/* ----------
+				 * Tell the collector what we're doing
+				 * ----------
+				 */
+				pgstat_report_activity("<FASTPATH> function call");
+
 				/* start an xact for this function invocation */
 				start_xact_command();
 
@@ -1906,6 +1933,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
 					if (Show_query_stats)
 						ResetUsage();
 
+					pgstat_report_activity(parser_input->data);
+
 					pg_exec_query_string(parser_input->data,
 										 whereToSendOutput,
 										 QueryContext);
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index 75ba6448beb1f69873fd26be8ad1662ea564e350..0f8bdfe0b2454d518bac7fc431dd1b99dc0c14e5 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for utils/adt
 #
-# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.48 2000/10/20 21:03:52 petere Exp $
+# $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.49 2001/06/22 19:16:23 wieck Exp $
 #
 
 subdir = src/backend/utils/adt
@@ -24,7 +24,7 @@ OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o \
 	tid.o timestamp.o varbit.o varchar.o varlena.o version.o \
 	network.o mac.o inet_net_ntop.o inet_net_pton.o \
 	ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
-	ascii.o quote.o
+	ascii.o quote.o pgstatfuncs.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 1f3abde5f119ab8183165ec197ddc1f47a26d25d..eb6ab3f46469bba237fcc47ece54cf32ad75df24 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.61 2001/03/22 03:59:53 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.62 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,7 +90,8 @@ regprocin(PG_FUNCTION_ARGS)
 				tuple.t_self = indexRes->heap_iptr;
 				heap_fetch(hdesc, SnapshotNow,
 						   &tuple,
-						   &buffer);
+						   &buffer,
+						   sd);
 				pfree(indexRes);
 				if (tuple.t_data != NULL)
 				{
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index d6901ea839177f58893116be667b6c7008b8c2b8..f5f16e771881929a8b0fb6b257b596b751dbcf4f 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.80 2001/06/19 19:42:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.81 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -980,7 +980,7 @@ SearchCatCache(CatCache *cache,
 		while ((indexRes = index_getnext(isd, ForwardScanDirection)))
 		{
 			tuple.t_self = indexRes->heap_iptr;
-			heap_fetch(relation, SnapshotNow, &tuple, &buffer);
+			heap_fetch(relation, SnapshotNow, &tuple, &buffer, isd);
 			pfree(indexRes);
 			if (tuple.t_data != NULL)
 			{
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d44c3dc2340e3eb9d5c67fb39f96a576392cf697..7b90122b9f20989122f97d5c9973c1a58ce6cb4b 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.138 2001/06/18 03:35:07 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.139 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2257,7 +2257,7 @@ AttrDefaultFetch(Relation relation)
 				break;
 
 			tuple.t_self = indexRes->heap_iptr;
-			heap_fetch(adrel, SnapshotNow, &tuple, &buffer);
+			heap_fetch(adrel, SnapshotNow, &tuple, &buffer, sd);
 			pfree(indexRes);
 			if (tuple.t_data == NULL)
 				continue;
@@ -2364,7 +2364,7 @@ RelCheckFetch(Relation relation)
 				break;
 
 			tuple.t_self = indexRes->heap_iptr;
-			heap_fetch(rcrel, SnapshotNow, &tuple, &buffer);
+			heap_fetch(rcrel, SnapshotNow, &tuple, &buffer, sd);
 			pfree(indexRes);
 			if (tuple.t_data == NULL)
 				continue;
@@ -2502,7 +2502,7 @@ RelationGetIndexList(Relation relation)
 			tuple.t_self = indexRes->heap_iptr;
 			tuple.t_datamcxt = NULL;
 			tuple.t_data = NULL;
-			heap_fetch(indrel, SnapshotNow, &tuple, &buffer);
+			heap_fetch(indrel, SnapshotNow, &tuple, &buffer, sd);
 			pfree(indexRes);
 			if (tuple.t_data == NULL)
 				continue;
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index b3a991fdc5253f47053480ee3e08cf906d27c3d0..fd9b11ba98e52be57c435482f2585c1be1fbbca9 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.35 2001/03/22 03:59:59 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/hash/dynahash.c,v 1.36 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -82,18 +82,13 @@ static int	init_htab(HTAB *hashp, int nelem);
  * ----------------
  */
 static MemoryContext DynaHashCxt = NULL;
+static MemoryContext CurrentDynaHashCxt = NULL;
 
 static void *
 DynaHashAlloc(Size size)
 {
-	if (!DynaHashCxt)
-		DynaHashCxt = AllocSetContextCreate(TopMemoryContext,
-											"DynaHash",
-											ALLOCSET_DEFAULT_MINSIZE,
-											ALLOCSET_DEFAULT_INITSIZE,
-											ALLOCSET_DEFAULT_MAXSIZE);
-
-	return MemoryContextAlloc(DynaHashCxt, size);
+	Assert(MemoryContextIsValid(CurrentDynaHashCxt));
+	return MemoryContextAlloc(CurrentDynaHashCxt, size);
 }
 
 #define MEM_ALLOC		DynaHashAlloc
@@ -133,6 +128,17 @@ hash_create(int nelem, HASHCTL *info, int flags)
 	HHDR	   *hctl;
 	HTAB	   *hashp;
 
+	if (!DynaHashCxt)
+		DynaHashCxt = AllocSetContextCreate(TopMemoryContext,
+											"DynaHash",
+											ALLOCSET_DEFAULT_MINSIZE,
+											ALLOCSET_DEFAULT_INITSIZE,
+											ALLOCSET_DEFAULT_MAXSIZE);
+
+	if (flags & HASH_CONTEXT)
+		CurrentDynaHashCxt = info->hcxt;
+	else
+		CurrentDynaHashCxt = DynaHashCxt;
 
 	hashp = (HTAB *) MEM_ALLOC(sizeof(HTAB));
 	MemSet(hashp, 0, sizeof(HTAB));
@@ -157,6 +163,7 @@ hash_create(int nelem, HASHCTL *info, int flags)
 		hashp->segbase = (char *) info->segbase;
 		hashp->alloc = info->alloc;
 		hashp->dir = (SEG_OFFSET *) info->dir;
+		hashp->hcxt = NULL;
 
 		/* hash table already exists, we're just attaching to it */
 		if (flags & HASH_ATTACH)
@@ -171,12 +178,13 @@ hash_create(int nelem, HASHCTL *info, int flags)
 		hashp->alloc = MEM_ALLOC;
 		hashp->dir = NULL;
 		hashp->segbase = NULL;
+		hashp->hcxt = DynaHashCxt;
 
 	}
 
 	if (!hashp->hctl)
 	{
-		hashp->hctl = (HHDR *) hashp->alloc(sizeof(HHDR));
+			hashp->hctl = (HHDR *) hashp->alloc(sizeof(HHDR));
 		if (!hashp->hctl)
 			return 0;
 	}
@@ -218,6 +226,28 @@ hash_create(int nelem, HASHCTL *info, int flags)
 	}
 	if (flags & HASH_ALLOC)
 		hashp->alloc = info->alloc;
+	else
+	{
+		if (flags & HASH_CONTEXT)
+		{
+			CurrentDynaHashCxt = AllocSetContextCreate(info->hcxt,
+											"DynaHashTable",
+											ALLOCSET_DEFAULT_MINSIZE,
+											ALLOCSET_DEFAULT_INITSIZE,
+											ALLOCSET_DEFAULT_MAXSIZE);
+			
+			hashp->hcxt = CurrentDynaHashCxt;
+		}
+		else
+		{
+			CurrentDynaHashCxt = AllocSetContextCreate(DynaHashCxt,
+											"DynaHashTable",
+											ALLOCSET_DEFAULT_MINSIZE,
+											ALLOCSET_DEFAULT_INITSIZE,
+											ALLOCSET_DEFAULT_MAXSIZE);
+			hashp->hcxt = CurrentDynaHashCxt;
+		}
+	}
 
 	if (init_htab(hashp, nelem))
 	{
@@ -305,6 +335,7 @@ init_htab(HTAB *hashp, int nelem)
 	/* Allocate a directory */
 	if (!(hashp->dir))
 	{
+		CurrentDynaHashCxt = hashp->hcxt;
 		hashp->dir = (SEG_OFFSET *)
 			hashp->alloc(hctl->dsize * sizeof(SEG_OFFSET));
 		if (!hashp->dir)
@@ -414,6 +445,14 @@ hash_select_dirsize(long num_entries)
  * allocated individually, see bucket_alloc!!  Why doesn't it crash?
  * ANSWER: it probably does crash, but is never invoked in normal
  * operations...
+ *
+ * Thomas is right, it does crash. Therefore I changed the code
+ * to use a separate memory context which is a child of the DynaHashCxt
+ * by default. And the HASHCTL structure got extended with a hcxt
+ * field, where someone can specify an explicit context (giving new
+ * flag HASH_CONTEXT) and forget about hash_destroy() completely.
+ * The shmem operations aren't changed, but in shmem mode a destroy
+ * doesn't work anyway. Jan Wieck 03/2001.
  */
 
 void
@@ -421,6 +460,7 @@ hash_destroy(HTAB *hashp)
 {
 	if (hashp != NULL)
 	{
+#if 0
 		SEG_OFFSET	segNum;
 		SEGMENT		segp;
 		int			nsegs = hashp->hctl->nsegs;
@@ -429,14 +469,27 @@ hash_destroy(HTAB *hashp)
 					p,
 					q;
 		ELEMENT    *curr;
+#endif
 
 		/* cannot destroy a shared memory hash table */
 		Assert(!hashp->segbase);
 		/* allocation method must be one we know how to free, too */
 		Assert(hashp->alloc == MEM_ALLOC);
+		/* so this hashtable must have it's own context */
+		Assert(hashp->hcxt != NULL);
 
 		hash_stats("destroy", hashp);
 
+		/*
+		 * Free buckets, dir etc. by destroying the hash tables
+		 * memory context.
+		 */
+		MemoryContextDelete(hashp->hcxt);
+
+#if 0
+		/*
+		 * Dead code - replaced by MemoryContextDelete() above
+		 */
 		for (segNum = 0; nsegs > 0; nsegs--, segNum++)
 		{
 
@@ -453,6 +506,13 @@ hash_destroy(HTAB *hashp)
 			MEM_FREE((char *) segp);
 		}
 		MEM_FREE((char *) hashp->dir);
+#endif
+
+		/*
+		 * Free the HTAB and control structure, which are allocated
+		 * in the parent context (DynaHashCxt or the context given
+		 * by the caller of hash_create().
+		 */
 		MEM_FREE((char *) hashp->hctl);
 		MEM_FREE((char *) hashp);
 	}
@@ -876,6 +936,7 @@ dir_realloc(HTAB *hashp)
 	old_dirsize = hashp->hctl->dsize * sizeof(SEG_OFFSET);
 	new_dirsize = new_dsize * sizeof(SEG_OFFSET);
 
+	CurrentDynaHashCxt = hashp->hcxt;
 	old_p = (char *) hashp->dir;
 	p = (char *) hashp->alloc((Size) new_dirsize);
 
@@ -898,6 +959,7 @@ seg_alloc(HTAB *hashp)
 	SEGMENT		segp;
 	SEG_OFFSET	segOffset;
 
+	CurrentDynaHashCxt = hashp->hcxt;
 	segp = (SEGMENT) hashp->alloc(sizeof(BUCKET_INDEX) * hashp->hctl->ssize);
 
 	if (!segp)
@@ -928,6 +990,7 @@ bucket_alloc(HTAB *hashp)
 	/* make sure its aligned correctly */
 	bucketSize = MAXALIGN(bucketSize);
 
+	CurrentDynaHashCxt = hashp->hcxt;
 	tmpBucket = (ELEMENT *) hashp->alloc(BUCKET_ALLOC_INCR * bucketSize);
 
 	if (!tmpBucket)
diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh
index b5c2a0004ee114c5f6402b6bc0b4ff72d2cf0cf4..ffb2dc50e081123f77e2266074a9808580ee7ad3 100644
--- a/src/bin/initdb/initdb.sh
+++ b/src/bin/initdb/initdb.sh
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.127 2001/06/14 19:47:25 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.128 2001/06/22 19:16:23 wieck Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -642,6 +642,170 @@ echo "CREATE VIEW pg_stats AS \
 echo "REVOKE ALL on pg_statistic FROM public" \
 	| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
 
+echo "CREATE VIEW pg_stat_all_tables AS \
+		SELECT \
+			C.oid AS relid, \
+			C.relname AS relname, \
+			pg_stat_get_numscans(C.oid) AS seq_scan, \
+			pg_stat_get_tuples_returned(C.oid) AS seq_tup_read, \
+			sum(pg_stat_get_numscans(I.indexrelid)) AS idx_scan, \
+			sum(pg_stat_get_tuples_fetched(I.indexrelid)) AS idx_tup_fetch, \
+			pg_stat_get_tuples_inserted(C.oid) AS n_tup_ins, \
+			pg_stat_get_tuples_updated(C.oid) AS n_tup_upd, \
+			pg_stat_get_tuples_deleted(C.oid) AS n_tup_del \
+		FROM pg_class C FULL OUTER JOIN \
+		     pg_index I ON C.oid = I.indrelid \
+		WHERE C.relkind = 'r' \
+		GROUP BY C.oid, C.relname;" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_sys_tables AS \
+		SELECT * FROM pg_stat_all_tables \
+		WHERE relname ~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_user_tables AS \
+		SELECT * FROM pg_stat_all_tables \
+		WHERE relname !~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_all_tables AS \
+		SELECT \
+			C.oid AS relid, \
+			C.relname AS relname, \
+			pg_stat_get_blocks_fetched(C.oid) - \
+				pg_stat_get_blocks_hit(C.oid) AS heap_blks_read, \
+			pg_stat_get_blocks_hit(C.oid) AS heap_blks_hit, \
+			sum(pg_stat_get_blocks_fetched(I.indexrelid) - \
+				pg_stat_get_blocks_hit(I.indexrelid)) AS idx_blks_read, \
+			sum(pg_stat_get_blocks_hit(I.indexrelid)) AS idx_blks_hit, \
+			pg_stat_get_blocks_fetched(T.oid) - \
+				pg_stat_get_blocks_hit(T.oid) AS toast_blks_read, \
+			pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit, \
+			pg_stat_get_blocks_fetched(X.oid) - \
+				pg_stat_get_blocks_hit(X.oid) AS tidx_blks_read, \
+			pg_stat_get_blocks_hit(X.oid) AS tidx_blks_hit \
+		FROM pg_class C FULL OUTER JOIN \
+			pg_index I ON C.oid = I.indrelid FULL OUTER JOIN \
+			pg_class T ON C.reltoastrelid = T.oid FULL OUTER JOIN \
+			pg_class X ON C.reltoastidxid = X.oid \
+		WHERE C.relkind = 'r' \
+		GROUP BY C.oid, C.relname, T.oid, X.oid;" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_sys_tables AS \
+		SELECT * FROM pg_statio_all_tables \
+		WHERE relname ~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_user_tables AS \
+		SELECT * FROM pg_statio_all_tables \
+		WHERE relname !~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_all_indexes AS \
+		SELECT \
+			C.oid AS relid, \
+			I.oid AS indexrelid, \
+			C.relname AS relname, \
+			I.relname AS indexrelname, \
+			pg_stat_get_numscans(I.oid) AS idx_scan, \
+			pg_stat_get_tuples_returned(I.oid) AS idx_tup_read, \
+			pg_stat_get_tuples_fetched(I.oid) AS idx_tup_fetch \
+		FROM pg_class C, \
+			pg_class I, \
+			pg_index X \
+		WHERE C.relkind = 'r' AND \
+			X.indrelid = C.oid AND \
+			X.indexrelid = I.oid;" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_sys_indexes AS \
+		SELECT * FROM pg_stat_all_indexes \
+		WHERE relname ~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_user_indexes AS \
+		SELECT * FROM pg_stat_all_indexes \
+		WHERE relname !~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_all_indexes AS \
+		SELECT \
+			C.oid AS relid, \
+			I.oid AS indexrelid, \
+			C.relname AS relname, \
+			I.relname AS indexrelname, \
+			pg_stat_get_blocks_fetched(I.oid) - \
+				pg_stat_get_blocks_hit(I.oid) AS idx_blks_read, \
+			pg_stat_get_blocks_hit(I.oid) AS idx_blks_hit \
+		FROM pg_class C, \
+			pg_class I, \
+			pg_index X \
+		WHERE C.relkind = 'r' AND \
+			X.indrelid = C.oid AND \
+			X.indexrelid = I.oid;" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_sys_indexes AS \
+		SELECT * FROM pg_statio_all_indexes \
+		WHERE relname ~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_user_indexes AS \
+		SELECT * FROM pg_statio_all_indexes \
+		WHERE relname !~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_all_sequences AS \
+		SELECT \
+			C.oid AS relid, \
+			C.relname AS relname, \
+			pg_stat_get_blocks_fetched(C.oid) - \
+				pg_stat_get_blocks_hit(C.oid) AS blks_read, \
+			pg_stat_get_blocks_hit(C.oid) AS blks_hit \
+		FROM pg_class C \
+		WHERE C.relkind = 'S';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_sys_sequences AS \
+		SELECT * FROM pg_statio_all_sequences \
+		WHERE relname ~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_statio_user_sequences AS \
+		SELECT * FROM pg_statio_all_sequences \
+		WHERE relname !~ '^pg_';" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_activity AS \
+		SELECT \
+			D.oid AS datid, \
+			D.datname AS datname, \
+			pg_stat_get_backend_pid(S.backendid) AS procpid, \
+			pg_stat_get_backend_userid(S.backendid) AS usesysid, \
+			U.usename AS usename, \
+			pg_stat_get_backend_activity(S.backendid) AS current_query \
+		FROM pg_database D, \
+			(SELECT pg_stat_get_backend_idset() AS backendid) AS S, \
+			pg_shadow U \
+		WHERE pg_stat_get_backend_dbid(S.backendid) = D.oid AND \
+			pg_stat_get_backend_userid(S.backendid) = U.usesysid;" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
+echo "CREATE VIEW pg_stat_database AS \
+		SELECT \
+			D.oid AS datid, \
+			D.datname AS datname, \
+			pg_stat_get_db_numbackends(D.oid) AS numbackends, \
+			pg_stat_get_db_xact_commit(D.oid) AS xact_commit, \
+			pg_stat_get_db_xact_rollback(D.oid) AS xact_rollback, \
+			pg_stat_get_db_blocks_fetched(D.oid) - \
+				pg_stat_get_db_blocks_hit(D.oid) AS blks_read, \
+			pg_stat_get_db_blocks_hit(D.oid) AS blks_hit \
+		FROM pg_database D;" \
+        | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
+
 echo "Loading pg_description."
 echo "COPY pg_description FROM STDIN" > $TEMPFILE
 cat "$POSTGRES_DESCR" >> $TEMPFILE
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9e2d1d427b74dacb5b2ca1cc5710d01bc2ab99e2..62b91e51623416d2788df6508b128559b0592e12 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.64 2001/06/12 05:55:50 tgl Exp $
+ * $Id: heapam.h,v 1.65 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,7 +202,7 @@ extern HeapScanDesc heap_beginscan(Relation relation, int atend,
 extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);
 extern void heap_endscan(HeapScanDesc scan);
 extern HeapTuple heap_getnext(HeapScanDesc scandesc, int backw);
-extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf);
+extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf, IndexScanDesc iscan);
 extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot, ItemPointer tid);
 extern Oid	heap_insert(Relation relation, HeapTuple tup);
 extern int	heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 8bfb514b1e445ed7af2e101390407f8ee2a21171..907ecee230d1fc383f371de9664330fe1891740c 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relscan.h,v 1.21 2001/06/09 18:16:59 tgl Exp $
+ * $Id: relscan.h,v 1.22 2001/06/22 19:16:23 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,8 @@ typedef struct HeapScanDescData
 	Snapshot	rs_snapshot;	/* snapshot to see */
 	uint16		rs_nkeys;		/* number of scan keys to select tuples */
 	ScanKey		rs_key;			/* key descriptors */
+
+	PgStat_Info rs_pgstat_info;	/* statistics collector hook */
 } HeapScanDescData;
 
 typedef HeapScanDescData *HeapScanDesc;
@@ -42,6 +44,8 @@ typedef struct IndexScanDescData
 	uint16		numberOfKeys;	/* number of scan keys to select tuples */
 	ScanKey		keyData;		/* key descriptors */
 	FmgrInfo	fn_getnext;		/* cached lookup info for am's getnext fn */
+
+	PgStat_Info xs_pgstat_info;	/* statistics collector hook */
 } IndexScanDescData;
 
 typedef IndexScanDescData *IndexScanDesc;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index c34655308e09e384e6facd7dabf70a835785b1a9..162bf4fe5f64e571f2b75be65db2033f5425f7ee 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.84 2001/06/19 22:39:12 tgl Exp $
+ * $Id: catversion.h,v 1.85 2001/06/22 19:16:24 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200106191
+#define CATALOG_VERSION_NO	200106221
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 415f3b0372cd2d2c6280ca0221597e017811494c..fdff7f7f176374c6a17c2e4bd7039ac2fb4c2467 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.194 2001/06/14 01:09:22 tgl Exp $
+ * $Id: pg_proc.h,v 1.195 2001/06/22 19:16:24 wieck Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -2647,6 +2647,43 @@ DATA(insert OID = 1927 (  has_table_privilege		   PGUID 12 f t f t 2 f 16 "26 25
 DESCR("current user privilege on relation by rel oid");
 
 
+DATA(insert OID = 1928 (  pg_stat_get_numscans			PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_numscans - ));
+DESCR("Statistics: Number of scans done for table/index");
+DATA(insert OID = 1929 (  pg_stat_get_tuples_returned	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_tuples_returned - ));
+DESCR("Statistics: Number of tuples read by seqscan");
+DATA(insert OID = 1930 (  pg_stat_get_tuples_fetched	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_tuples_fetched - ));
+DESCR("Statistics: Number of tuples fetched by idxscan");
+DATA(insert OID = 1931 (  pg_stat_get_tuples_inserted	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_tuples_inserted - ));
+DESCR("Statistics: Number of tuples inserted");
+DATA(insert OID = 1932 (  pg_stat_get_tuples_updated	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_tuples_updated - ));
+DESCR("Statistics: Number of tuples updated");
+DATA(insert OID = 1933 (  pg_stat_get_tuples_deleted	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_tuples_deleted - ));
+DESCR("Statistics: Number of tuples deleted");
+DATA(insert OID = 1934 (  pg_stat_get_blocks_fetched	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_blocks_fetched - ));
+DESCR("Statistics: Number of blocks fetched");
+DATA(insert OID = 1935 (  pg_stat_get_blocks_hit		PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_blocks_hit - ));
+DESCR("Statistics: Number of blocks found in cache");
+DATA(insert OID = 1936 (  pg_stat_get_backend_idset		PGUID 12 f t t t 0 t 23 "" 100 0 0 100	pg_stat_get_backend_idset - ));
+DESCR("Statistics: Currently active backend IDs");
+DATA(insert OID = 1937 (  pg_stat_get_backend_pid		PGUID 12 f t t t 1 f 23 "23" 100 0 0 100	pg_stat_get_backend_pid - ));
+DESCR("Statistics: PID of backend");
+DATA(insert OID = 1938 (  pg_stat_get_backend_dbid		PGUID 12 f t t t 1 f 26 "23" 100 0 0 100	pg_stat_get_backend_dbid - ));
+DESCR("Statistics: Database ID of backend");
+DATA(insert OID = 1939 (  pg_stat_get_backend_userid	PGUID 12 f t t t 1 f 26 "23" 100 0 0 100	pg_stat_get_backend_userid - ));
+DESCR("Statistics: User ID of backend");
+DATA(insert OID = 1940 (  pg_stat_get_backend_activity	PGUID 12 f t t t 1 f 25 "23" 100 0 0 100	pg_stat_get_backend_activity - ));
+DESCR("Statistics: Current query of backend");
+DATA(insert OID = 1941 (  pg_stat_get_db_numbackends	PGUID 12 f t t t 1 f 23 "26" 100 0 0 100	pg_stat_get_db_numbackends - ));
+DESCR("Statistics: Number of backends in database");
+DATA(insert OID = 1942 (  pg_stat_get_db_xact_commit	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_db_xact_commit - ));
+DESCR("Statistics: Transactions committed");
+DATA(insert OID = 1943 (  pg_stat_get_db_xact_rollback	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_db_xact_rollback - ));
+DESCR("Statistics: Transactions rolled back");
+DATA(insert OID = 1944 (  pg_stat_get_db_blocks_fetched	PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_db_blocks_fetched - ));
+DESCR("Statistics: Blocks fetched for database");
+DATA(insert OID = 1945 (  pg_stat_get_db_blocks_hit		PGUID 12 f t t t 1 f 20 "26" 100 0 0 100	pg_stat_get_db_blocks_hit - ));
+DESCR("Statistics: Block found in cache for database");
+
 /*
  * prototypes for functions pg_proc.c
  */
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index 9d47d73d3868387068e46fe4919e1f0b35541dc6..2f9d99e037447d2c257a9e84a45d8a3e98840580 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: hsearch.h,v 1.19 2001/03/22 04:01:12 momjian Exp $
+ * $Id: hsearch.h,v 1.20 2001/06/22 19:16:24 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,6 +85,7 @@ typedef struct htab
 								 * pointer values */
 	SEG_OFFSET *dir;			/* 'directory' of segm starts */
 	void	   *(*alloc) (Size);/* memory allocator */
+	MemoryContext hcxt;			/* memory context if default allocator used */
 } HTAB;
 
 typedef struct hashctl
@@ -102,6 +103,7 @@ typedef struct hashctl
 	long	   *dir;			/* directory if allocated already */
 	long	   *hctl;			/* location of header information in shd
 								 * mem */
+	MemoryContext hcxt;			/* memory context to use for all allocations */
 } HASHCTL;
 
 /* Flags to indicate action for hctl */
@@ -113,6 +115,7 @@ typedef struct hashctl
 #define HASH_SHARED_MEM 0x040	/* Setting shared mem const */
 #define HASH_ATTACH		0x080	/* Do not initialize hctl */
 #define HASH_ALLOC		0x100	/* Setting memory allocator */
+#define HASH_CONTEXT	0x200	/* Setting explicit memory context */
 
 
 /* seg_alloc assumes that INVALID_INDEX is 0 */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 5eae99578ee6a03b667d864b75a6a8aa0eb45f0f..c2a9d0982f7c1626fa6b7c362b6acc841a614f35 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rel.h,v 1.49 2001/06/19 21:28:41 tgl Exp $
+ * $Id: rel.h,v 1.50 2001/06/22 19:16:24 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,6 +85,19 @@ typedef struct TriggerDesc
 	int			numtriggers;
 } TriggerDesc;
 
+
+/* ----------
+ * Same for the statistics collector data in Relation and scan data.
+ * ----------
+ */
+typedef struct	PgStat_Info
+{
+	void			   *tabentry;
+	bool				no_stats;
+	bool				heap_scan_counted;
+	bool				index_scan_counted;
+} PgStat_Info;
+
 /*
  * Here are the contents of a relation cache entry.
  */
@@ -110,6 +123,8 @@ typedef struct RelationData
 	IndexStrategy rd_istrat;	/* info needed if rel is an index */
 	RegProcedure *rd_support;
 	TriggerDesc *trigdesc;		/* Trigger info, or NULL if rel has none */
+
+	PgStat_Info	pgstat_info;
 } RelationData;
 
 typedef RelationData *Relation;
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a651ef8327f882002a2aea81bffa7341ba211ee9..1c4fabd28bd7bd2d83fd7665dffbdec2ed83937f 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1264,30 +1264,47 @@ drop table cchild;
 -- Check that ruleutils are working
 --
 SELECT viewname, definition FROM pg_views ORDER BY viewname;
-      viewname      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- iexit              | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
- pg_indexes         | SELECT c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(x.indexrelid) AS indexdef FROM pg_index x, pg_class c, pg_class i WHERE ((((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")) AND (c.oid = x.indrelid)) AND (i.oid = x.indexrelid));
- pg_rules           | SELECT c.relname AS tablename, r.rulename, pg_get_ruledef(r.rulename) AS definition FROM pg_rewrite r, pg_class c WHERE ((r.rulename !~ '^_RET'::text) AND (c.oid = r.ev_class));
- pg_stats           | SELECT c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (1 = s.stakind1) THEN s.stavalues1 WHEN (1 = s.stakind2) THEN s.stavalues2 WHEN (1 = s.stakind3) THEN s.stavalues3 WHEN (1 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS most_common_vals, CASE WHEN (1 = s.stakind1) THEN s.stanumbers1 WHEN (1 = s.stakind2) THEN s.stanumbers2 WHEN (1 = s.stakind3) THEN s.stanumbers3 WHEN (1 = s.stakind4) THEN s.stanumbers4 ELSE NULL::"_float4" END AS most_common_freqs, CASE WHEN (2 = s.stakind1) THEN s.stavalues1 WHEN (2 = s.stakind2) THEN s.stavalues2 WHEN (2 = s.stakind3) THEN s.stavalues3 WHEN (2 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS histogram_bounds, CASE WHEN (3 = s.stakind1) THEN s.stanumbers1[1] WHEN (3 = s.stakind2) THEN s.stanumbers2[1] WHEN (3 = s.stakind3) THEN s.stanumbers3[1] WHEN (3 = s.stakind4) THEN s.stanumbers4[1] ELSE NULL::float4 END AS correlation FROM pg_class c, pg_attribute a, pg_statistic s WHERE ((((c.oid = s.starelid) AND (c.oid = a.attrelid)) AND (a.attnum = s.staattnum)) AND has_table_privilege(c.oid, 'select'::text));
- pg_tables          | SELECT c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM pg_class c WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 's'::"char"));
- pg_user            | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usetrace, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil FROM pg_shadow;
- pg_views           | SELECT c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.relname) AS definition FROM pg_class c WHERE (c.relkind = 'v'::"char");
- rtest_v1           | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1;
- rtest_vcomp        | SELECT x.part, (x.size * y.factor) AS size_in_cm FROM rtest_comp x, rtest_unitfact y WHERE (x.unit = y.unit);
- rtest_vview1       | SELECT x.a, x.b FROM rtest_view1 x WHERE (0 < (SELECT count(*) AS count FROM rtest_view2 y WHERE (y.a = x.a)));
- rtest_vview2       | SELECT rtest_view1.a, rtest_view1.b FROM rtest_view1 WHERE rtest_view1.v;
- rtest_vview3       | SELECT x.a, x.b FROM rtest_vview2 x WHERE (0 < (SELECT count(*) AS count FROM rtest_view2 y WHERE (y.a = x.a)));
- rtest_vview4       | SELECT x.a, x.b, count(y.a) AS refcount FROM rtest_view1 x, rtest_view2 y WHERE (x.a = y.a) GROUP BY x.a, x.b;
- rtest_vview5       | SELECT rtest_view1.a, rtest_view1.b, rtest_viewfunc1(rtest_view1.a) AS refcount FROM rtest_view1;
- shoe               | SELECT sh.shoename, sh.sh_avail, sh.slcolor, sh.slminlen, (sh.slminlen * un.un_fact) AS slminlen_cm, sh.slmaxlen, (sh.slmaxlen * un.un_fact) AS slmaxlen_cm, sh.slunit FROM shoe_data sh, unit un WHERE (sh.slunit = un.un_name);
- shoe_ready         | SELECT rsh.shoename, rsh.sh_avail, rsl.sl_name, rsl.sl_avail, int4smaller(rsh.sh_avail, rsl.sl_avail) AS total_avail FROM shoe rsh, shoelace rsl WHERE (((rsl.sl_color = rsh.slcolor) AND (rsl.sl_len_cm >= rsh.slminlen_cm)) AND (rsl.sl_len_cm <= rsh.slmaxlen_cm));
- shoelace           | SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit, (s.sl_len * u.un_fact) AS sl_len_cm FROM shoelace_data s, unit u WHERE (s.sl_unit = u.un_name);
- shoelace_candelete | SELECT shoelace_obsolete.sl_name, shoelace_obsolete.sl_avail, shoelace_obsolete.sl_color, shoelace_obsolete.sl_len, shoelace_obsolete.sl_unit, shoelace_obsolete.sl_len_cm FROM shoelace_obsolete WHERE (shoelace_obsolete.sl_avail = 0);
- shoelace_obsolete  | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color))));
- street             | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath);
- toyemp             | SELECT emp.name, emp.age, emp."location", (12 * emp.salary) AS annualsal FROM emp;
-(21 rows)
+         viewname         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ iexit                    | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
+ pg_indexes               | SELECT c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(x.indexrelid) AS indexdef FROM pg_index x, pg_class c, pg_class i WHERE ((((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")) AND (c.oid = x.indrelid)) AND (i.oid = x.indexrelid));
+ pg_rules                 | SELECT c.relname AS tablename, r.rulename, pg_get_ruledef(r.rulename) AS definition FROM pg_rewrite r, pg_class c WHERE ((r.rulename !~ '^_RET'::text) AND (c.oid = r.ev_class));
+ pg_stat_activity         | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));
+ pg_stat_all_indexes      | SELECT c.oid AS relid, i.oid AS indexrelid, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM pg_class c, pg_class i, pg_index x WHERE (((c.relkind = 'r'::"char") AND (x.indrelid = c.oid)) AND (x.indexrelid = i.oid));
+ pg_stat_all_tables       | SELECT c.oid AS relid, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, sum(pg_stat_get_numscans(i.indexrelid)) AS idx_scan, sum(pg_stat_get_tuples_fetched(i.indexrelid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del FROM (pg_class c FULL JOIN pg_index i ON ((c.oid = i.indrelid))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, c.relname;
+ pg_stat_database         | SELECT d.oid AS datid, d.datname, pg_stat_get_db_numbackends(d.oid) AS numbackends, pg_stat_get_db_xact_commit(d.oid) AS xact_commit, pg_stat_get_db_xact_rollback(d.oid) AS xact_rollback, (pg_stat_get_db_blocks_fetched(d.oid) - pg_stat_get_db_blocks_hit(d.oid)) AS blks_read, pg_stat_get_db_blocks_hit(d.oid) AS blks_hit FROM pg_database d;
+ pg_stat_sys_indexes      | SELECT pg_stat_all_indexes.relid, pg_stat_all_indexes.indexrelid, pg_stat_all_indexes.relname, pg_stat_all_indexes.indexrelname, pg_stat_all_indexes.idx_scan, pg_stat_all_indexes.idx_tup_read, pg_stat_all_indexes.idx_tup_fetch FROM pg_stat_all_indexes WHERE (pg_stat_all_indexes.relname ~ '^pg_'::text);
+ pg_stat_sys_tables       | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del FROM pg_stat_all_tables WHERE (pg_stat_all_tables.relname ~ '^pg_'::text);
+ pg_stat_user_indexes     | SELECT pg_stat_all_indexes.relid, pg_stat_all_indexes.indexrelid, pg_stat_all_indexes.relname, pg_stat_all_indexes.indexrelname, pg_stat_all_indexes.idx_scan, pg_stat_all_indexes.idx_tup_read, pg_stat_all_indexes.idx_tup_fetch FROM pg_stat_all_indexes WHERE (pg_stat_all_indexes.relname !~ '^pg_'::text);
+ pg_stat_user_tables      | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del FROM pg_stat_all_tables WHERE (pg_stat_all_tables.relname !~ '^pg_'::text);
+ pg_statio_all_indexes    | SELECT c.oid AS relid, i.oid AS indexrelid, c.relname, i.relname AS indexrelname, (pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid)) AS idx_blks_read, pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit FROM pg_class c, pg_class i, pg_index x WHERE (((c.relkind = 'r'::"char") AND (x.indrelid = c.oid)) AND (x.indexrelid = i.oid));
+ pg_statio_all_sequences  | SELECT c.oid AS relid, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS blks_read, pg_stat_get_blocks_hit(c.oid) AS blks_hit FROM pg_class c WHERE (c.relkind = 'S'::"char");
+ pg_statio_all_tables     | SELECT c.oid AS relid, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read, pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit, sum((pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid))) AS idx_blks_read, sum(pg_stat_get_blocks_hit(i.indexrelid)) AS idx_blks_hit, (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read, pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, (pg_stat_get_blocks_fetched(x.oid) - pg_stat_get_blocks_hit(x.oid)) AS tidx_blks_read, pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit FROM (((pg_class c FULL JOIN pg_index i ON ((c.oid = i.indrelid))) FULL JOIN pg_class t ON ((c.reltoastrelid = t.oid))) FULL JOIN pg_class x ON ((c.reltoastidxid = x.oid))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, c.relname, t.oid, x.oid;
+ pg_statio_sys_indexes    | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE (pg_statio_all_indexes.relname ~ '^pg_'::text);
+ pg_statio_sys_sequences  | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE (pg_statio_all_sequences.relname ~ '^pg_'::text);
+ pg_statio_sys_tables     | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE (pg_statio_all_tables.relname ~ '^pg_'::text);
+ pg_statio_user_indexes   | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE (pg_statio_all_indexes.relname !~ '^pg_'::text);
+ pg_statio_user_sequences | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE (pg_statio_all_sequences.relname !~ '^pg_'::text);
+ pg_statio_user_tables    | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE (pg_statio_all_tables.relname !~ '^pg_'::text);
+ pg_stats                 | SELECT c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE WHEN (1 = s.stakind1) THEN s.stavalues1 WHEN (1 = s.stakind2) THEN s.stavalues2 WHEN (1 = s.stakind3) THEN s.stavalues3 WHEN (1 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS most_common_vals, CASE WHEN (1 = s.stakind1) THEN s.stanumbers1 WHEN (1 = s.stakind2) THEN s.stanumbers2 WHEN (1 = s.stakind3) THEN s.stanumbers3 WHEN (1 = s.stakind4) THEN s.stanumbers4 ELSE NULL::"_float4" END AS most_common_freqs, CASE WHEN (2 = s.stakind1) THEN s.stavalues1 WHEN (2 = s.stakind2) THEN s.stavalues2 WHEN (2 = s.stakind3) THEN s.stavalues3 WHEN (2 = s.stakind4) THEN s.stavalues4 ELSE NULL::"_text" END AS histogram_bounds, CASE WHEN (3 = s.stakind1) THEN s.stanumbers1[1] WHEN (3 = s.stakind2) THEN s.stanumbers2[1] WHEN (3 = s.stakind3) THEN s.stanumbers3[1] WHEN (3 = s.stakind4) THEN s.stanumbers4[1] ELSE NULL::float4 END AS correlation FROM pg_class c, pg_attribute a, pg_statistic s WHERE ((((c.oid = s.starelid) AND (c.oid = a.attrelid)) AND (a.attnum = s.staattnum)) AND has_table_privilege(c.oid, 'select'::text));
+ pg_tables                | SELECT c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM pg_class c WHERE ((c.relkind = 'r'::"char") OR (c.relkind = 's'::"char"));
+ pg_user                  | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usetrace, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil FROM pg_shadow;
+ pg_views                 | SELECT c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.relname) AS definition FROM pg_class c WHERE (c.relkind = 'v'::"char");
+ rtest_v1                 | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1;
+ rtest_vcomp              | SELECT x.part, (x.size * y.factor) AS size_in_cm FROM rtest_comp x, rtest_unitfact y WHERE (x.unit = y.unit);
+ rtest_vview1             | SELECT x.a, x.b FROM rtest_view1 x WHERE (0 < (SELECT count(*) AS count FROM rtest_view2 y WHERE (y.a = x.a)));
+ rtest_vview2             | SELECT rtest_view1.a, rtest_view1.b FROM rtest_view1 WHERE rtest_view1.v;
+ rtest_vview3             | SELECT x.a, x.b FROM rtest_vview2 x WHERE (0 < (SELECT count(*) AS count FROM rtest_view2 y WHERE (y.a = x.a)));
+ rtest_vview4             | SELECT x.a, x.b, count(y.a) AS refcount FROM rtest_view1 x, rtest_view2 y WHERE (x.a = y.a) GROUP BY x.a, x.b;
+ rtest_vview5             | SELECT rtest_view1.a, rtest_view1.b, rtest_viewfunc1(rtest_view1.a) AS refcount FROM rtest_view1;
+ shoe                     | SELECT sh.shoename, sh.sh_avail, sh.slcolor, sh.slminlen, (sh.slminlen * un.un_fact) AS slminlen_cm, sh.slmaxlen, (sh.slmaxlen * un.un_fact) AS slmaxlen_cm, sh.slunit FROM shoe_data sh, unit un WHERE (sh.slunit = un.un_name);
+ shoe_ready               | SELECT rsh.shoename, rsh.sh_avail, rsl.sl_name, rsl.sl_avail, int4smaller(rsh.sh_avail, rsl.sl_avail) AS total_avail FROM shoe rsh, shoelace rsl WHERE (((rsl.sl_color = rsh.slcolor) AND (rsl.sl_len_cm >= rsh.slminlen_cm)) AND (rsl.sl_len_cm <= rsh.slmaxlen_cm));
+ shoelace                 | SELECT s.sl_name, s.sl_avail, s.sl_color, s.sl_len, s.sl_unit, (s.sl_len * u.un_fact) AS sl_len_cm FROM shoelace_data s, unit u WHERE (s.sl_unit = u.un_name);
+ shoelace_candelete       | SELECT shoelace_obsolete.sl_name, shoelace_obsolete.sl_avail, shoelace_obsolete.sl_color, shoelace_obsolete.sl_len, shoelace_obsolete.sl_unit, shoelace_obsolete.sl_len_cm FROM shoelace_obsolete WHERE (shoelace_obsolete.sl_avail = 0);
+ shoelace_obsolete        | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color))));
+ street                   | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath);
+ toyemp                   | SELECT emp.name, emp.age, emp."location", (12 * emp.salary) AS annualsal FROM emp;
+(38 rows)
 
 SELECT tablename, rulename, definition FROM pg_rules 
 	ORDER BY tablename, rulename;