Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 698bdd9

Browse files
committed
Add extension_destdir GUC
Based on a [patch] by Christophe Berg in the Debian Project, add a new GUC, `extension_destdir`, that prepends a directory prefix for extension loading. This directory is prepended to the `SHAREDIR` 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. Also document the PGXS `DESTDIR` variable, which should be used to install extensions into the proper destination directory. [patch]: https://salsa.debian.org/postgresql/postgresql/-/blob/17/debian/patches/extension_destdir?ref_type=heads
1 parent 1bf29f5 commit 698bdd9

File tree

7 files changed

+179
-2
lines changed

7 files changed

+179
-2
lines changed

doc/src/sgml/config.sgml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10389,6 +10389,41 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
1038910389
</listitem>
1039010390
</varlistentry>
1039110391

10392+
<varlistentry id="guc-extension-destdir" xreflabel="extension_destdir">
10393+
<term><varname>extension_destdir</varname> (<type>string</type>)
10394+
<indexterm>
10395+
<primary><varname>extension_destdir</varname> configuration parameter</primary>
10396+
</indexterm>
10397+
</term>
10398+
<listitem>
10399+
<para>
10400+
Specifies a directory prefix into which extensions should be
10401+
installed. When set, the postmaster will search this directory for an
10402+
extension before searching the default paths.
10403+
</para>
10404+
10405+
<para>
10406+
For example, this configuration:
10407+
<programlisting>
10408+
extension_destdir = '/mnt/extensions'
10409+
</programlisting>
10410+
will allow <productname>PostgreSQL</productname> to first look for
10411+
extension control files, SQL files, and loadable modules installed in
10412+
<literal>/mnt/extensions</literal> and fall back on the
10413+
default directories if they're not found there.
10414+
</para>
10415+
10416+
<para>
10417+
Note that the files should be installed in their full paths under the
10418+
<varname>extension_destdir</varname> prefix. When using
10419+
<link linkend="extend-pgxs">PGXS</link> to install an extension, pass
10420+
the destination directory via the <varname>DESTDIR</varname> variable
10421+
to install the files in the proper location. For more information see
10422+
<xref linkend="extend-extensions-files-directory"/>.
10423+
</para>
10424+
</listitem>
10425+
</varlistentry>
10426+
1039210427
</variablelist>
1039310428
</sect2>
1039410429
</sect1>

doc/src/sgml/extend.sgml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,8 @@ RETURNS anycompatible AS ...
669669
<para>
670670
The directory containing the extension's <acronym>SQL</acronym> script
671671
file(s). Unless an absolute path is given, the name is relative to
672-
the installation's <literal>SHAREDIR</literal> directory. The
672+
the <literal>SHAREDIR</literal> under the <xref linkend="guc-extension-destdir"/>
673+
prefix and to the installation's <literal>SHAREDIR</literal> directory. The
673674
default behavior is equivalent to specifying
674675
<literal>directory = 'extension'</literal>.
675676
</para>
@@ -1710,6 +1711,15 @@ include $(PGXS)
17101711
</listitem>
17111712
</varlistentry>
17121713

1714+
<varlistentry id="extend-pgxs-destdir">
1715+
<term><varname>DESTDIR</varname></term>
1716+
<listitem>
1717+
<para>
1718+
install all files under this directory prefix
1719+
</para>
1720+
</listitem>
1721+
</varlistentry>
1722+
17131723
<varlistentry id="extend-pgxs-no-installcheck">
17141724
<term><varname>NO_INSTALLCHECK</varname></term>
17151725
<listitem>

src/backend/commands/extension.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,16 @@ get_extension_control_filename(const char *extname)
393393

