Subject: Function for listing pg_wal/summaries directory

From: btogiwarayuushi <[email-masked]>
Date: Fri, 04 Oct 2024 11:32:08 +0900

Hi,

While WAL summaries feature and some support functions have been added 
in version 17, merely listing the contents of the pg_wal/summaries 
directory is missing. As discussed in the pg_ls_archive_status() 
discussion, it would be convenient to add pg_ls_summariesdir() that 
lists the contents of the pg_wal/summaries directory with the pg_monitor 
role.

This patch is based on a very recent master and does not include the 
catversion bump.

Best,
Yushi

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index d6acdd3059..1b7f5c3a12 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -30530,6 +30530,30 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size
        </para></entry>
       </row>
 
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>pg_ls_summariesdir</primary>
+        </indexterm>
+        <function>pg_ls_summariesdir</function> ()
+        <returnvalue>setof record</returnvalue>
+        ( <parameter>name</parameter> <type>text</type>,
+        <parameter>size</parameter> <type>bigint</type>,
+        <parameter>modification</parameter> <type>timestamp with time zone</type> )
+       </para>
+       <para>
+        Returns the name, size, and last modification time (mtime) of each
+        ordinary file in the server's WAL summary directory
+        (<filename>pg_wal/summaries</filename>).  Filenames beginning
+        with a dot, directories, and other special files are excluded.
+       </para>
+       <para>
+        This function is restricted to superusers and members of
+        the <literal>pg_monitor</literal> role by default, but other users can
+        be granted EXECUTE to run the function.
+       </para></entry>
+      </row>
+
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql
index b0d0de051e..fd6b606ae9 100644
--- a/src/backend/catalog/system_functions.sql
+++ b/src/backend/catalog/system_functions.sql
@@ -700,6 +700,8 @@ REVOKE EXECUTE ON FUNCTION pg_ls_waldir() FROM public;
 
 REVOKE EXECUTE ON FUNCTION pg_ls_archive_statusdir() FROM public;
 
+REVOKE EXECUTE ON FUNCTION pg_ls_summariesdir() FROM public;
+
 REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir() FROM public;
 
 REVOKE EXECUTE ON FUNCTION pg_ls_tmpdir(oid) FROM public;
@@ -770,6 +772,8 @@ GRANT EXECUTE ON FUNCTION pg_ls_waldir() TO pg_monitor;
 
 GRANT EXECUTE ON FUNCTION pg_ls_archive_statusdir() TO pg_monitor;
 
+GRANT EXECUTE ON FUNCTION pg_ls_summariesdir() TO pg_monitor;
+
 GRANT EXECUTE ON FUNCTION pg_ls_tmpdir() TO pg_monitor;
 
 GRANT EXECUTE ON FUNCTION pg_ls_tmpdir(oid) TO pg_monitor;
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index 24b95c32b7..d84ed8970e 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -689,6 +689,15 @@ pg_ls_archive_statusdir(PG_FUNCTION_ARGS)
 	return pg_ls_dir_files(fcinfo, XLOGDIR "/archive_status", true);
 }
 
+/*
+ * Function to return the list of files in the WAL summary directory.
+ */
+Datum
+pg_ls_summariesdir(PG_FUNCTION_ARGS)
+{
+	return pg_ls_dir_files(fcinfo, XLOGDIR "/summaries", true);
+}
+
 /*
  * Function to return the list of files in the PG_LOGICAL_SNAPSHOTS_DIR
  * directory.
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 77f54a79e6..a3035559b6 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12173,6 +12173,12 @@
   provolatile => 'v', prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,timestamptz}', proargmodes => '{o,o,o}',
   proargnames => '{name,size,modification}', prosrc => 'pg_ls_waldir' },
+{ oid => '5101', descr => 'list of files in the summaries directory',
+  proname => 'pg_ls_summariesdir', procost => '10', prorows => '20',
+  proretset => 't', provolatile => 'v', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
+  proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
+  prosrc => 'pg_ls_summariesdir' },
 { oid => '5031', descr => 'list of files in the archive_status directory',
   proname => 'pg_ls_archive_statusdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index 5f7bf6b8af..36b1201f9f 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -412,6 +412,12 @@ select count(*) >= 0 as ok from pg_ls_archive_statusdir();
  t
 (1 row)
 
+select count(*) >= 0 as ok from pg_ls_summariesdir();
+ ok 
+----
+ t
+(1 row)
+
 -- pg_read_file()
 select length(pg_read_file('postmaster.pid')) > 20;
  ?column? 
diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql
index 1e90d60af3..b7495d70eb 100644
--- a/src/test/regress/sql/misc_functions.sql
+++ b/src/test/regress/sql/misc_functions.sql
@@ -163,6 +163,7 @@ select (w).size = :segsize as ok
 from (select pg_ls_waldir() w) ss where length((w).name) = 24 limit 1;
 
 select count(*) >= 0 as ok from pg_ls_archive_statusdir();
+select count(*) >= 0 as ok from pg_ls_summariesdir();
 
 -- pg_read_file()
 select length(pg_read_file('postmaster.pid')) > 20;