public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v17 07/10] Add pg_ls_dir_recurse to show dir recursively..
2+ messages / 2 participants
[nested] [flat]

* [PATCH v17 07/10] Add pg_ls_dir_recurse to show dir recursively..
@ 2020-03-09 03:52  Justin Pryzby <[email protected]>
  0 siblings, 0 replies; 2+ messages in thread

From: Justin Pryzby @ 2020-03-09 03:52 UTC (permalink / raw)

..possibly there's a better place to put this, like maybe a doc-only example ?

Need catversion bumped ?
---
 doc/src/sgml/func.sgml                       | 32 ++++++++++++++++++++
 src/backend/catalog/system_views.sql         |  1 +
 src/include/catalog/pg_proc.dat              |  6 ++++
 src/test/regress/expected/misc_functions.out | 14 +++++++++
 src/test/regress/sql/misc_functions.sql      |  6 ++++
 5 files changed, 59 insertions(+)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 8e0de7c02d..334b6beb3a 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -25738,6 +25738,38 @@ 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_dir_recurse</primary>
+        </indexterm>
+        <function>pg_ls_dir_recurse</function> ( <parameter>dirname</parameter> <type>text</type> )
+        <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>isdir</parameter> <type>boolean</type> )
+       </para>
+       <para>
+        Recursively list each file in the specified directory, along with the
+        files' metadata.
+       </para>
+       <para>
+        Restricted to superusers by default, but other users can be granted
+        EXECUTE to run the function.
+       </para></entry>
+      </row>
+
+   <!--para>
+    To recursively list temporary directories in all tablespaces:
+<programlisting>
+SELECT * FROM (SELECT DISTINCT COALESCE(NULLIF(pg_tablespace_location(b.oid),'')||suffix, 'base/pgsql_tmp') AS dir
+FROM pg_tablespace b, pg_control_system() pcs,
+LATERAL format('/PG_%s_%s', left(current_setting('server_version_num'), 2), pcs.catalog_version_no) AS suffix) AS dir,
+LATERAL pg_ls_dir_recurse(dir) AS a;
+</programlisting>
+   </para-->
+
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 1c77430f0c..215fba3b7d 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1468,6 +1468,7 @@ REVOKE EXECUTE ON FUNCTION pg_stat_file(text,boolean) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_ls_dir(text) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_ls_dir(text,boolean,boolean) FROM public;
 REVOKE EXECUTE ON FUNCTION pg_ls_dir_metadata(text,boolean,boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_ls_dir_recurse(text) FROM public;
 
 --
 -- We also set up some things as accessible to standard roles.
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index adfce45d1a..f94f403475 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -10916,6 +10916,12 @@
   proallargtypes => '{text,text,int8,timestamptz,bool}', proargmodes => '{i,o,o,o,o}',
   proargnames => '{dirname,name,size,modification,isdir}',
   prosrc => 'pg_ls_dir_metadata_1arg' },
