From ed626abcec5fdeb09795d3e7fe2280f4b0642ebc Mon Sep 17 00:00:00 2001
From: Bernd Helmle <mailings@oopsware.de>
Date: Tue, 21 Sep 2010 22:42:54 +0200
Subject: [PATCH] Merge truncate stats patch into new branch.

---
 src/backend/catalog/system_views.sql |  1 +
 src/backend/commands/tablecmds.c     |  5 ++
 src/backend/postmaster/pgstat.c      | 68 +++++++++++++++++++---------
 src/backend/utils/adt/pgstatfuncs.c  | 15 ++++++
 src/include/catalog/pg_proc.h        |  2 +
 src/include/pgstat.h                 | 26 +++++++++--
 6 files changed, 92 insertions(+), 25 deletions(-)

diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 651ffc61b9..ce9a7f729c 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -196,6 +196,7 @@ CREATE VIEW pg_stat_all_tables AS
             pg_stat_get_tuples_updated(C.oid) AS n_tup_upd, 
             pg_stat_get_tuples_deleted(C.oid) AS n_tup_del,
             pg_stat_get_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
+            pg_stat_get_numtruncate(C.oid) AS n_truncate,
             pg_stat_get_live_tuples(C.oid) AS n_live_tup, 
             pg_stat_get_dead_tuples(C.oid) AS n_dead_tup,
             pg_stat_get_last_vacuum_time(C.oid) as last_vacuum,
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 82143682d5..ab657a0d4e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1064,6 +1064,11 @@ ExecuteTruncate(TruncateStmt *stmt)
 	{
 		Relation	rel = (Relation) lfirst(cell);
 
+		/*
+		 * increase statistic counts
+		 */
+		pgstat_count_heap_truncate(rel);
+
 		heap_close(rel, NoLock);
 	}
 
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 483d7afe34..edd1aceb0f 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1736,6 +1736,27 @@ pgstat_update_heap_dead_tuples(Relation rel, int delta)
 		pgstat_info->t_counts.t_delta_dead_tuples -= delta;
 }
 
+/*
+ * pgstat_count_heap_truncate - count heap truncate operations
+ */
+void
+pgstat_count_heap_truncate(Relation rel)
+{
+	PgStat_TableStatus *pgstat_info = rel->pgstat_info;
+	
+	if (pgstat_track_counts && pgstat_info != NULL)
+	{
+		int			nest_level = GetCurrentTransactionNestLevel();
+		pgstat_info->t_counts.t_numtruncate++;
+
+		/* We have to log the transactional effect at the proper level */
+		if (pgstat_info->trans == NULL ||
+			pgstat_info->trans->nest_level != nest_level)
+			add_tabstat_xact_level(pgstat_info, nest_level);
+
+		pgstat_info->trans->trunc_state.numtruncate++;
+	}
+}
 
 /* ----------
  * AtEOXact_PgStat
@@ -3850,18 +3871,20 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
 			 * If it's a new table entry, initialize counters to the values we
 			 * just got.
 			 */
-			tabentry->numscans = tabmsg->t_counts.t_numscans;
-			tabentry->tuples_returned = tabmsg->t_counts.t_tuples_returned;
-			tabentry->tuples_fetched = tabmsg->t_counts.t_tuples_fetched;
-			tabentry->tuples_inserted = tabmsg->t_counts.t_tuples_inserted;
-			tabentry->tuples_updated = tabmsg->t_counts.t_tuples_updated;
-			tabentry->tuples_deleted = tabmsg->t_counts.t_tuples_deleted;
-			tabentry->tuples_hot_updated = tabmsg->t_counts.t_tuples_hot_updated;
-			tabentry->n_live_tuples = tabmsg->t_counts.t_delta_live_tuples;
-			tabentry->n_dead_tuples = tabmsg->t_counts.t_delta_dead_tuples;
+<<<<<<< HEAD
+			tabentry->numscans = tabmsg[i].t_counts.t_numscans;
+			tabentry->tuples_returned = tabmsg[i].t_counts.t_tuples_returned;
+			tabentry->tuples_fetched = tabmsg[i].t_counts.t_tuples_fetched;
+			tabentry->tuples_inserted = tabmsg[i].t_counts.t_tuples_inserted;
+			tabentry->tuples_updated = tabmsg[i].t_counts.t_tuples_updated;
+			tabentry->tuples_deleted = tabmsg[i].t_counts.t_tuples_deleted;
+			tabentry->tuples_hot_updated = tabmsg[i].t_counts.t_tuples_hot_updated;
+			tabentry->numtruncate   = tabmsg[i].t_counts.t_numtruncate;
+			tabentry->n_live_tuples = tabmsg[i].t_counts.t_new_live_tuples;
+			tabentry->n_dead_tuples = tabmsg[i].t_counts.t_new_dead_tuples;
 			tabentry->changes_since_analyze = tabmsg->t_counts.t_changed_tuples;
