postgresql: provide PL/Perl, PL/Python and PL/Tcl as packages (#385859)

This commit is contained in:
Wolfgang Walther
2025-03-21 18:50:30 +00:00
committed by GitHub
7 changed files with 289 additions and 48 deletions

View File

@@ -27,6 +27,8 @@
The `nixLog` function, which logs unconditionally, was also re-introduced and modified to prefix messages with the function name of the caller.
For more information, [see this PR](https://github.com/NixOS/nixpkgs/pull/370742).
- `postgresql`'s `pythonSupport` argument has been changed. It is now enabled by default, but to use PL/Python the extension needs to be added explicitly with `postgresql.withPackages`. If you were using `postgresql.override { pythonSupport = true; }` before, change it to `postgresql.withPackages (ps: [ ps.plpython3 ])`. The same applies to `perlSupport`/`plperl` and `tclSupport`/`pltcl` respectively.
- The `rustPlatform.fetchCargoTarball` function is deprecated, because it relied on `cargo vendor` not changing its output format to keep fixed-output derivation hashes the same, which is a Nix invariant, and Cargo 1.84.0 changed `cargo vendor`'s output format.
It should generally be replaced with `rustPlatform.fetchCargoVendor`, but `rustPlatform.importCargoLock` may also be appropriate in some circumstances.
`rustPlatform.buildRustPackage` users must set `useFetchCargoVendor` to `true` and regenerate the `cargoHash`.

View File

@@ -9,6 +9,15 @@ in
// {
timescaledb-apache = super.callPackage ./ext/timescaledb.nix { enableUnfree = false; };
}
// lib.optionalAttrs (!self.perlSupport) {
plperl = throw "PostgreSQL extension `plperl` is not available, because `postgresql` was built without Perl support. Override with `perlSupport = true` to enable the extension.";
}
// lib.optionalAttrs (!self.pythonSupport) {
plpython3 = throw "PostgreSQL extension `plpython3` is not available, because `postgresql` was built without Python support. Override with `pythonSupport = true` to enable the extension.";
}
// lib.optionalAttrs (!self.tclSupport) {
pltcl = throw "PostgreSQL extension `pltcl` is not available, because `postgresql` was built without Tcl support. Override with `tclSupport = true` to enable the extension.";
}
// lib.optionalAttrs config.allowAliases {
pg_embedding = throw "PostgreSQL extension `pg_embedding` has been removed since the project has been abandoned. Upstream's recommendation is to use pgvector instead (https://neon.tech/docs/extensions/pg_embedding#migrate-from-pg_embedding-to-pgvector)";
}

View File

@@ -0,0 +1,45 @@
{
buildEnv,
perl,
postgresql,
postgresqlTestExtension,
}:
let
withPackages =
f:
let
perl' = perl.withPackages f;
finalPackage = buildEnv {
name = "${postgresql.pname}-plperl-${postgresql.version}";
paths = [ postgresql.plperl ];
passthru = {
inherit withPackages;
wrapperArgs = [
''--set PERL5LIB "${perl'}/${perl'.libPrefix}"''
];
tests.extension = postgresqlTestExtension {
finalPackage = finalPackage.withPackages (ps: [ ps.boolean ]);
sql = ''
CREATE EXTENSION plperlu;
DO LANGUAGE plperlu $$
use boolean;
$$;
'';
};
};
meta = {
inherit (postgresql.meta)
homepage
license
changelog
maintainers
platforms
;
description = "PL/Perl - Perl Procedural Language";
};
};
in
finalPackage;
in
withPackages (_: [ ])

View File

@@ -0,0 +1,45 @@
{
buildEnv,
postgresql,
postgresqlTestExtension,
python3,
}:
let
withPackages =
f:
let
python = python3.withPackages f;
finalPackage = buildEnv {
name = "${postgresql.pname}-plpython3-${postgresql.version}";
paths = [ postgresql.plpython3 ];
passthru = {
inherit withPackages;
wrapperArgs = [
''--set PYTHONPATH "${python}/${python.sitePackages}"''
];
tests.extension = postgresqlTestExtension {
finalPackage = finalPackage.withPackages (ps: [ ps.base58 ]);
sql = ''
CREATE EXTENSION plpython3u;
DO LANGUAGE plpython3u $$
import base58
$$;
'';
};
};
meta = {
inherit (postgresql.meta)
homepage
license
changelog
maintainers
platforms
;
description = "PL/Python - Python Procedural Language";
};
};
in
finalPackage;
in
withPackages (_: [ ])

