v1-0001-Add-extension_directory-GUC.patch
application/octet-stream
Filename: v1-0001-Add-extension_directory-GUC.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v1-0001
Subject: Add extension_directory GUC
| File | + | − |
|---|---|---|
| src/backend/commands/extension.c | 90 | 0 |
| src/backend/utils/fmgr/dfmgr.c | 28 | 1 |
| src/backend/utils/misc/guc_tables.c | 12 | 0 |
| src/backend/utils/misc/postgresql.conf.sample | 2 | 0 |
| src/include/utils/guc.h | 1 | 0 |
From 5d5a0eb568b265bf48664bfa479dee7fd718cf03 Mon Sep 17 00:00:00 2001
From: "David E. Wheeler" <david@justatheory.com>
Date: Wed, 3 Apr 2024 09:27:48 -0400
Subject: [PATCH v1] Add extension_directory GUC
Based on a [patch] by Christophe Berg in the Debian Project, add a new
GUC, `extension_directory`, that prepends a path for extension loading.
This directory is prepended to paths when loading extensions (control
and SQL files), and to the `$libdir` directive when loading modules that
back functions. Changing the configuration requires a server restart,
and is visible only to super users.
[patch]: https://salsa.debian.org/postgresql/postgresql/-/blob/17/debian/patches/extension_destdir?ref_type=heads
---
src/backend/commands/extension.c | 90 +++++++++++++++++++
src/backend/utils/fmgr/dfmgr.c | 29 +++++-
src/backend/utils/misc/guc_tables.c | 12 +++
src/backend/utils/misc/postgresql.conf.sample | 2 +
src/include/utils/guc.h | 1 +
5 files changed, 133 insertions(+), 1 deletion(-)
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 77d8c9e186..fbe0e32aca 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -393,6 +393,16 @@ get_extension_control_filename(const char *extname)
get_share_path(my_exec_path, sharepath);
result = (char *) palloc(MAXPGPATH);
+ /*
+ * If extension_destdir is set, try to find the file there first
+ */
+ if (*extension_destdir != '\0')
+ {
+ snprintf(result, MAXPGPATH, "%s%s/extension/%s.control",
+ extension_destdir, sharepath, extname);
+ if (pg_file_exists(result))
+ return result;
+ }
snprintf(result, MAXPGPATH, "%s/extension/%s.control",
sharepath, extname);
@@ -432,6 +442,16 @@ get_extension_aux_control_filename(ExtensionControlFile *control,
scriptdir = get_extension_script_directory(control);
result = (char *) palloc(MAXPGPATH);
+ /*
+ * If extension_destdir is set, try to find the file there first
+ */
+ if (*extension_destdir != '\0')
+ {
+ snprintf(result, MAXPGPATH, "%s%s/%s--%s.control",
+ extension_destdir, scriptdir, control->name, version);
+ if (pg_file_exists(result))
+ return result;
+ }
snprintf(result, MAXPGPATH, "%s/%s--%s.control",
scriptdir, control->name, version);
@@ -450,6 +470,23 @@ get_extension_script_filename(ExtensionControlFile *control,
scriptdir = get_extension_script_directory(control);
result = (char *) palloc(MAXPGPATH);
+ /*
+ * If extension_destdir is set, try to find the file there first
+ */
+ if (*extension_destdir != '\0')
+ {
+ if (from_version)
+ snprintf(result, MAXPGPATH, "%s%s/%s--%s--%s.sql",
+ extension_destdir, scriptdir, control->name, from_version, version);
+ else
+ snprintf(result, MAXPGPATH, "%s%s/%s--%s.sql",
+ extension_destdir, scriptdir, control->name, version);
+ if (pg_file_exists(result))
+ {
+ pfree(scriptdir);
+ return result;
+ }
+ }
if (from_version)
snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
scriptdir, control->name, from_version, version);
@@ -1209,6 +1246,59 @@ get_ext_ver_list(ExtensionControlFile *control)
DIR *dir;
struct dirent *de;
+ /*
+ * If extension_destdir is set, try to find the files there first
+ */
+ if (*extension_destdir != '\0')
+ {
+ char location[MAXPGPATH];
+
+ snprintf(location, MAXPGPATH, "%s%s", extension_destdir,
+ get_extension_script_directory(control));
+ dir = AllocateDir(location);
+ while ((de = ReadDir(dir, location)) != NULL)
+ {
+ char *vername;
+ char *vername2;
+ ExtensionVersionInfo *evi;
+ ExtensionVersionInfo *evi2;
+
+ /* must be a .sql file ... */
+ if (!is_extension_script_filename(de->d_name))
+ continue;
+
+ /* ... matching extension name followed by separator */
+ if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
+ de->d_name[extnamelen] != '-' ||
+ de->d_name[extnamelen + 1] != '-')
+ continue;
+
+ /* extract version name(s) from 'extname--something.sql' filename */
+ vername = pstrdup(de->d_name + extnamelen + 2);
+ *strrchr(vername, '.') = '\0';
+ vername2 = strstr(vername, "--");
+ if (!vername2)
+ {
+ /* It's an install, not update, script; record its version name */
+ evi = get_ext_ver_info(vername, &evi_list);
+ evi->installable = true;
+ continue;
+ }
+ *vername2 = '\0'; /* terminate first version */
+ vername2 += 2; /* and point to second */
+
+ /* if there's a third --, it's bogus, ignore it */
+ if (strstr(vername2, "--"))
+ continue;
+
+ /* Create ExtensionVersionInfos and link them together */
+ evi = get_ext_ver_info(vername, &evi_list);
+ evi2 = get_ext_ver_info(vername2, &evi_list);
+ evi->reachable = lappend(evi->reachable, evi2);
+ }
+ FreeDir(dir);
+ }
+
location = get_extension_script_directory(control);
dir = AllocateDir(location);
while ((de = ReadDir(dir, location)) != NULL)
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index eafa0128ef..8dc17da5b5 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -35,6 +35,7 @@
#include "miscadmin.h"
#include "storage/fd.h"
#include "storage/shmem.h"
+#include "utils/guc.h"
#include "utils/hsearch.h"
@@ -415,7 +416,7 @@ expand_dynamic_library_name(const char *name)
{
bool have_slash;
char *new;
- char *full;
+ char *full, *full2;
Assert(name);
@@ -430,6 +431,19 @@ expand_dynamic_library_name(const char *name)
else
{
full = substitute_libpath_macro(name);
+ /*
+ * If extension_destdir is set, try to find the file there first
+ */
+ if (*extension_destdir != '\0')
+ {
+ full2 = psprintf("%s%s", extension_destdir, full);
+ if (pg_file_exists(full2))
+ {
+ pfree(full);
+ return full2;
+ }
+ pfree(full2);
+ }
if (pg_file_exists(full))
return full;
pfree(full);
@@ -448,6 +462,19 @@ expand_dynamic_library_name(const char *name)
{
full = substitute_libpath_macro(new);
pfree(new);
+ /*
+ * If extension_destdir is set, try to find the file there first
+ */
+ if (*extension_destdir != '\0')
+ {
+ full2 = psprintf("%s%s", extension_destdir, full);
+ if (pg_file_exists(full2))
+ {
+ pfree(full);
+ return full2;
+ }
+ pfree(full2);
+ }
if (pg_file_exists(full))
return full;
pfree(full);
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index c12784cbec..f46e84db13 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -541,6 +541,7 @@ char *ConfigFileName;
char *HbaFileName;
char *IdentFileName;
char *external_pid_file;
+char *extension_destdir;
char *application_name;
@@ -4497,6 +4498,17 @@ struct config_string ConfigureNamesString[] =
check_canonical_path, NULL, NULL
},
+ {
+ {"extension_destdir", PGC_POSTMASTER, FILE_LOCATIONS,
+ gettext_noop("Path to prepend for extension loading."),
+ gettext_noop("This directory is prepended to paths when loading extensions (control and SQL files), and to the '$libdir' directive when loading modules that back functions. The location is made configurable to allow build-time testing of extensions that do not have been installed to their proper location yet."),
+ GUC_SUPERUSER_ONLY
+ },
+ &extension_destdir,
+ "",
+ NULL, NULL, NULL
+ },
+
{
{"ssl_library", PGC_INTERNAL, PRESET_OPTIONS,
gettext_noop("Shows the name of the SSL library."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index baecde2841..d8df437554 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -771,6 +771,8 @@
# - Other Defaults -
#dynamic_library_path = '$libdir'
+#extension_destdir = '' # prepend path when loading extensions
+ # and shared objects (added by Debian)
#gin_fuzzy_search_limit = 0
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 8d1fe04078..9f198cf2b5 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -278,6 +278,7 @@ extern PGDLLIMPORT char *ConfigFileName;
extern PGDLLIMPORT char *HbaFileName;
extern PGDLLIMPORT char *IdentFileName;
extern PGDLLIMPORT char *external_pid_file;
+extern PGDLLIMPORT char *extension_destdir;
extern PGDLLIMPORT char *application_name;
--
2.44.0