From f87a11adfa95475ae9da2b487b2ebbc21e065e36 Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Mon, 9 Mar 2020 01:00:42 -0500
Subject: [PATCH v31 05/11] pg_ls_*dir to show directories and "isdir" column..

pg_ls_logdir, pg_ls_waldir, pg_ls_archive_statusdir, ...

Need catversion bump
---
 doc/src/sgml/func.sgml                       | 36 ++++++++++++--------
 src/backend/utils/adt/genfile.c              | 21 +++++-------
 src/include/catalog/pg_proc.dat              | 26 +++++++-------
 src/test/regress/expected/misc_functions.out |  4 +--
 4 files changed, 45 insertions(+), 42 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 9ddd23f90e..77547aa7cd 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -25871,7 +25871,8 @@ postgres=# SELECT * FROM pg_walfile_name_offset(pg_stop_backup());
         <returnvalue>setof record</returnvalue>
         ( <parameter>filename</parameter> <type>text</type>,
         <parameter>size</parameter> <type>bigint</type>,
-        <parameter>modification</parameter> <type>timestamp with time zone</type> )
+        <parameter>modification</parameter> <type>timestamp with time zone</type>,
+        <parameter>isdir</parameter> <type>boolean</type> )
        </para>
        <para>
         For each file in the specified directory, list the file and its
@@ -27270,12 +27271,14 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size
         <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> )
+        <parameter>modification</parameter> <type>timestamp with time zone</type>,
+        <parameter>isdir</parameter> <type>boolean</type> )
        </para>
        <para>
-        Returns the name, size, and last modification time (mtime) of each
-        ordinary file in the server's log directory.  Filenames beginning with
-        a dot, directories, and other special files are excluded.
+        For each file in the server's log directory,
+        return the file's name, size, last modification time (mtime), and a boolean
+        indicating if the file is a directory.
+        Filenames beginning with a dot and special file types are excluded.
        </para>
        <para>
         This function is restricted to superusers and members of
@@ -27293,13 +27296,14 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size
         <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> )
+        <parameter>modification</parameter> <type>timestamp with time zone</type>,
+        <parameter>isdir</parameter> <type>boolean</type> )
        </para>
        <para>
-        Returns the name, size, and last modification time (mtime) of each
-        ordinary file in the server's write-ahead log (WAL) directory.
-        Filenames beginning with a dot, directories, and other special files
-        are excluded.
+        For each file in the server's write-ahead log (WAL) directory, list the
+        file's name, size, last modification time (mtime), and a boolean
+        indicating if the file is a directory.
+        Filenames beginning with a dot and special files types are excluded.
        </para>
        <para>
         This function is restricted to superusers and members of
@@ -27317,13 +27321,15 @@ SELECT pg_size_pretty(sum(pg_relation_size(relid))) AS total_size
         <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> )
+        <parameter>modification</parameter> <type>timestamp with time zone</type>,
+        <parameter>isdir</parameter> <type>boolean</type> )
        </para>
        <para>
-        Returns the name, size, and last modification time (mtime) of each
-        ordinary file in the server's WAL archive status directory
-        (<filename>pg_wal/archive_status</filename>).  Filenames beginning
-        with a dot, directories, and other special files are excluded.
+        For each file in the server's WAL archive status directory
+        (<filename>pg_wal/archive_status</filename>), list the file's
+        name, size, last modification time (mtime), and a boolean indicating if
+        the file is a directory.
+        Filenames beginning with a dot and special file types are excluded.
        </para>
        <para>
         This function is restricted to superusers and members of
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index d6be8cef6e..eed71892bd 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -47,11 +47,8 @@ static Datum pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, int flags
 #define	LS_DIR_SKIP_DIRS			(1<<5) /* Do not show directories */
 #define	LS_DIR_SKIP_SPECIAL			(1<<6) /* Do not show special file types */
 