View File

@@ -1,16 +1,21 @@
{
R,
buildEnv,
fetchFromGitHub,
lib,
pkg-config,
postgresql,
postgresqlBuildExtension,
postgresqlTestExtension,
R,
rPackages,
stdenv,
}:
postgresqlBuildExtension rec {
postgresqlBuildExtension (finalAttrs: {
pname = "plr";
version = "${builtins.replaceStrings [ "_" ] [ "." ] (lib.strings.removePrefix "REL" src.rev)}";
version = "${builtins.replaceStrings [ "_" ] [ "." ] (
lib.strings.removePrefix "REL" finalAttrs.src.rev
)}";
src = fetchFromGitHub {
owner = "postgres-plr";
@@ -24,12 +29,38 @@ postgresqlBuildExtension rec {
makeFlags = [ "USE_PGXS=1" ];
passthru = {
withPackages =
f:
let
pkgs = f rPackages;
paths = lib.concatMapStringsSep ":" (pkg: "${pkg}/library") pkgs;
in
buildEnv {
name = "${finalAttrs.pname}-with-packages-${finalAttrs.version}";
paths = [ finalAttrs.finalPackage ];
passthru.wrapperArgs = [
''--set R_LIBS_SITE "${paths}"''
];
};
tests.extension = postgresqlTestExtension {
finalPackage = finalAttrs.finalPackage.withPackages (ps: [ ps.base64enc ]);
sql = ''
CREATE EXTENSION plr;
DO LANGUAGE plr $$
require('base64enc')
base64encode(1:100)
$$;
'';
};
};
meta = {
description = "PL/R - R Procedural Language for PostgreSQL";
homepage = "https://github.com/postgres-plr/plr";
changelog = "https://github.com/postgres-plr/plr/blob/${src.rev}/changelog.md";
changelog = "https://github.com/postgres-plr/plr/blob/${finalAttrs.src.rev}/changelog.md";
maintainers = with lib.maintainers; [ qoelet ];
platforms = postgresql.meta.platforms;
license = lib.licenses.gpl2Only;
};
}
})

View File

@@ -0,0 +1,53 @@
{
buildEnv,
lib,
postgresql,
postgresqlTestExtension,
tcl,
tclPackages,
}:
let
withPackages =
f:
let
pkgs = f tclPackages;
paths = lib.concatMapStringsSep " " (pkg: "${pkg}/lib") pkgs;
finalPackage = buildEnv {
name = "${postgresql.pname}-pltcl-${postgresql.version}";
paths = [ postgresql.pltcl ];
passthru = {
inherit withPackages;
wrapperArgs = [
''--set TCLLIBPATH "${paths}"''
];
tests.extension = postgresqlTestExtension {
finalPackage = finalPackage.withPackages (ps: [
ps.mustache-tcl
ps.tcllib
]);
sql = ''
CREATE EXTENSION pltclu;
CREATE FUNCTION test() RETURNS VOID
LANGUAGE pltclu AS $$
package require mustache
$$;
SELECT test();
'';
};
};
meta = {
inherit (postgresql.meta)
homepage
license
changelog
maintainers
platforms
;
description = "PL/Tcl - Tcl Procedural Language";
};
};
in
finalPackage;
in
withPackages (_: [ ])

View File

