From 9b4727e20cd7df7d2acde17610c8612d07aac789 Mon Sep 17 00:00:00 2001
From: Shinya Kato <shinya11.kato@gmail.com>
Date: Fri, 2 May 2025 14:58:07 +0900
Subject: [PATCH v3 2/9] Make pg_stat_reset_shared() return the reset time

---
 doc/src/sgml/monitoring.sgml                |  5 +-
 src/backend/access/transam/xlogprefetcher.c |  6 ++-
 src/backend/catalog/system_functions.sql    |  2 +-
 src/backend/utils/activity/pgstat.c         |  5 +-
 src/backend/utils/adt/pgstatfuncs.c         | 21 ++++----
 src/include/access/xlogprefetcher.h         |  3 +-
 src/include/catalog/pg_proc.dat             |  2 +-
 src/include/pgstat.h                        |  2 +-
 src/test/regress/expected/stats.out         | 56 ++++++++++-----------
 src/test/regress/sql/stats.sql              | 14 +++---
 10 files changed, 61 insertions(+), 55 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 6ebb205bb3f..e5edee97e94 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5086,11 +5086,12 @@ description | Waiting for a newly initialized WAL file to reach durable storage
          <primary>pg_stat_reset_shared</primary>
         </indexterm>
         <function>pg_stat_reset_shared</function> ( [ <parameter>target</parameter> <type>text</type> <literal>DEFAULT</literal> <literal>NULL</literal> ] )
-        <returnvalue>void</returnvalue>
+        <returnvalue>timestamp with time zone</returnvalue>
        </para>
        <para>
         Resets some cluster-wide statistics counters to zero, depending on the
-        argument. <parameter>target</parameter> can be:
+        argument, and returns the time of the reset.
+        <parameter>target</parameter> can be:
        <itemizedlist>
         <listitem>
          <para>
diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index ed3aacabc98..bc033ae1842 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -299,16 +299,18 @@ XLogPrefetchShmemSize(void)
 /*
  * Reset all counters to zero.
  */
-void
+TimestampTz
 XLogPrefetchResetStats(void)
 {
-	pg_atomic_write_u64(&SharedStats->reset_time, GetCurrentTimestamp());
+	TimestampTz ts = GetCurrentTimestamp();
+	pg_atomic_write_u64(&SharedStats->reset_time, ts);
 	pg_atomic_write_u64(&SharedStats->prefetch, 0);
 	pg_atomic_write_u64(&SharedStats->hit, 0);
 	pg_atomic_write_u64(&SharedStats->skip_init, 0);
 	pg_atomic_write_u64(&SharedStats->skip_new, 0);
 	pg_atomic_write_u64(&SharedStats->skip_fpw, 0);
 	pg_atomic_write_u64(&SharedStats->skip_rep, 0);
+	return ts;
 }
 
 void
diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql
index 2d946d6d9e9..0d679e6a8d4 100644
--- a/src/backend/catalog/system_functions.sql
+++ b/src/backend/catalog/system_functions.sql
@@ -638,7 +638,7 @@ AS 'unicode_is_normalized';
 
 CREATE OR REPLACE FUNCTION
   pg_stat_reset_shared(target text DEFAULT NULL)
-RETURNS void
+RETURNS timestamp with time zone
 LANGUAGE INTERNAL
 CALLED ON NULL INPUT VOLATILE PARALLEL SAFE
 AS 'pg_stat_reset_shared';
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 510e6cb11b6..1fcd140a589 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -875,7 +875,7 @@ pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid)
  * Permission checking for this function is managed through the normal
  * GRANT system.
  */
-void
+TimestampTz
 pgstat_reset_of_kind(PgStat_Kind kind)
 {
 	const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
@@ -885,8 +885,9 @@ pgstat_reset_of_kind(PgStat_Kind kind)
 		kind_info->reset_all_cb(ts);
 	else
 		pgstat_reset_entries_of_kind(kind, ts);
-}
 
