Skip to content

Commit 8ad0772

Browse files
jfrochesamrose
authored andcommitted
feat(hypopg): build multiple versions of the hypopg extension
Build multiple versions of the hypopg extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17.
1 parent 9898ced commit 8ad0772

File tree

3 files changed

+259
-29
lines changed

3 files changed

+259
-29
lines changed

nix/ext/hypopg.nix

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,95 @@
11
{
22
lib,
33
stdenv,
4+
buildEnv,
45
fetchFromGitHub,
56
postgresql,
67
}:
78

8-
stdenv.mkDerivation rec {
9+
let
910
pname = "hypopg";
10-
version = "1.4.1";
11+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
12+
supportedVersions = lib.filterAttrs (
13+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
14+
) allVersions;
15+
versions = lib.naturalSort (lib.attrNames supportedVersions);
16+
latestVersion = lib.last versions;
17+
numberOfVersions = builtins.length versions;
18+
build =
19+
version: hash:
20+
stdenv.mkDerivation rec {
21+
inherit pname version;
1122

12-
buildInputs = [ postgresql ];
23+
buildInputs = [ postgresql ];
1324

14-
src = fetchFromGitHub {
15-
owner = "HypoPG";
16-
repo = pname;
17-
rev = "refs/tags/${version}";
18-
hash = "sha256-88uKPSnITRZ2VkelI56jZ9GWazG/Rn39QlyHKJKSKMM=";
19-
};
25+
src = fetchFromGitHub {
26+
owner = "HypoPG";
27+
repo = pname;
28+
rev = "refs/tags/${version}";
29+
inherit hash;
30+
};
31+
32+
installPhase = ''
33+
mkdir -p $out/{lib,share/postgresql/extension}
34+
35+
mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix}
36+
37+
create_sql_files() {
38+
echo "Creating SQL files for previous versions..."
39+
if [[ "${version}" == "${latestVersion}" ]]; then
40+
cp *.sql $out/share/postgresql/extension
41+
fi
42+
}
43+
44+
create_control_files() {
45+
sed -e "/^default_version =/d" \
46+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
47+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
48+
49+
if [[ "${version}" == "${latestVersion}" ]]; then
50+
{
51+
echo "default_version = '${latestVersion}'"
52+
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
53+
} > $out/share/postgresql/extension/${pname}.control
54+
ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix}
55+
fi
56+
}
2057
21-
installPhase = ''
22-
mkdir -p $out/{lib,share/postgresql/extension}
58+
create_sql_files
59+
create_control_files
60+
'';
2361

24-
cp *${postgresql.dlSuffix} $out/lib
25-
cp *.sql $out/share/postgresql/extension
26-
cp *.control $out/share/postgresql/extension
62+
meta = with lib; {
63+
description = "Hypothetical Indexes for PostgreSQL";
64+
homepage = "https://github.com/HypoPG/${pname}";
65+
license = licenses.postgresql;
66+
inherit (postgresql.meta) platforms;
67+
};
68+
};
69+
packages = builtins.attrValues (
70+
lib.mapAttrs (name: value: build name value.hash) supportedVersions
71+
);
72+
in
73+
buildEnv {
74+
name = pname;
75+
paths = packages;
76+
pathsToLink = [
77+
"/lib"
78+
"/share/postgresql/extension"
79+
];
80+
postBuild = ''
81+
# checks
82+
(set -x
83+
test "$(ls -A $out/lib/${pname}*${postgresql.dlSuffix} | wc -l)" = "${
84+
toString (numberOfVersions + 1)
85+
}"
86+
)
2787
'';
2888

29-
meta = with lib; {
30-
description = "Hypothetical Indexes for PostgreSQL";
31-
homepage = "https://github.com/HypoPG/${pname}";
32-
platforms = postgresql.meta.platforms;
33-
license = licenses.postgresql;
89+
passthru = {
90+
inherit versions numberOfVersions;
91+
pname = "${pname}-all";
92+
version =
93+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
3494
};
3595
}