+{ oid => '5034', descr => 'list all files in a directory recursively',
+  proname => 'pg_ls_dir_recurse', prorows => '10000', proretset => 't',
+  provolatile => 'v', prorettype => 'record', proargtypes => 'text',
+  proallargtypes => '{text,text,int8,timestamptz,bool}',
+  proargnames => '{dirname,name,size,modification,isdir}', proargmodes => '{i,o,o,o,o}',
+  prolang => 'sql', prosrc => "with recursive ls as (select * from pg_ls_dir_metadata(dirname, true, false) union all select ls.name||'/'||a.name, a.size, a.modification, a.isdir from ls, lateral pg_ls_dir_metadata(dirname||'/'||ls.name, false, false)a where ls.isdir) select * from ls" },
 
 # hash partitioning constraint function
 { oid => '5028', descr => 'hash partition CHECK constraint',
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index 64b1417fb8..4188d684f0 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -243,6 +243,20 @@ select * from pg_ls_dir_metadata('.') limit 0;
 ------+------+--------------+-------
 (0 rows)
 
+-- Check that we at least succeed in recursing once, and that we don't show the leading dir prefix
+SELECT name, isdir FROM pg_ls_dir_recurse('.') WHERE isdir AND name~'^pg_wal';
+         name          | isdir 
+-----------------------+-------
+ pg_wal                | t
+ pg_wal/archive_status | t
+(2 rows)
+
+-- Check that expected columns are present
+SELECT * FROM pg_ls_dir_recurse('.') LIMIT 0;
+ name | size | modification | isdir 
+------+------+--------------+-------
+(0 rows)
+
 --
 -- Test adding a support function to a subject function
 --
diff --git a/src/test/regress/sql/misc_functions.sql b/src/test/regress/sql/misc_functions.sql
index 372345720d..6041c4f3dc 100644
--- a/src/test/regress/sql/misc_functions.sql
+++ b/src/test/regress/sql/misc_functions.sql
@@ -76,6 +76,12 @@ select name, isdir from pg_ls_dir_metadata('.', false, false) where name='.'; --
 -- Check that expected columns are present
 select * from pg_ls_dir_metadata('.') limit 0;
 
+-- Check that we at least succeed in recursing once, and that we don't show the leading dir prefix
+SELECT name, isdir FROM pg_ls_dir_recurse('.') WHERE isdir AND name~'^pg_wal';
+
+-- Check that expected columns are present
+SELECT * FROM pg_ls_dir_recurse('.') LIMIT 0;
+
 --
 -- Test adding a support function to a subject function
 --
-- 
2.17.0


--4LFBTxd4L5NLO6ly
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="v17-0008-pg_ls_logdir-to-ignore-error-if-initial-top-dir-.patch"



^ permalink  raw  reply  [nested|flat] 2+ messages in thread

* A few pg_locale.c fixes
@ 2026-01-28 19:37  Jeff Davis <[email protected]>
  0 siblings, 0 replies; 2+ messages in thread

From: Jeff Davis @ 2026-01-28 19:37 UTC (permalink / raw)
  To: pgsql-hackers

Attached patches.

Problems found with AI assistance. Patches by me.

Regards,
	Jeff Davis



Attachments:

  [text/x-patch] v1-0001-Fix-memory-leaks-in-pg_locale_libc.c.patch (1.9K, ../../[email protected]/2-v1-0001-Fix-memory-leaks-in-pg_locale_libc.c.patch)
  download | inline diff:
From f4fd755be542add500aabc23b4255b9ee3631873 Mon Sep 17 00:00:00 2001
From: Jeff Davis <[email protected]>
Date: Tue, 27 Jan 2026 13:39:55 -0800
Subject: [PATCH v1 1/3] Fix memory leaks in pg_locale_libc.c.

---
 src/backend/utils/adt/pg_locale_libc.c | 30 +++++++++++++-------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index 2f96e889595..78f6ea161a0 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -527,11 +527,11 @@ strlower_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 
 	result_size = wchar2char(result, workspace, max_size + 1, loc);
 
-	if (result_size + 1 > destsize)
-		return result_size;
-
-	memcpy(dest, result, result_size);
-	dest[result_size] = '\0';
+	if (destsize >= result_size + 1)
+	{
+		memcpy(dest, result, result_size);
+		dest[result_size] = '\0';
+	}
 
 	pfree(workspace);
 	pfree(result);
@@ -638,11 +638,11 @@ strtitle_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 
 	result_size = wchar2char(result, workspace, max_size + 1, loc);
 
-	if (result_size + 1 > destsize)
-		return result_size;
-
-	memcpy(dest, result, result_size);
-	dest[result_size] = '\0';
+	if (destsize >= result_size + 1)
+	{
+		memcpy(dest, result, result_size);
+		dest[result_size] = '\0';
+	}
 
 	pfree(workspace);
 	pfree(result);
@@ -725,11 +725,11 @@ strupper_libc_mb(char *dest, size_t destsize, const char *src, ssize_t srclen,
 
 	result_size = wchar2char(result, workspace, max_size + 1, loc);
 
-	if (result_size + 1 > destsize)
-		return result_size;
-
-	memcpy(dest, result, result_size);
-	dest[result_size] = '\0';
+	if (destsize >= result_size + 1)
+	{
+		memcpy(dest, result, result_size);
+		dest[result_size] = '\0';
+	}
 
 	pfree(workspace);
 	pfree(result);
-- 
2.43.0



  [text/x-patch] v1-0002-Fix-memory-leaks-in-pg_locale_icu.c.patch (959B, ../../[email protected]/3-v1-0002-Fix-memory-leaks-in-pg_locale_icu.c.patch)
  download | inline diff:
From 1922a118576f9be73018447b6e5531e6571484de Mon Sep 17 00:00:00 2001
From: Jeff Davis <[email protected]>
Date: Tue, 27 Jan 2026 13:50:22 -0800
Subject: [PATCH v1 2/3] Fix memory leaks in pg_locale_icu.c.

---
 src/backend/utils/adt/pg_locale_icu.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/backend/utils/adt/pg_locale_icu.c b/src/backend/utils/adt/pg_locale_icu.c
index 88f86ab18a3..352b4c3885f 100644
--- a/src/backend/utils/adt/pg_locale_icu.c
+++ b/src/backend/utils/adt/pg_locale_icu.c
@@ -597,6 +597,8 @@ make_icu_collator(const char *iculocstr, const char *icurules)
 							iculocstr, icurules, u_errorName(status))));
 		}
 
