From c03614ef00bcb82e6d75985d823b72f78b423fd0 Mon Sep 17 00:00:00 2001
From: B Sadhu Prasad Patro <b.sadhuprasadp@enterprisedb.com>
Date: Thu, 5 Aug 2021 09:16:25 -0700
Subject: [PATCH] pg_stat_reset and pg_stat_reset_single_table_counters don't
 work for shared objects.

This patch will reset the stats for shared tables also.
Code changes are done in pgstat_recv_resetcounter and
pgstat_recv_resetsinglecounter for dbentry with 'InvaidOid'.
---
 src/backend/postmaster/pgstat.c | 60 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 56755cb..f272931 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -5092,7 +5092,6 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
 	 * Lookup the database in the hashtable.  Nothing to do if not there.
 	 */
 	dbentry = pgstat_get_db_entry(msg->m_databaseid, false);
-
 	if (!dbentry)
 		return;
 
@@ -5113,6 +5112,30 @@ pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len)
 	 * tables and functions.
 	 */
 	reset_dbentry_counters(dbentry);
+
+	/*
+	 * Lookup for the shared tables also to reset the stats
+	 */
+	dbentry = pgstat_get_db_entry(InvalidOid, false);
+	if (!dbentry)
+		return;
+
+	/*
+	 * We simply throw away all the shared table entries by recreating new
+	 * hash table for them.
+	 */
+	if (dbentry->tables != NULL)
+		hash_destroy(dbentry->tables);
+	if (dbentry->functions != NULL)
+		hash_destroy(dbentry->functions);
+
+	dbentry->tables = NULL;
+	dbentry->functions = NULL;
+
+	/*
+	 * This creates empty hash tables for tables and functions.
+	 */
+	reset_dbentry_counters(dbentry);
 }
 
 /* ----------
@@ -5159,6 +5182,7 @@ static void
 pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len)
 {
 	PgStat_StatDBEntry *dbentry;
+	bool		found;
 
 	dbentry = pgstat_get_db_entry(msg->m_databaseid, false);
 
@@ -5168,13 +5192,41 @@ pgstat_recv_resetsinglecounter(PgStat_MsgResetsinglecounter *msg, int len)
 	/* Set the reset timestamp for the whole database */
 	dbentry->stat_reset_timestamp = GetCurrentTimestamp();
 
-	/* Remove object if it exists, ignore it if not */
+	/* Remove object if it exists, if not then may be it's a shared table */
 	if (msg->m_resettype == RESET_TABLE)
+	{
 		(void) hash_search(dbentry->tables, (void *) &(msg->m_objectid),
-						   HASH_REMOVE, NULL);
+						   HASH_REMOVE, &found);
+		if (!found)
+		{
+			/* If we didn't find it, maybe it's a shared table */
+			dbentry = pgstat_get_db_entry(InvalidOid, false);
+			if (dbentry)
+			{
+				/* Set the reset timestamp for the whole database */
+				dbentry->stat_reset_timestamp = GetCurrentTimestamp();
+				(void) hash_search(dbentry->tables, (void *) &(msg->m_objectid),
+								   HASH_REMOVE, NULL);
+			}
+		}
+	}
 	else if (msg->m_resettype == RESET_FUNCTION)
+	{
 		(void) hash_search(dbentry->functions, (void *) &(msg->m_objectid),
-						   HASH_REMOVE, NULL);
+						   HASH_REMOVE, &found);
+		if (!found)
+		{
+			/* If we didn't find it, maybe it's a shared table */
+			dbentry = pgstat_get_db_entry(InvalidOid, false);
+			if (dbentry)
+			{
+				/* Set the reset timestamp for the whole database */
+				dbentry->stat_reset_timestamp = GetCurrentTimestamp();
+				(void) hash_search(dbentry->functions, (void *) &(msg->m_objectid),
+								   HASH_REMOVE, NULL);
+			}
+		}
+	}
 }
 
 /* ----------
-- 
1.8.3.1