nix/ext/tests/hypopg.nix

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
{ self, pkgs }:
2+
let
3+
pname = "hypopg";
4+
inherit (pkgs) lib;
5+
installedExtension =
6+
postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
7+
versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
8+
postgresqlWithExtension =
9+
postgresql:
10+
let
11+
majorVersion = lib.versions.major postgresql.version;
12+
pkg = pkgs.buildEnv {
13+
name = "postgresql-${majorVersion}-${pname}";
14+
paths = [
15+
postgresql
16+
postgresql.lib
17+
(installedExtension majorVersion)
18+
];
19+
passthru = {
20+
inherit (postgresql) version psqlSchema;
21+
lib = pkg;
22+
withPackages = _: pkg;
23+
};
24+
nativeBuildInputs = [ pkgs.makeWrapper ];
25+
pathsToLink = [
26+
"/"
27+
"/bin"
28+
"/lib"
29+
];
30+
postBuild = ''
31+
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
32+
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
33+
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
34+
'';
35+
};
36+
in
37+
pkg;
38+
in
39+
self.inputs.nixpkgs.lib.nixos.runTest {
40+
name = pname;
41+
hostPkgs = pkgs;
42+
nodes.server =
43+
{ config, ... }:
44+
{
45+
virtualisation = {
46+
forwardPorts = [
47+
{
48+
from = "host";
49+
host.port = 13022;
50+
guest.port = 22;
51+
}
52+
];
53+
};
54+
55+
services.postgresql = {
56+
enable = true;
57+
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
58+
settings = {
59+
shared_preload_libraries = pname;
60+
};
61+
};
62+
63+
specialisation.postgresql17.configuration = {
64+
services.postgresql = {
65+
package = lib.mkForce (postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17);
66+
};
67+
68+
systemd.services.postgresql-migrate = {
69+
serviceConfig = {
70+
Type = "oneshot";
71+
RemainAfterExit = true;
72+
User = "postgres";
73+
Group = "postgres";
74+
StateDirectory = "postgresql";
75+
WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
76+
};
77+
script =
78+
let
79+
oldPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
80+
newPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
81+
oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
82+
newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
83+
in
84+
''
85+
if [[ ! -d ${newDataDir} ]]; then
86+
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
87+
${newPostgresql}/bin/initdb -D "${newDataDir}"
88+
echo "shared_preload_libraries = '${pname}'" >> "${newDataDir}/postgresql.conf"
89+
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
90+
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
91+
else
92+
echo "${newDataDir} already exists"
93+
fi
94+
'';
95+
};
96+
97+
systemd.services.postgresql = {
98+
after = [ "postgresql-migrate.service" ];
99+
requires = [ "postgresql-migrate.service" ];
100+
};
101+
};
102+
};
103+
testScript =
104+
{ nodes, ... }:
105+
let
106+
pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
107+
in
108+
''
109+
versions = {
110+
"15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
111+
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
112+
}
113+
114+
def run_sql(query):
115+
return server.succeed(f"""sudo -u postgres psql -t -A -F\",\" -c \"{query}\" """).strip()
116+
117+
def check_upgrade_path(pg_version):
118+
with subtest("Check ${pname} upgrade path"):
119+
firstVersion = versions[pg_version][0]
120+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION IF EXISTS ${pname};'")
121+
run_sql(f"""CREATE EXTENSION ${pname} WITH VERSION '{firstVersion}';""")
122+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
123+
assert installed_version == firstVersion, f"Expected ${pname} version {firstVersion}, but found {installed_version}"
124+
for version in versions[pg_version][1:]:
125+
run_sql(f"""ALTER EXTENSION ${pname} UPDATE TO '{version}';""")
126+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
127+
assert installed_version == version, f"Expected ${pname} version {version}, but found {installed_version}"
128+
129+
start_all()
130+
131+
server.wait_for_unit("multi-user.target")
132+
server.wait_for_unit("postgresql.service")
133+
134+
check_upgrade_path("15")
135+
136+
with subtest("Check ${pname} latest extension version"):
137+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION ${pname};'")
138+
server.succeed("sudo -u postgres psql -c 'CREATE EXTENSION ${pname};'")
139+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
140+
latestVersion = versions["15"][-1]
141+
assert f"${pname},{latestVersion}" in installed_extensions
142+
143+
with subtest("switch to postgresql 17"):
144+
server.succeed(
145+
"${pg17-configuration}/bin/switch-to-configuration test >&2"
146+
)
147+
148+
with subtest("Check ${pname} latest extension version"):
149+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
150+
latestVersion = versions["17"][-1]
151+
assert f"${pname},{latestVersion}" in installed_extensions
152+
153+
check_upgrade_path("17")
154+
'';
155+
}

nix/ext/versions.json

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
{
2-
"wrappers": {
3-
"0.5.4": {
2+
"index_advisor": {
3+
"0.2.0": {
44
"postgresql": [
55
"15",
66
"17",
77
"orioledb-17"
88
],
9-
"hash": "sha256-W1RokXH4Vfj2FIuEzGEP5SzzWsv2Pbzfa816nXKnSoc=",
10-
"pgrx": "0.14.3",
11-
"rust": "1.87.0"
9+
"hash": "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs="
1210
}
1311
},
14-
"index_advisor": {
15-
"0.2.0": {
12+
"hypopg": {
13+
"1.3.1": {
14+
"postgresql": [
15+
"15"
16+
],
17+
"hash": "sha256-AIBXy+LxyHUo+1hd8gQTwaBdFiTEzKaCVc4cx5tZgME="
18+
},
19+
"1.4.1": {
1620
"postgresql": [
1721
"15",
18-
"17",
19-
"orioledb-17"
22+
"17"
2023
],
21-
"hash": "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs="
24+
"hash": "sha256-88uKPSnITRZ2VkelI56jZ9GWazG/Rn39QlyHKJKSKMM="
2225
}
2326
},
2427
"pg_cron": {
@@ -177,5 +180,17 @@
177180
],
178181
"hash": "sha256-JsZV+I4eRMypXTjGmjCtMBXDVpqTIPHQa28ogXncE/Q="
179182
}
183+
},
184+
"wrappers": {
185+
"0.5.4": {
186+
"postgresql": [
187+
"15",
188+
"17",
189+
"orioledb-17"
190+
],
191+
"hash": "sha256-W1RokXH4Vfj2FIuEzGEP5SzzWsv2Pbzfa816nXKnSoc=",
192+
"pgrx": "0.14.3",
193+
"rust": "1.87.0"
194+
}
180195
}
181196
}

0 commit comments

Comments
 (0)