-			tabentry->blocks_fetched = tabmsg->t_counts.t_blocks_fetched;
-			tabentry->blocks_hit = tabmsg->t_counts.t_blocks_hit;
+			tabentry->blocks_fetched = tabmsg[i].t_counts.t_blocks_fetched;
+			tabentry->blocks_hit = tabmsg[i].t_counts.t_blocks_hit;
 
 			tabentry->vacuum_timestamp = 0;
 			tabentry->autovac_vacuum_timestamp = 0;
@@ -3873,18 +3896,19 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
 			/*
 			 * Otherwise add the values to the existing entry.
 			 */
-			tabentry->numscans += tabmsg->t_counts.t_numscans;
-			tabentry->tuples_returned += tabmsg->t_counts.t_tuples_returned;
-			tabentry->tuples_fetched += tabmsg->t_counts.t_tuples_fetched;
-			tabentry->tuples_inserted += tabmsg->t_counts.t_tuples_inserted;
-			tabentry->tuples_updated += tabmsg->t_counts.t_tuples_updated;
-			tabentry->tuples_deleted += tabmsg->t_counts.t_tuples_deleted;
-			tabentry->tuples_hot_updated += tabmsg->t_counts.t_tuples_hot_updated;
-			tabentry->n_live_tuples += tabmsg->t_counts.t_delta_live_tuples;
-			tabentry->n_dead_tuples += tabmsg->t_counts.t_delta_dead_tuples;
+			tabentry->numscans += tabmsg[i].t_counts.t_numscans;
+			tabentry->tuples_returned += tabmsg[i].t_counts.t_tuples_returned;
+			tabentry->tuples_fetched += tabmsg[i].t_counts.t_tuples_fetched;
+			tabentry->tuples_inserted += tabmsg[i].t_counts.t_tuples_inserted;
+			tabentry->tuples_updated += tabmsg[i].t_counts.t_tuples_updated;
+			tabentry->tuples_deleted += tabmsg[i].t_counts.t_tuples_deleted;
+			tabentry->tuples_hot_updated += tabmsg[i].t_counts.t_tuples_hot_updated;
+			tabentry->numtruncate   += tabmsg[i].t_counts.t_numtruncate;
+			tabentry->n_live_tuples += tabmsg[i].t_counts.t_new_live_tuples;
+			tabentry->n_dead_tuples += tabmsg[i].t_counts.t_new_dead_tuples;
 			tabentry->changes_since_analyze += tabmsg->t_counts.t_changed_tuples;
-			tabentry->blocks_fetched += tabmsg->t_counts.t_blocks_fetched;
-			tabentry->blocks_hit += tabmsg->t_counts.t_blocks_hit;
+			tabentry->blocks_fetched += tabmsg[i].t_counts.t_blocks_fetched;
+			tabentry->blocks_hit += tabmsg[i].t_counts.t_blocks_hit;
 		}
 
 		/* Clamp n_live_tuples in case of negative delta_live_tuples */
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 6edb8bfd13..c4011a74dd 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -29,6 +29,7 @@ extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
+extern Datum pg_stat_get_numtruncate(PG_FUNCTION_ARGS);
 extern Datum pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS);
 extern Datum pg_stat_get_live_tuples(PG_FUNCTION_ARGS);
 extern Datum pg_stat_get_dead_tuples(PG_FUNCTION_ARGS);
@@ -198,6 +199,20 @@ pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(result);
 }
 