394394
get_share_path(my_exec_path, sharepath);
395395
result = (char *) palloc(MAXPGPATH);
396+
/*
397+
* If extension_destdir is set, try to find the file there first
398+
*/
399+
if (*extension_destdir != '\0')
400+
{
401+
snprintf(result, MAXPGPATH, "%s%s/extension/%s.control",
402+
extension_destdir, sharepath, extname);
403+
if (pg_file_exists(result))
404+
return result;
405+
}
396406
snprintf(result, MAXPGPATH, "%s/extension/%s.control",
397407
sharepath, extname);
398408

@@ -432,6 +442,16 @@ get_extension_aux_control_filename(ExtensionControlFile *control,
432442
scriptdir = get_extension_script_directory(control);
433443

434444
result = (char *) palloc(MAXPGPATH);
445+
/*
446+
* If extension_destdir is set, try to find the file there first
447+
*/
448+
if (*extension_destdir != '\0')
449+
{
450+
snprintf(result, MAXPGPATH, "%s%s/%s--%s.control",
451+
extension_destdir, scriptdir, control->name, version);
452+
if (pg_file_exists(result))
453+
return result;
454+
}
435455
snprintf(result, MAXPGPATH, "%s/%s--%s.control",
436456
scriptdir, control->name, version);
437457

@@ -450,6 +470,23 @@ get_extension_script_filename(ExtensionControlFile *control,
450470
scriptdir = get_extension_script_directory(control);
451471

452472
result = (char *) palloc(MAXPGPATH);
473+
/*
474+
* If extension_destdir is set, try to find the file there first
475+
*/
476+
if (*extension_destdir != '\0')
477+
{
478+
if (from_version)
479+
snprintf(result, MAXPGPATH, "%s%s/%s--%s--%s.sql",
480+
extension_destdir, scriptdir, control->name, from_version, version);
481+
else
482+
snprintf(result, MAXPGPATH, "%s%s/%s--%s.sql",
483+
extension_destdir, scriptdir, control->name, version);
484+
if (pg_file_exists(result))
485+
{
486+
pfree(scriptdir);
487+
return result;
488+
}
489+
}
453490
if (from_version)
454491
snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
455492
scriptdir, control->name, from_version, version);
@@ -1209,6 +1246,59 @@ get_ext_ver_list(ExtensionControlFile *control)
12091246
DIR *dir;
12101247
struct dirent *de;
12111248

1249+
/*
1250+
* If extension_destdir is set, try to find the files there first
1251+
*/
1252+
if (*extension_destdir != '\0')
1253+
{
1254+
char location[MAXPGPATH];
1255+
1256+
snprintf(location, MAXPGPATH, "%s%s", extension_destdir,
1257+
get_extension_script_directory(control));
1258+
dir = AllocateDir(location);
1259+
while ((de = ReadDir(dir, location)) != NULL)
1260+
{
1261+
char *vername;
1262+
char *vername2;
1263+
ExtensionVersionInfo *evi;
1264+
ExtensionVersionInfo *evi2;
1265+
1266+
/* must be a .sql file ... */
1267+
if (!is_extension_script_filename(de->d_name))
1268+
continue;
1269+
1270+
/* ... matching extension name followed by separator */
1271+
if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
1272+
de->d_name[extnamelen] != '-' ||
1273+
de->d_name[extnamelen + 1] != '-')
1274+
continue;
1275+
1276+
/* extract version name(s) from 'extname--something.sql' filename */
1277+
vername = pstrdup(de->d_name + extnamelen + 2);
1278+
*strrchr(vername, '.') = '\0';
1279+
vername2 = strstr(vername, "--");
1280+
if (!vername2)
1281+
{
1282+
/* It's an install, not update, script; record its version name */
1283+
evi = get_ext_ver_info(vername, &evi_list);
1284+
evi->installable = true;
1285+
continue;
1286+
}
1287+
*vername2 = '\0'; /* terminate first version */
1288+
vername2 += 2; /* and point to second */
1289+
1290+
/* if there's a third --, it's bogus, ignore it */
1291+
if (strstr(vername2, "--"))
1292+
continue;
1293+
1294+
/* Create ExtensionVersionInfos and link them together */
1295+
evi = get_ext_ver_info(vername, &evi_list);
1296+
evi2 = get_ext_ver_info(vername2, &evi_list);
1297+
evi->reachable = lappend(evi->reachable, evi2);
1298+
}
1299+
FreeDir(dir);
1300+
}
1301+
12121302
location = get_extension_script_directory(control);
12131303
dir = AllocateDir(location);
12141304
while ((de = ReadDir(dir, location)) != NULL)