+	return ts;
+}
 
 /* ------------------------------------------------------------
  * Fetching of stats
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 393958be632..4a84575e7a7 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1893,6 +1893,7 @@ Datum
 pg_stat_reset_shared(PG_FUNCTION_ARGS)
 {
 	char	   *target = NULL;
+	TimestampTz ts;
 
 	if (PG_ARGISNULL(0))
 	{
@@ -1903,34 +1904,34 @@ pg_stat_reset_shared(PG_FUNCTION_ARGS)
 		pgstat_reset_of_kind(PGSTAT_KIND_IO);
 		XLogPrefetchResetStats();
 		pgstat_reset_of_kind(PGSTAT_KIND_SLRU);
-		pgstat_reset_of_kind(PGSTAT_KIND_WAL);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_WAL);
 
-		PG_RETURN_VOID();
+		PG_RETURN_TIMESTAMPTZ(ts);
 	}
 
 	target = text_to_cstring(PG_GETARG_TEXT_PP(0));
 
 	if (strcmp(target, "archiver") == 0)
-		pgstat_reset_of_kind(PGSTAT_KIND_ARCHIVER);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_ARCHIVER);
 	else if (strcmp(target, "bgwriter") == 0)
-		pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER);
 	else if (strcmp(target, "checkpointer") == 0)
-		pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER);
 	else if (strcmp(target, "io") == 0)
-		pgstat_reset_of_kind(PGSTAT_KIND_IO);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_IO);
 	else if (strcmp(target, "recovery_prefetch") == 0)
-		XLogPrefetchResetStats();
+		ts = XLogPrefetchResetStats();
 	else if (strcmp(target, "slru") == 0)
-		pgstat_reset_of_kind(PGSTAT_KIND_SLRU);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_SLRU);
 	else if (strcmp(target, "wal") == 0)
-		pgstat_reset_of_kind(PGSTAT_KIND_WAL);
+		ts = pgstat_reset_of_kind(PGSTAT_KIND_WAL);
 	else
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("unrecognized reset target: \"%s\"", target),
 				 errhint("Target must be \"archiver\", \"bgwriter\", \"checkpointer\", \"io\", \"recovery_prefetch\", \"slru\", or \"wal\".")));
 
-	PG_RETURN_VOID();
+	PG_RETURN_TIMESTAMPTZ(ts);
 }
 
 /*
diff --git a/src/include/access/xlogprefetcher.h b/src/include/access/xlogprefetcher.h
index 50b39c1fb0d..6cc95b70c6e 100644
--- a/src/include/access/xlogprefetcher.h
+++ b/src/include/access/xlogprefetcher.h
@@ -16,6 +16,7 @@
 #include "access/xlogdefs.h"
 #include "access/xlogreader.h"
 #include "access/xlogrecord.h"
+#include "utils/timestamp.h"
 
 /* GUCs */
 extern PGDLLIMPORT int recovery_prefetch;
@@ -37,7 +38,7 @@ extern void XLogPrefetchReconfigure(void);
 extern size_t XLogPrefetchShmemSize(void);
 extern void XLogPrefetchShmemInit(void);
 
-extern void XLogPrefetchResetStats(void);
+extern TimestampTz XLogPrefetchResetStats(void);
 
 extern XLogPrefetcher *XLogPrefetcherAllocate(XLogReaderState *reader);
 extern void XLogPrefetcherFree(XLogPrefetcher *prefetcher);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 1d1edf67ac5..df291d21ef7 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6164,7 +6164,7 @@
 { oid => '3775',
   descr => 'statistics: reset collected statistics shared across the cluster',
   proname => 'pg_stat_reset_shared', proisstrict => 'f', provolatile => 'v',
-  prorettype => 'void', proargtypes => 'text',
+  prorettype => 'timestamptz', proargtypes => 'text',
   prosrc => 'pg_stat_reset_shared' },
 { oid => '3776',
   descr => 'statistics: reset collected statistics for a single table or index in the current database or shared across all databases in the cluster',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 33b3bd242a8..a91984f086f 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -531,7 +531,7 @@ extern void pgstat_force_next_flush(void);
 
 extern TimestampTz pgstat_reset_counters(void);
 extern void pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid);
-extern void pgstat_reset_of_kind(PgStat_Kind kind);
+extern TimestampTz pgstat_reset_of_kind(PgStat_Kind kind);
 
 /* stats accessors */
 extern void pgstat_clear_snapshot(void);
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index c150229da52..9b93d257992 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1045,10 +1045,10 @@ SELECT stats_reset > :'slru_notify_reset_ts'::timestamptz FROM pg_stat_slru WHER
 
 -- Test that reset_shared with archiver specified as the stats type works
 SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset
-SELECT pg_stat_reset_shared('archiver');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('archiver') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver;
@@ -1059,10 +1059,10 @@ SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver;
 
 -- Test that reset_shared with bgwriter specified as the stats type works
 SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset
-SELECT pg_stat_reset_shared('bgwriter');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('bgwriter') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter;
@@ -1073,10 +1073,10 @@ SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter;
 
 -- Test that reset_shared with checkpointer specified as the stats type works
 SELECT stats_reset AS checkpointer_reset_ts FROM pg_stat_checkpointer \gset
-SELECT pg_stat_reset_shared('checkpointer');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('checkpointer') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT stats_reset > :'checkpointer_reset_ts'::timestamptz FROM pg_stat_checkpointer;
@@ -1087,10 +1087,10 @@ SELECT stats_reset > :'checkpointer_reset_ts'::timestamptz FROM pg_stat_checkpoi
 
 -- Test that reset_shared with recovery_prefetch specified as the stats type works
 SELECT stats_reset AS recovery_prefetch_reset_ts FROM pg_stat_recovery_prefetch \gset