@@ -36,7 +36,7 @@ let
docbook_xml_dtd_45,
flex,
libxslt,
makeWrapper,
makeBinaryWrapper,
pkg-config,
removeReferencesTo,
@@ -80,23 +80,43 @@ let
gettext,
# PAM
# Building with linux-pam in pkgsStatic gives a few "undefined reference" errors like this:
# /nix/store/3s55icpsbc36sgn7sa8q3qq4z6al6rlr-linux-pam-static-x86_64-unknown-linux-musl-1.6.1/lib/libpam.a(pam_audit.o):
# in function `pam_modutil_audit_write':(.text+0x571):
# undefined reference to `audit_close'
pamSupport ? stdenv.hostPlatform.isLinux && !stdenv.hostPlatform.isStatic,
pamSupport ?
lib.meta.availableOn stdenv.hostPlatform linux-pam
# Building with linux-pam in pkgsStatic gives a few "undefined reference" errors like this:
# /nix/store/3s55icpsbc36sgn7sa8q3qq4z6al6rlr-linux-pam-static-x86_64-unknown-linux-musl-1.6.1/lib/libpam.a(pam_audit.o):
# in function `pam_modutil_audit_write':(.text+0x571):
# undefined reference to `audit_close'
&& !stdenv.hostPlatform.isStatic,
linux-pam,
# PL/Perl
perlSupport ? false,
perlSupport ?
lib.meta.availableOn stdenv.hostPlatform perl
# Building with perl in pkgsStatic gives this error:
# configure: error: cannot build PL/Perl because libperl is not a shared library
&& !stdenv.hostPlatform.isStatic
# configure tries to call the perl executable for the version
&& stdenv.buildPlatform.canExecute stdenv.hostPlatform,
perl,
# PL/Python
pythonSupport ? false,
pythonSupport ?
lib.meta.availableOn stdenv.hostPlatform python3
# Building with python in pkgsStatic gives this error:
# checking how to link an embedded Python application... configure: error: could not find shared library for Python
&& !stdenv.hostPlatform.isStatic
# configure tries to call the python executable
&& stdenv.buildPlatform.canExecute stdenv.hostPlatform,
python3,
# PL/Tcl
tclSupport ? false,
tclSupport ?
lib.meta.availableOn stdenv.hostPlatform tcl
# tcl is broken in pkgsStatic
&& !stdenv.hostPlatform.isStatic
# configure fails with:
# configure: error: file 'tclConfig.sh' is required for Tcl
&& stdenv.buildPlatform.canExecute stdenv.hostPlatform,
tcl,
# SELinux
@@ -144,13 +164,17 @@ let
hardeningEnable = lib.optionals (!stdenv'.cc.isClang) [ "pie" ];
outputs = [
"out"
"dev"
"doc"
"lib"
"man"
];
outputs =
[
"out"
"dev"
"doc"
"lib"
"man"
]
++ lib.optionals perlSupport [ "plperl" ]
++ lib.optionals pythonSupport [ "plpython3" ]
++ lib.optionals tclSupport [ "pltcl" ];
outputChecks = {
out = {
disallowedReferences = [
@@ -209,12 +233,10 @@ let
++ lib.optionals lz4Enabled [ lz4 ]
++ lib.optionals zstdEnabled [ zstd ]
++ lib.optionals systemdSupport [ systemdLibs ]
++ lib.optionals pythonSupport [ python3 ]
++ lib.optionals gssSupport [ libkrb5 ]
++ lib.optionals pamSupport [ linux-pam ]
++ lib.optionals perlSupport [ perl ]
++ lib.optionals ldapSupport [ openldap ]
++ lib.optionals tclSupport [ tcl ]
++ lib.optionals selinuxSupport [ libselinux ]
++ lib.optionals nlsSupport [ gettext ];
@@ -226,7 +248,7 @@ let
flex
libxml2
libxslt
makeWrapper
makeBinaryWrapper
perl
pkg-config
removeReferencesTo
@@ -242,16 +264,20 @@ let
buildFlags = [ "world" ];
# libpgcommon.a and libpgport.a contain all paths returned by pg_config and are linked
# into all binaries. However, almost no binaries actually use those paths. The following
# flags will remove unused sections from all shared libraries and binaries - including
# those paths. This avoids a lot of circular dependency problems with different outputs,
# and allows splitting them cleanly.
env = {
CFLAGS =
"-fdata-sections -ffunction-sections"
+ (if stdenv'.cc.isClang then " -flto" else " -fmerge-constants -Wl,--gc-sections");
} // lib.optionalAttrs pythonSupport { PYTHON = "${python3}/bin/python"; };
env =
{
# libpgcommon.a and libpgport.a contain all paths returned by pg_config and are linked
# into all binaries. However, almost no binaries actually use those paths. The following
# flags will remove unused sections from all shared libraries and binaries - including
# those paths. This avoids a lot of circular dependency problems with different outputs,
# and allows splitting them cleanly.
CFLAGS =
"-fdata-sections -ffunction-sections"
+ (if stdenv'.cc.isClang then " -flto" else " -fmerge-constants -Wl,--gc-sections");
}
// lib.optionalAttrs perlSupport { PERL = lib.getExe perl; }
// lib.optionalAttrs pythonSupport { PYTHON = lib.getExe python3; }
// lib.optionalAttrs tclSupport { TCLSH = "${lib.getBin tcl}/bin/tclsh"; };
configureFlags =
let
@@ -266,6 +292,7 @@ let
"--enable-debug"
(lib.optionalString systemdSupport "--with-systemd")
(if stdenv.hostPlatform.isFreeBSD then "--with-uuid=bsd" else "--with-uuid=e2fs")
(withFeature perlSupport "perl")
]
++ lib.optionals lz4Enabled [ "--with-lz4" ]
++ lib.optionals zstdEnabled [ "--with-zstd" ]
@@ -289,7 +316,6 @@ let
[
"LDFLAGS_EX_BE=-Wl,--export-dynamic"
]
++ lib.optionals (atLeast "17" && !perlSupport) [ "--without-perl" ]
++ lib.optionals ldapSupport [ "--with-ldap" ]
++ lib.optionals tclSupport [ "--with-tcl" ]
++ lib.optionals selinuxSupport [ "--with-selinux" ]
@@ -390,17 +416,25 @@ let
# to their own output for installation, will then fail to find "postgres" during linking.
substituteInPlace "$dev/lib/pgxs/src/Makefile.port" \
--replace-fail '-bundle_loader $(bindir)/postgres' "-bundle_loader $out/bin/postgres"
'';
postFixup =
lib.optionalString stdenv'.hostPlatform.isGnu ''
# initdb needs access to "locale" command from glibc.
wrapProgram $out/bin/initdb --prefix PATH ":" ${glibc.bin}/bin
''
+ lib.optionalString perlSupport ''
moveToOutput "lib/*plperl*" "$plperl"
moveToOutput "share/postgresql/extension/*plperl*" "$plperl"
''
+ lib.optionalString pythonSupport ''
wrapProgram "$out/bin/postgres" --set PYTHONPATH "${python3}/${python3.sitePackages}"
moveToOutput "lib/*plpython3*" "$plpython3"
moveToOutput "share/postgresql/extension/*plpython3*" "$plpython3"
''
+ lib.optionalString tclSupport ''
moveToOutput "lib/*pltcl*" "$pltcl"
moveToOutput "share/postgresql/extension/*pltcl*" "$pltcl"
'';
postFixup = lib.optionalString stdenv'.hostPlatform.isGnu ''
# initdb needs access to "locale" command from glibc.
wrapProgram $out/bin/initdb --prefix PATH ":" ${glibc.bin}/bin
'';
# Running tests as "install check" to work around SIP issue on macOS:
# https://www.postgresql.org/message-id/flat/4D8E1BC5-BBCF-4B19-8226-359201EA8305%40gmail.com
# Also see <nixpkgs>/doc/stdenv/platform-notes.chapter.md
@@ -434,7 +468,12 @@ let
pkgs =
let
scope = {
inherit jitSupport;
inherit
jitSupport
pythonSupport
perlSupport
tclSupport
;
inherit (llvmPackages) llvm;
postgresql = this;
stdenv = stdenv';
@@ -449,7 +488,7 @@ let
import ./ext.nix newSelf newSuper;
withPackages = postgresqlWithPackages {
inherit buildEnv;
inherit buildEnv lib makeBinaryWrapper;
postgresql = this;
};
@@ -499,7 +538,12 @@ let
});
postgresqlWithPackages =
{ postgresql, buildEnv }:
{
postgresql,
buildEnv,
lib,
makeBinaryWrapper,
}:
f:
let
installedExtensions = f postgresql.pkgs;
@@ -511,7 +555,19 @@ let
postgresql.man # in case user installs this into environment
];
pathsToLink = [ "/" ];
pathsToLink = [
"/"
"/bin"
];
nativeBuildInputs = [ makeBinaryWrapper ];
postBuild =
let
args = lib.concatMap (ext: ext.wrapperArgs or [ ]) installedExtensions;
in
''
wrapProgram "$out/bin/postgres" ${lib.concatStringsSep " " args}
'';
passthru = {
inherit installedExtensions;
@@ -522,11 +578,11 @@ let
;
withJIT = postgresqlWithPackages {
inherit buildEnv;
inherit buildEnv lib makeBinaryWrapper;
postgresql = postgresql.withJIT;
} f;
withoutJIT = postgresqlWithPackages {
inherit buildEnv;
inherit buildEnv lib makeBinaryWrapper;
postgresql = postgresql.withoutJIT;
} f;
};