-/*
- * Shortcut for the historic behavior of the pg_ls_* functions (not including
- * pg_ls_dir, which skips different files and doesn't show metadata).
- */
-#define LS_DIR_HISTORIC				(LS_DIR_SKIP_DIRS | LS_DIR_SKIP_HIDDEN | LS_DIR_SKIP_SPECIAL | LS_DIR_METADATA)
+/* Shortcut for common behavior */
+#define LS_DIR_COMMON				(LS_DIR_SKIP_HIDDEN | LS_DIR_SKIP_SPECIAL | LS_DIR_METADATA)
 
 /*
  * Convert a "text" filename argument to C string, and check it's allowable.
@@ -683,14 +680,14 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, int flags)
 Datum
 pg_ls_logdir(PG_FUNCTION_ARGS)
 {
-	return pg_ls_dir_files(fcinfo, Log_directory, LS_DIR_HISTORIC);
+	return pg_ls_dir_files(fcinfo, Log_directory, LS_DIR_COMMON);
 }
 
 /* Function to return the list of files in the WAL directory */
 Datum
 pg_ls_waldir(PG_FUNCTION_ARGS)
 {
-	return pg_ls_dir_files(fcinfo, XLOGDIR, LS_DIR_HISTORIC);
+	return pg_ls_dir_files(fcinfo, XLOGDIR, LS_DIR_COMMON);
 }
 
 /*
@@ -709,7 +706,7 @@ pg_ls_tmpdir(FunctionCallInfo fcinfo, Oid tblspc)
 
 	TempTablespacePath(path, tblspc);
 	return pg_ls_dir_files(fcinfo, path,
-			LS_DIR_SKIP_HIDDEN | LS_DIR_SKIP_SPECIAL | LS_DIR_ISDIR | LS_DIR_METADATA | LS_DIR_MISSING_OK);
+			LS_DIR_COMMON | LS_DIR_MISSING_OK);
 }
 
 /*
@@ -739,7 +736,7 @@ Datum
 pg_ls_archive_statusdir(PG_FUNCTION_ARGS)
 {
 	return pg_ls_dir_files(fcinfo, XLOGDIR "/archive_status",
-			LS_DIR_HISTORIC | LS_DIR_MISSING_OK);
+			LS_DIR_COMMON | LS_DIR_MISSING_OK);
 }
 
 /*
@@ -775,7 +772,7 @@ pg_ls_dir_metadata_1arg(PG_FUNCTION_ARGS)
 Datum
 pg_ls_logicalsnapdir(PG_FUNCTION_ARGS)
 {
-	return pg_ls_dir_files(fcinfo, "pg_logical/snapshots", LS_DIR_HISTORIC);
+	return pg_ls_dir_files(fcinfo, "pg_logical/snapshots", LS_DIR_COMMON);
 }
 
 /*
@@ -784,7 +781,7 @@ pg_ls_logicalsnapdir(PG_FUNCTION_ARGS)
 Datum
 pg_ls_logicalmapdir(PG_FUNCTION_ARGS)
 {
-	return pg_ls_dir_files(fcinfo, "pg_logical/mappings", LS_DIR_HISTORIC);
+	return pg_ls_dir_files(fcinfo, "pg_logical/mappings", LS_DIR_COMMON);
 }
 
 /*
@@ -809,5 +806,5 @@ pg_ls_replslotdir(PG_FUNCTION_ARGS)
 						slotname)));
 
 	snprintf(path, sizeof(path), "pg_replslot/%s", slotname);
-	return pg_ls_dir_files(fcinfo, path, LS_DIR_HISTORIC);
+	return pg_ls_dir_files(fcinfo, path, LS_DIR_COMMON);
 }
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 3ffdcaf3a7..b442ca1130 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -11599,18 +11599,18 @@
 { oid => '3353', descr => 'list files in the log directory',
   proname => 'pg_ls_logdir', 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_logdir' },
+  proallargtypes => '{text,int8,timestamptz,bool}', proargmodes => '{o,o,o,o}',
+  proargnames => '{name,size,modification,isdir}', prosrc => 'pg_ls_logdir' },
 { oid => '3354', descr => 'list of files in the WAL directory',
   proname => 'pg_ls_waldir', 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_waldir' },
+  proallargtypes => '{text,int8,timestamptz,bool}', proargmodes => '{o,o,o,o}',
+  proargnames => '{name,size,modification,isdir}', prosrc => 'pg_ls_waldir' },
 { 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',
-  proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
-  proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
+  proargtypes => '', proallargtypes => '{text,int8,timestamptz,bool}',
+  proargmodes => '{o,o,o,o}', proargnames => '{name,size,modification,isdir}',
   prosrc => 'pg_ls_archive_statusdir' },
 { oid => '5029', descr => 'list files in the pgsql_tmp directory',
   proname => 'pg_ls_tmpdir', procost => '10', prorows => '20', proretset => 't',
@@ -11627,23 +11627,23 @@
   descr => 'list of files in the pg_logical/snapshots directory',
   proname => 'pg_ls_logicalsnapdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
-  proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
+  proargtypes => '', proallargtypes => '{text,int8,timestamptz,bool}',
+  proargmodes => '{o,o,o,o}', proargnames => '{name,size,modification,isdir}',
   prosrc => 'pg_ls_logicalsnapdir' },
 { oid => '9859',
   descr => 'list of files in the pg_logical/mappings directory',
   proname => 'pg_ls_logicalmapdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{text,int8,timestamptz}',
-  proargmodes => '{o,o,o}', proargnames => '{name,size,modification}',
+  proargtypes => '', proallargtypes => '{text,int8,timestamptz,bool}',
+  proargmodes => '{o,o,o,o}', proargnames => '{name,size,modification,isdir}',
   prosrc => 'pg_ls_logicalmapdir' },
 { oid => '9860',
   descr => 'list of files in the pg_replslot/slot_name directory',
   proname => 'pg_ls_replslotdir', procost => '10', prorows => '20',
   proretset => 't', provolatile => 'v', prorettype => 'record',
-  proargtypes => 'text', proallargtypes => '{text,text,int8,timestamptz}',
-  proargmodes => '{i,o,o,o}',
-  proargnames => '{slot_name,name,size,modification}',
+  proargtypes => 'text', proallargtypes => '{text,text,int8,timestamptz,bool}',
+  proargmodes => '{i,o,o,o,o}',
+  proargnames => '{slot_name,name,size,modification,isdir}',
   prosrc => 'pg_ls_replslotdir' },
 { oid => '8450', descr => 'list directory with metadata',
   proname => 'pg_ls_dir_metadata', procost => '10', prorows => '20', proretset => 't',
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index a2bec47d76..25492860bd 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -199,8 +199,8 @@ select count(*) > 0 as ok from (select pg_ls_waldir()) ss;
 
 -- Test not-run-to-completion cases.
 select * from pg_ls_waldir() limit 0;
- name | size | modification 
-------+------+--------------
+ name | size | modification | isdir 
+------+------+--------------+-------
 (0 rows)
 
 select count(*) > 0 as ok from (select * from pg_ls_waldir() limit 1) ss;
-- 
2.17.0