-SELECT pg_stat_reset_shared('recovery_prefetch');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('recovery_prefetch') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT stats_reset > :'recovery_prefetch_reset_ts'::timestamptz FROM pg_stat_recovery_prefetch;
@@ -1101,10 +1101,10 @@ SELECT stats_reset > :'recovery_prefetch_reset_ts'::timestamptz FROM pg_stat_rec
 
 -- Test that reset_shared with slru specified as the stats type works
 SELECT max(stats_reset) AS slru_reset_ts FROM pg_stat_slru \gset
-SELECT pg_stat_reset_shared('slru');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('slru') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT max(stats_reset) > :'slru_reset_ts'::timestamptz FROM pg_stat_slru;
@@ -1115,10 +1115,10 @@ SELECT max(stats_reset) > :'slru_reset_ts'::timestamptz FROM pg_stat_slru;
 
 -- Test that reset_shared with wal specified as the stats type works
 SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset
-SELECT pg_stat_reset_shared('wal');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('wal') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT stats_reset > :'wal_reset_ts'::timestamptz FROM pg_stat_wal;
@@ -1727,10 +1727,10 @@ SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) +
   FROM pg_stat_io \gset
 SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_pre_reset
   FROM pg_stat_get_backend_io(pg_backend_pid()) \gset
-SELECT pg_stat_reset_shared('io');
- pg_stat_reset_shared 
-----------------------
- 
+SELECT pg_stat_reset_shared('io') IS NOT NULL AS t;
+ t 
+---
+ t
 (1 row)
 
 SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_post_reset
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 86690e41b69..07fcff8215a 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -492,32 +492,32 @@ SELECT stats_reset > :'slru_notify_reset_ts'::timestamptz FROM pg_stat_slru WHER
 
 -- Test that reset_shared with archiver specified as the stats type works
 SELECT stats_reset AS archiver_reset_ts FROM pg_stat_archiver \gset
-SELECT pg_stat_reset_shared('archiver');
+SELECT pg_stat_reset_shared('archiver') IS NOT NULL AS t;
 SELECT stats_reset > :'archiver_reset_ts'::timestamptz FROM pg_stat_archiver;
 
 -- Test that reset_shared with bgwriter specified as the stats type works
 SELECT stats_reset AS bgwriter_reset_ts FROM pg_stat_bgwriter \gset
-SELECT pg_stat_reset_shared('bgwriter');
+SELECT pg_stat_reset_shared('bgwriter') IS NOT NULL AS t;
 SELECT stats_reset > :'bgwriter_reset_ts'::timestamptz FROM pg_stat_bgwriter;
 
 -- Test that reset_shared with checkpointer specified as the stats type works
 SELECT stats_reset AS checkpointer_reset_ts FROM pg_stat_checkpointer \gset
-SELECT pg_stat_reset_shared('checkpointer');
+SELECT pg_stat_reset_shared('checkpointer') IS NOT NULL AS t;
 SELECT stats_reset > :'checkpointer_reset_ts'::timestamptz FROM pg_stat_checkpointer;
 
 -- Test that reset_shared with recovery_prefetch specified as the stats type works
 SELECT stats_reset AS recovery_prefetch_reset_ts FROM pg_stat_recovery_prefetch \gset
-SELECT pg_stat_reset_shared('recovery_prefetch');
+SELECT pg_stat_reset_shared('recovery_prefetch') IS NOT NULL AS t;
 SELECT stats_reset > :'recovery_prefetch_reset_ts'::timestamptz FROM pg_stat_recovery_prefetch;
 
 -- Test that reset_shared with slru specified as the stats type works
 SELECT max(stats_reset) AS slru_reset_ts FROM pg_stat_slru \gset
-SELECT pg_stat_reset_shared('slru');
+SELECT pg_stat_reset_shared('slru') IS NOT NULL AS t;
 SELECT max(stats_reset) > :'slru_reset_ts'::timestamptz FROM pg_stat_slru;
 
 -- Test that reset_shared with wal specified as the stats type works
 SELECT stats_reset AS wal_reset_ts FROM pg_stat_wal \gset
-SELECT pg_stat_reset_shared('wal');
+SELECT pg_stat_reset_shared('wal') IS NOT NULL AS t;
 SELECT stats_reset > :'wal_reset_ts'::timestamptz FROM pg_stat_wal;
 
 -- Test error case for reset_shared with unknown stats type
@@ -827,7 +827,7 @@ SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) +
   FROM pg_stat_io \gset
 SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS my_io_stats_pre_reset
   FROM pg_stat_get_backend_io(pg_backend_pid()) \gset
-SELECT pg_stat_reset_shared('io');
+SELECT pg_stat_reset_shared('io') IS NOT NULL AS t;
 SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_post_reset
   FROM pg_stat_io \gset
 SELECT :io_stats_post_reset < :io_stats_pre_reset;
-- 
2.47.3