src/backend/utils/fmgr/dfmgr.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "miscadmin.h"
3636
#include "storage/fd.h"
3737
#include "storage/shmem.h"
38+
#include "utils/guc.h"
3839
#include "utils/hsearch.h"
3940

4041

@@ -415,7 +416,7 @@ expand_dynamic_library_name(const char *name)
415416
{
416417
bool have_slash;
417418
char *new;
418-
char *full;
419+
char *full, *full2;
419420

420421
Assert(name);
421422

@@ -430,6 +431,19 @@ expand_dynamic_library_name(const char *name)
430431
else
431432
{
432433
full = substitute_libpath_macro(name);
434+
/*
435+
* If extension_destdir is set, try to find the file there first
436+
*/
437+
if (*extension_destdir != '\0')
438+
{
439+
full2 = psprintf("%s%s", extension_destdir, full);
440+
if (pg_file_exists(full2))
441+
{
442+
pfree(full);
443+
return full2;
444+
}
445+
pfree(full2);
446+
}
433447
if (pg_file_exists(full))
434448
return full;
435449
pfree(full);
@@ -448,6 +462,19 @@ expand_dynamic_library_name(const char *name)
448462
{
449463
full = substitute_libpath_macro(new);
450464
pfree(new);
465+
/*
466+
* If extension_destdir is set, try to find the file there first
467+
*/
468+
if (*extension_destdir != '\0')
469+
{
470+
full2 = psprintf("%s%s", extension_destdir, full);
471+
if (pg_file_exists(full2))
472+
{
473+
pfree(full);
474+
return full2;
475+
}
476+
pfree(full2);
477+
}
451478
if (pg_file_exists(full))
452479
return full;
453480
pfree(full);

src/backend/utils/misc/guc_tables.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ char *ConfigFileName;
541541
char *HbaFileName;
542542
char *IdentFileName;
543543
char *external_pid_file;
544+
char *extension_destdir;
544545

545546
char *application_name;
546547

@@ -4487,6 +4488,17 @@ struct config_string ConfigureNamesString[] =
44874488
check_canonical_path, NULL, NULL
44884489
},
44894490

4491+
{
4492+
{"extension_destdir", PGC_POSTMASTER, FILE_LOCATIONS,
4493+
gettext_noop("Path to prepend for extension loading."),
4494+
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."),
4495+
GUC_SUPERUSER_ONLY
4496+
},
4497+
&extension_destdir,
4498+
"",
4499+
NULL, NULL, NULL
4500+
},
4501+
44904502
{
44914503
{"ssl_library", PGC_INTERNAL, PRESET_OPTIONS,
44924504
gettext_noop("Shows the name of the SSL library."),

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,8 @@
771771
# - Other Defaults -
772772

773773
#dynamic_library_path = '$libdir'
774+
#extension_destdir = '' # prepend path when loading extensions
775+
# and shared objects (added by Debian)
774776
#gin_fuzzy_search_limit = 0
775777

776778

src/include/utils/guc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ extern PGDLLIMPORT char *ConfigFileName;
277277
extern PGDLLIMPORT char *HbaFileName;
278278
extern PGDLLIMPORT char *IdentFileName;
279279
extern PGDLLIMPORT char *external_pid_file;
280+
extern PGDLLIMPORT char *extension_destdir;
280281

281282
extern PGDLLIMPORT char *application_name;
282283

0 commit comments

Comments
 (0)