+Datum
+pg_stat_get_numtruncate(PG_FUNCTION_ARGS)
+{
+	Oid   relid = PG_GETARG_OID(0);
+	int64 result;
+	PgStat_StatTabEntry *tabentry;
+
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
+		result = 0;
+	else
+		result = (int64) (tabentry->numtruncate);
+
+	PG_RETURN_INT64(result);
+}
 
 Datum
 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 61c6b27d1d..4c21b32519 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3032,6 +3032,8 @@ DATA(insert OID = 1933 (  pg_stat_get_tuples_deleted	PGNSP PGUID 12 1 0 0 f f f
 DESCR("statistics: number of tuples deleted");
 DATA(insert OID = 1972 (  pg_stat_get_tuples_hot_updated PGNSP PGUID 12 1 0 0 f f f t f s 1 0 20 "26" _null_ _null_ _null_ _null_ pg_stat_get_tuples_hot_updated _null_ _null_ _null_ ));
 DESCR("statistics: number of tuples hot updated");
+DATA(insert OID = 1981 (  pg_stat_get_numtruncate	PGNSP PGUID 12 1 0 0 f f f t f s 1 0 20 "26" _null_ _null_ _null_ _null_ pg_stat_get_numtruncate _null_ _null_ _null_ ));
+DESCR("statistics: number of table truncation");
 DATA(insert OID = 2878 (  pg_stat_get_live_tuples	PGNSP PGUID 12 1 0 0 f f f t f s 1 0 20 "26" _null_ _null_ _null_ _null_ pg_stat_get_live_tuples _null_ _null_ _null_ ));
 DESCR("statistics: number of live tuples");
 DATA(insert OID = 2879 (  pg_stat_get_dead_tuples	PGNSP PGUID 12 1 0 0 f f f t f s 1 0 20 "26" _null_ _null_ _null_ _null_ pg_stat_get_dead_tuples _null_ _null_ _null_ ));
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 87541433c0..648c08671c 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -86,6 +86,7 @@ typedef struct PgStat_TableCounts
 	PgStat_Counter t_tuples_updated;
 	PgStat_Counter t_tuples_deleted;
 	PgStat_Counter t_tuples_hot_updated;
+	PgStat_Counter t_numtruncate;
 
 	PgStat_Counter t_delta_live_tuples;
 	PgStat_Counter t_delta_dead_tuples;
@@ -137,15 +138,29 @@ typedef struct PgStat_TableStatus
 	PgStat_TableCounts t_counts;	/* event counts to be sent */
 } PgStat_TableStatus;
 
+/*
+ * PgStat_XactTruncateStatus		Per-table, TRUNCATE (sub)transaction status
+ * ----------
+ */
+typedef struct PgStat_XactTruncateStatus
+{
+
+	PgStat_Counter numtruncate;     /* number of truncates */
+	PgStat_Counter tuples_deleted;     /* store previously deleted tuples */
+	PgStat_Counter tuples_inserted;    /* store previously inserted tuples */
+
+} PgStat_XactTruncateStatus;
+
 /* ----------
  * PgStat_TableXactStatus		Per-table, per-subtransaction status
  * ----------
  */
 typedef struct PgStat_TableXactStatus
 {
-	PgStat_Counter tuples_inserted;		/* tuples inserted in (sub)xact */
-	PgStat_Counter tuples_updated;		/* tuples updated in (sub)xact */
-	PgStat_Counter tuples_deleted;		/* tuples deleted in (sub)xact */
+	PgStat_Counter tuples_inserted;		   /* tuples inserted in (sub)xact */
+	PgStat_Counter tuples_deleted;		   /* tuples deleted in (sub)xact */
+	PgStat_Counter tuples_updated;		   /* tuples updated in (sub)xact */
+	PgStat_XactTruncateStatus trunc_state; /* per-table TRUNCATE status */
 	int			nest_level;		/* subtransaction nest level */
 	/* links to other structs for same relation: */
 	struct PgStat_TableXactStatus *upper;		/* next higher subxact if any */
@@ -519,7 +534,12 @@ typedef struct PgStat_StatTabEntry
 
 	PgStat_Counter n_live_tuples;
 	PgStat_Counter n_dead_tuples;
+<<<<<<< HEAD
+	PgStat_Counter numtruncate;
+	PgStat_Counter last_anl_tuples;
+=======
 	PgStat_Counter changes_since_analyze;
+>>>>>>> 6f4569d9b9b95c7cb2a04bdfd9c99ca3e7bada82
 
 	PgStat_Counter blocks_fetched;
 	PgStat_Counter blocks_hit;
-- 
2.39.5

