From e2500f1c610d2f73b53e353b98856a90db4cc452 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Date: Thu, 18 Sep 2025 15:55:01 +0530
Subject: [PATCH 2/2] Address review comments

Among others rename total_txns and total_bytes to total_wal_txns and
total_wal_bytes respectively.

Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Shveta Malik <shveta.malik@gmail.com>
---
 contrib/test_decoding/expected/stats.out  | 58 +++++++++++------------
 contrib/test_decoding/sql/stats.sql       | 17 +++----
 contrib/test_decoding/t/001_repl_stats.pl |  6 +--
 doc/src/sgml/logicaldecoding.sgml         |  6 +--
 doc/src/sgml/monitoring.sgml              | 18 +++----
 src/backend/catalog/system_views.sql      |  4 +-
 src/backend/utils/adt/pgstatfuncs.c       |  4 +-
 src/include/catalog/pg_proc.dat           |  2 +-
 src/test/regress/expected/rules.out       |  6 +--
 9 files changed, 61 insertions(+), 60 deletions(-)

diff --git a/contrib/test_decoding/expected/stats.out b/contrib/test_decoding/expected/stats.out
index d19fe6a1c61..4834b3460a6 100644
--- a/contrib/test_decoding/expected/stats.out
+++ b/contrib/test_decoding/expected/stats.out
@@ -37,17 +37,17 @@ SELECT pg_stat_force_next_flush();
  
 (1 row)
 
--- total_txns may vary based on the background activity but sent_txns should
--- always be 1 since the background transactions are always skipped. Filtered
--- bytes would be set only when there's a change that was passed to the plugin
--- but was filtered out. Depending upon the background transactions, filtered
--- bytes may or may not be zero.
-SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
-       slot_name        | spill_txns | spill_count | total_txns | total_bytes | plugin_sent_txns | sent_bytes | filtered_bytes 
-------------------------+------------+-------------+------------+-------------+------------------+------------+----------------
- regression_slot_stats1 | t          | t           | t          | t           |                1 | t          | t
- regression_slot_stats2 | t          | t           | t          | t           |                1 | t          | t
- regression_slot_stats3 | t          | t           | t          | t           |                1 | t          | t
+-- total_wal_txns may vary based on the background activity but plugin_sent_txns
+-- should always be 1 since the background transactions are always skipped.
+-- Filtered bytes would be set only when there's a change that was passed to the
+-- plugin but was filtered out. Depending upon the background transactions,
+-- filtered bytes may or may not be zero.
+SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
+       slot_name        | spill_txns | spill_count | total_wal_txns | total_wal_bytes | plugin_sent_txns | sent_bytes | filtered_bytes 
+------------------------+------------+-------------+----------------+-----------------+------------------+------------+----------------
+ regression_slot_stats1 | t          | t           | t              | t               |                1 | t          | t
+ regression_slot_stats2 | t          | t           | t              | t               |                1 | t          | t
+ regression_slot_stats3 | t          | t           | t              | t               |                1 | t          | t
 (3 rows)
 
 RESET logical_decoding_work_mem;
@@ -58,12 +58,12 @@ SELECT pg_stat_reset_replication_slot('regression_slot_stats1');
  
 (1 row)
 
-SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
-       slot_name        | spill_txns | spill_count | total_txns | total_bytes | plugin_sent_txns | sent_bytes | filtered_bytes 
-------------------------+------------+-------------+------------+-------------+------------------+------------+----------------
- regression_slot_stats1 | t          | t           | f          | f           |                  |            | 
- regression_slot_stats2 | t          | t           | t          | t           |                1 | t          | t
- regression_slot_stats3 | t          | t           | t          | t           |                1 | t          | t
+SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
+       slot_name        | spill_txns | spill_count | total_wal_txns | total_wal_bytes | plugin_sent_txns | sent_bytes | filtered_bytes 
+------------------------+------------+-------------+----------------+-----------------+------------------+------------+----------------
+ regression_slot_stats1 | t          | t           | f              | f               |                  |            | 
+ regression_slot_stats2 | t          | t           | t              | t               |                1 | t          | t
+ regression_slot_stats3 | t          | t           | t              | t               |                1 | t          | t
 (3 rows)
 
 -- reset stats for all slots