+		pfree(my_rules);
+		pfree(all_rules);
 		return collator_all_rules;
 	}
 }
@@ -1106,6 +1108,9 @@ strnxfrm_prefix_icu(char *dest, size_t destsize,
 				(errmsg("sort key generation failed: %s",
 						u_errorName(status))));
 
+	if (buf != sbuf)
+		pfree(buf);
+
 	return result_bsize;
 }
 
-- 
2.43.0



  [text/x-patch] v1-0003-pg_locale.c-Clean-up-srclen-1.patch (1.4K, ../../[email protected]/4-v1-0003-pg_locale.c-Clean-up-srclen-1.patch)
  download | inline diff:
From ec6a98973bfca4fd6be8538ec45119c286140082 Mon Sep 17 00:00:00 2001
From: Jeff Davis <[email protected]>
Date: Tue, 27 Jan 2026 14:30:19 -0800
Subject: [PATCH v1 3/3] pg_locale.c: Clean up srclen == -1.

No callers currently specify -1, but the API should handle it
correctly to mean a NUL-termianted string.
---
 src/backend/utils/adt/pg_locale_icu.c  | 1 +
 src/backend/utils/adt/pg_locale_libc.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/backend/utils/adt/pg_locale_icu.c b/src/backend/utils/adt/pg_locale_icu.c
index 352b4c3885f..4659a50cbb8 100644
--- a/src/backend/utils/adt/pg_locale_icu.c
+++ b/src/backend/utils/adt/pg_locale_icu.c
@@ -703,6 +703,7 @@ downcase_ident_icu(char *dst, size_t dstsize, const char *src,
 
 	libc_lower = lt && (pg_database_encoding_max_length() == 1);
 
+	srclen = (srclen >= 0) ? srclen : strlen(src);
 	for (i = 0; i < srclen && i < dstsize; i++)
 	{
 		unsigned char ch = (unsigned char) src[i];
diff --git a/src/backend/utils/adt/pg_locale_libc.c b/src/backend/utils/adt/pg_locale_libc.c
index 78f6ea161a0..5feec161a43 100644
--- a/src/backend/utils/adt/pg_locale_libc.c
+++ b/src/backend/utils/adt/pg_locale_libc.c
@@ -329,6 +329,7 @@ downcase_ident_libc_sb(char *dst, size_t dstsize, const char *src,
 	locale_t	loc = locale->lt;
 	int			i;
 
+	srclen = (srclen >= 0) ? srclen : strlen(src);
 	for (i = 0; i < srclen && i < dstsize; i++)
 	{
 		unsigned char ch = (unsigned char) src[i];
-- 
2.43.0



^ permalink  raw  reply  [nested|flat] 2+ messages in thread


end of thread, other threads:[~2026-01-28 19:37 UTC | newest]

Thread overview: 2+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-03-09 03:52 [PATCH v17 07/10] Add pg_ls_dir_recurse to show dir recursively.. Justin Pryzby <[email protected]>
2026-01-28 19:37 A few pg_locale.c fixes Jeff Davis <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox