0001-Hide-duplicate-names-from-extension-views.patch
text/plain
Filename: 0001-Hide-duplicate-names-from-extension-views.patch
Type: text/plain
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Hide duplicate names from extension views
| File | + | − |
|---|---|---|
| doc/src/sgml/config.sgml | 6 | 0 |
| src/backend/commands/extension.c | 24 | 0 |
| src/test/modules/test_extensions/t/001_extension_control_path.pl | 6 | 3 |
From a0064ef26339482c8982c4b299f221316fa5a2d8 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Thu, 11 Sep 2025 15:41:29 +0200
Subject: [PATCH] Hide duplicate names from extension views
If extensions of equal names were installed in different directories
in the path, the views pg_available_extensions and
pg_available_extension_versions would show all of them, even though
only the first one was actually reachable by CREATE EXTENSION. To
fix, have those views skip extensions found later in the path if they
have names already found earlier.
Also add a bit of documentation that only the first extension in the
path can be used.
Reported-by: Pierrick <pierrick.chovelon@dalibo.com>
Discussion: https://www.postgresql.org/message-id/flat/8f5a0517-1cb8-4085-ae89-77e7454e27ba%40dalibo.com
---
doc/src/sgml/config.sgml | 6 +++++
src/backend/commands/extension.c | 24 +++++++++++++++++++
.../t/001_extension_control_path.pl | 9 ++++---
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d1e103ed779..5aea6cc2fe8 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -11057,6 +11057,12 @@ <title>Other Defaults</title>
string, the default <literal>'$system'</literal> is also assumed.
</para>
+ <para>
+ If extensions with equal names are present in multiple directories in
+ the configured path, only the instance found first in the path will be
+ used.
+ </para>
+
<para>
This parameter can be changed at run time by superusers and users
with the appropriate <literal>SET</literal> privilege, but a
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index e6f9ab6dfd6..93ef1ad106f 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2208,6 +2208,7 @@ pg_available_extensions(PG_FUNCTION_ARGS)
List *locations;
DIR *dir;
struct dirent *de;
+ List *found_ext = NIL;
/* Build tuplestore to hold the result rows */
InitMaterializedSRF(fcinfo, 0);
@@ -2232,6 +2233,7 @@ pg_available_extensions(PG_FUNCTION_ARGS)
{
ExtensionControlFile *control;
char *extname;
+ String *extname_str;
Datum values[3];
bool nulls[3];
@@ -2246,6 +2248,16 @@ pg_available_extensions(PG_FUNCTION_ARGS)
if (strstr(extname, "--"))
continue;
+ /*
+ * Ignore already-found names. They are not reachable by the
+ * path search, so don't shown them.
+ */
+ extname_str = makeString(extname);
+ if (list_member(found_ext, extname_str))
+ continue;
+ else
+ found_ext = lappend(found_ext, extname_str);
+
control = new_ExtensionControlFile(extname);
control->control_dir = pstrdup(location);
parse_extension_control_file(control, NULL);
@@ -2294,6 +2306,7 @@ pg_available_extension_versions(PG_FUNCTION_ARGS)
List *locations;
DIR *dir;
struct dirent *de;
+ List *found_ext = NIL;
/* Build tuplestore to hold the result rows */
InitMaterializedSRF(fcinfo, 0);
@@ -2318,6 +2331,7 @@ pg_available_extension_versions(PG_FUNCTION_ARGS)
{
ExtensionControlFile *control;
char *extname;
+ String *extname_str;
if (!is_extension_control_filename(de->d_name))
continue;
@@ -2330,6 +2344,16 @@ pg_available_extension_versions(PG_FUNCTION_ARGS)
if (strstr(extname, "--"))
continue;
+ /*
+ * Ignore already-found names. They are not reachable by the
+ * path search, so don't shown them.
+ */
+ extname_str = makeString(extname);
+ if (list_member(found_ext, extname_str))
+ continue;
+ else
+ found_ext = lappend(found_ext, extname_str);
+
/* read the control file */
control = new_ExtensionControlFile(extname);
control->control_dir = pstrdup(location);
diff --git a/src/test/modules/test_extensions/t/001_extension_control_path.pl b/src/test/modules/test_extensions/t/001_extension_control_path.pl
index 1a9c97bbf4d..7fbe5bde332 100644
--- a/src/test/modules/test_extensions/t/001_extension_control_path.pl
+++ b/src/test/modules/test_extensions/t/001_extension_control_path.pl
@@ -11,12 +11,15 @@
$node->init;
-# Create a temporary directory for the extension control file
+# Create temporary directories for the extension control files
my $ext_dir = PostgreSQL::Test::Utils::tempdir();
mkpath("$ext_dir/extension");
+my $ext_dir2 = PostgreSQL::Test::Utils::tempdir();
+mkpath("$ext_dir2/extension");
my $ext_name = "test_custom_ext_paths";
create_extension($ext_name, $ext_dir);
+create_extension($ext_name, $ext_dir2);
my $ext_name2 = "test_custom_ext_paths_using_directory";
mkpath("$ext_dir/$ext_name2");
@@ -26,7 +29,7 @@
my $sep = $windows_os ? ";" : ":";
$node->append_conf(
'postgresql.conf', qq{
-extension_control_path = '\$system$sep@{[ $windows_os ? ($ext_dir =~ s/\\/\\\\/gr) : $ext_dir ]}'
+extension_control_path = '\$system$sep@{[ $windows_os ? ($ext_dir =~ s/\\/\\\\/gr) : $ext_dir ]}$sep@{[ $windows_os ? ($ext_dir2 =~ s/\\/\\\\/gr) : $ext_dir2 ]}'
});
# Start node
@@ -34,7 +37,7 @@
my $ecp = $node->safe_psql('postgres', 'show extension_control_path;');
-is($ecp, "\$system$sep$ext_dir",
+is($ecp, "\$system$sep$ext_dir$sep$ext_dir2",
"custom extension control directory path configured");
$node->safe_psql('postgres', "CREATE EXTENSION $ext_name");
base-commit: 3e43a7b1ab971ed22e663891d941d4d00b6dd9fe
--
2.51.0