@@ -73,27 +73,27 @@ SELECT pg_stat_reset_replication_slot(NULL);
  
 (1 row)
 
-SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
-       slot_name        | spill_txns | spill_count | total_txns | total_bytes | plugin_sent_txns | plugin_sent_bytes | plugin_filtered_bytes 
-------------------------+------------+-------------+------------+-------------+------------------+-------------------+-----------------------
- regression_slot_stats1 | t          | t           | f          | f           |                  |                   |                      
- regression_slot_stats2 | t          | t           | f          | f           |                  |                   |                      
- regression_slot_stats3 | t          | t           | f          | f           |                  |                   |                      
+SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
+       slot_name        | spill_txns | spill_count | total_wal_txns | total_wal_bytes | plugin_sent_txns | plugin_sent_bytes | plugin_filtered_bytes 
+------------------------+------------+-------------+----------------+-----------------+------------------+-------------------+-----------------------
+ regression_slot_stats1 | t          | t           | f              | f               |                  |                   |                      
+ regression_slot_stats2 | t          | t           | f              | f               |                  |                   |                      
+ regression_slot_stats3 | t          | t           | f              | f               |                  |                   |                      
 (3 rows)
 
 -- verify accessing/resetting stats for non-existent slot does something reasonable
 SELECT * FROM pg_stat_get_replication_slot('do-not-exist');
-  slot_name   | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_txns | total_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset 
---------------+------------+-------------+-------------+-------------+--------------+--------------+------------+-------------+-----------------------+------------------+-------------------+-------------
- do-not-exist |          0 |           0 |           0 |           0 |            0 |            0 |          0 |           0 |                       |                  |                   | 
+  slot_name   | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_wal_txns | total_wal_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset 
+--------------+------------+-------------+-------------+-------------+--------------+--------------+----------------+-----------------+-----------------------+------------------+-------------------+-------------
+ do-not-exist |          0 |           0 |           0 |           0 |            0 |            0 |              0 |               0 |                       |                  |                   | 
 (1 row)
 
 SELECT pg_stat_reset_replication_slot('do-not-exist');
 ERROR:  replication slot "do-not-exist" does not exist
 SELECT * FROM pg_stat_get_replication_slot('do-not-exist');
-  slot_name   | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_txns | total_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset 
---------------+------------+-------------+-------------+-------------+--------------+--------------+------------+-------------+-----------------------+------------------+-------------------+-------------
- do-not-exist |          0 |           0 |           0 |           0 |            0 |            0 |          0 |           0 |                       |                  |                   | 
+  slot_name   | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_wal_txns | total_wal_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset 
+--------------+------------+-------------+-------------+-------------+--------------+--------------+----------------+-----------------+-----------------------+------------------+-------------------+-------------
+ do-not-exist |          0 |           0 |           0 |           0 |            0 |            0 |              0 |               0 |                       |                  |                   | 
 (1 row)
 
 -- spilling the xact
diff --git a/contrib/test_decoding/sql/stats.sql b/contrib/test_decoding/sql/stats.sql
index 1077cea5855..99f513902d3 100644
--- a/contrib/test_decoding/sql/stats.sql
+++ b/contrib/test_decoding/sql/stats.sql
@@ -15,21 +15,22 @@ SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats1', NULL,
 SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats2', NULL, NULL, 'skip-empty-xacts', '1');
 SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats3', NULL, NULL, 'skip-empty-xacts', '1');
 SELECT pg_stat_force_next_flush();
--- total_txns may vary based on the background activity but sent_txns should
--- always be 1 since the background transactions are always skipped. Filtered
--- bytes would be set only when there's a change that was passed to the plugin
--- but was filtered out. Depending upon the background transactions, filtered
--- bytes may or may not be zero.
-SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
+
+-- total_wal_txns may vary based on the background activity but plugin_sent_txns
+-- should always be 1 since the background transactions are always skipped.
+-- Filtered bytes would be set only when there's a change that was passed to the
+-- plugin but was filtered out. Depending upon the background transactions,
+-- filtered bytes may or may not be zero.
+SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
 RESET logical_decoding_work_mem;
 
 -- reset stats for one slot, others should be unaffected
 SELECT pg_stat_reset_replication_slot('regression_slot_stats1');
-SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
+SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
 
 -- reset stats for all slots
 SELECT pg_stat_reset_replication_slot(NULL);
-SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
+SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name;
 
 -- verify accessing/resetting stats for non-existent slot does something reasonable
 SELECT * FROM pg_stat_get_replication_slot('do-not-exist');
diff --git a/contrib/test_decoding/t/001_repl_stats.pl b/contrib/test_decoding/t/001_repl_stats.pl
index 76dd86fc420..756fc691ed6 100644
--- a/contrib/test_decoding/t/001_repl_stats.pl
+++ b/contrib/test_decoding/t/001_repl_stats.pl
@@ -28,8 +28,8 @@ sub test_slot_stats
 	# guaranteed that such transactions would be present.
 	my $result = $node->safe_psql(
 		'postgres', qq[
-		SELECT slot_name, total_txns > 0 AS total_txn,
-			   total_bytes > 0 AS total_bytes,
+		SELECT slot_name, total_wal_txns > 0 AS total_txn,
+			   total_wal_bytes > 0 AS total_bytes,
 			   plugin_sent_txns > 0 AS sent_txn,
 			   plugin_sent_bytes > 0 AS sent_bytes,
 			   plugin_filtered_bytes >= 0 AS filtered_bytes
@@ -71,7 +71,7 @@ $node->poll_query_until(
 	'postgres', qq[
 	SELECT count(slot_name) >= 4 FROM pg_stat_replication_slots
 	WHERE slot_name ~ 'regression_slot'
-	AND total_txns > 0 AND total_bytes > 0;
+	AND total_wal_txns > 0 AND total_wal_bytes > 0;
 ]) or die "Timed out while waiting for statistics to be updated";
 
 # Test to drop one of the replication slot and verify replication statistics data is
diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml
index 8ac10cda90c..3952f68e806 100644
--- a/doc/src/sgml/logicaldecoding.sgml
+++ b/doc/src/sgml/logicaldecoding.sgml
@@ -956,11 +956,11 @@ typedef struct OutputPluginStats
 } OutputPluginStats;
 </programlisting>
       <literal>sentTxns</literal> is the number of transactions sent downstream
-      by the output plugin. <literal>sentBytes</literal> is the amount of data
+      by the output plugin. <literal>sentBytes</literal> is the amount of data, in bytes,
       sent downstream by the output plugin.
-      <function>OutputPluginWrite</function> is expected to update this counter
+      <function>OutputPluginWrite</function> will update this counter
       if <literal>ctx-&gt;stats</literal> is initialized by the output plugin.
-      <literal>filteredBytes</literal> is the size of changes in bytes that are
+      <literal>filteredBytes</literal> is the size of changes, in bytes, that are
       filtered out by the output plugin. Function
       <literal>ReorderBufferChangeSize</literal> may be used to find the size of
       filtered <literal>ReorderBufferChange</literal>.
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index e121f55c9c2..fbe03ffd670 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1633,19 +1633,19 @@ description | Waiting for a newly initialized WAL file to reach durable storage
 
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
-        <structfield>total_txns</structfield> <type>bigint</type>
+        <structfield>total_wal_txns</structfield> <type>bigint</type>
        </para>
        <para>
-        Number of decoded transactions sent to the decoding output plugin for
-        this slot. This counts top-level transactions only, and is not incremented
-        for subtransactions. Note that this includes the transactions that are
-        streamed and/or spilled.
+        Number of decoded transactions from WAL sent to the decoding output
+        plugin for this slot. This counts top-level transactions only, and is
+        not incremented for subtransactions. Note that this includes the
+        transactions that are streamed and/or spilled.
        </para></entry>
      </row>
 
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
-        <structfield>total_bytes</structfield><type>bigint</type>
+        <structfield>total_wal_bytes</structfield><type>bigint</type>
        </para>
        <para>
         Amount of transaction data decoded for sending transactions to the
@@ -1660,9 +1660,9 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         <structfield>plugin_filtered_bytes</structfield> <type>bigint</type>
        </para>
        <para>
-        Amount of changes, from <structfield>total_bytes</structfield>, filtered
+        Amount of changes, from <structfield>total_wal_bytes</structfield>, filtered
         out by the output plugin and not sent downstream. Please note that it
-        does not include the changes filtered before a change is handed over to
+        does not include the changes filtered before a change is sent to
         the output plugin, e.g. the changes filtered by origin. The count is
         maintained by the output plugin mentioned in
         <structfield>plugin</structfield>. It is NULL when statistics is not
@@ -1680,7 +1680,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
         counts top-level transactions only, and is not incremented for
         subtransactions. These transactions are subset of transctions sent to
         the decoding plugin. Hence this count is expected to be lesser than or
-        equal to <structfield>total_txns</structfield>.  The count is maintained
+        equal to <structfield>total_wal_txns</structfield>.  The count is maintained
         by the output plugin mentioned in <structfield>plugin</structfield>.  It
         is NULL when statistics is not initialized or immediately after a reset or
         when not maintained by the output plugin.
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index d38c21150b0..9e8e32b5849 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1060,8 +1060,8 @@ CREATE VIEW pg_stat_replication_slots AS
             s.stream_txns,
             s.stream_count,
             s.stream_bytes,
-            s.total_txns,
-            s.total_bytes,
+            s.total_wal_txns,
+            s.total_wal_bytes,
             s.plugin_filtered_bytes,
             s.plugin_sent_txns,
             s.plugin_sent_bytes,
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 796dacddcfb..15bafe63b24 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2125,9 +2125,9 @@ pg_stat_get_replication_slot(PG_FUNCTION_ARGS)
 					   INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stream_bytes",
 					   INT8OID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 8, "total_txns",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 8, "total_wal_txns",
 					   INT8OID, -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 9, "total_bytes",
+	TupleDescInitEntry(tupdesc, (AttrNumber) 9, "total_wal_bytes",
 					   INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 10, "plugin_filtered_bytes",
 					   INT8OID, -1, 0);
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 7519941bcf3..9e4f6620214 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5689,7 +5689,7 @@
   proparallel => 'r', prorettype => 'record', proargtypes => 'text',
   proallargtypes => '{text,text,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz}',
   proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,total_txns,total_bytes,plugin_filtered_bytes,plugin_sent_txns,plugin_sent_bytes,stats_reset}',
+  proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,total_wal_txns,total_wal_bytes,plugin_filtered_bytes,plugin_sent_txns,plugin_sent_bytes,stats_reset}',
   prosrc => 'pg_stat_get_replication_slot' },
 
 { oid => '6230', descr => 'statistics: check if a stats object exists',
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 2a048af3569..2a401552a7a 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2139,14 +2139,14 @@ pg_stat_replication_slots| SELECT s.slot_name,
     s.stream_txns,
     s.stream_count,
     s.stream_bytes,
-    s.total_txns,
-    s.total_bytes,
+    s.total_wal_txns,
+    s.total_wal_bytes,
     s.plugin_filtered_bytes,
     s.plugin_sent_txns,
     s.plugin_sent_bytes,
     s.stats_reset
    FROM pg_replication_slots r,
-    LATERAL pg_stat_get_replication_slot((r.slot_name)::text) s(slot_name, spill_txns, spill_count, spill_bytes, stream_txns, stream_count, stream_bytes, total_txns, total_bytes, plugin_filtered_bytes, plugin_sent_txns, plugin_sent_bytes, stats_reset)
+    LATERAL pg_stat_get_replication_slot((r.slot_name)::text) s(slot_name, spill_txns, spill_count, spill_bytes, stream_txns, stream_count, stream_bytes, total_wal_txns, total_wal_bytes, plugin_filtered_bytes, plugin_sent_txns, plugin_sent_bytes, stats_reset)
   WHERE (r.datoid IS NOT NULL);
 pg_stat_slru| SELECT name,
     blks_zeroed,
-- 
2.34.1

