Skip to content

Commit 9cb7409

Browse files
jfrochesamrose
andauthored
feat: support multiple versions of the index_advisor extension (#1671)
* feat: multiple versions for the index_advisor extension Build multiple versions of the index_advisor extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17. * Change VM name suffix * chore: bump testing version * chore: formatting * tests: bump version to test * fix: account for access needed by macos * fix: handle flake check user in darwin env * fix: pin version of macos * fix: trying without cleanup * fix: revert workflow * fix: disable pgtap * fix: restore tap tests * fix: restore and check version * chore: bump version for final testing * fix: include orioledb-17 in index_advisor * feat: bump version to release --------- Co-authored-by: Sam Rose <[email protected]>
1 parent b3ce15f commit 9cb7409

File tree

5 files changed

+230
-22
lines changed

5 files changed

+230
-22
lines changed

.github/workflows/nix-build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ jobs:
8282
- name: Aggressive disk cleanup for DuckDB build
8383
if: matrix.runner == 'macos-latest-xlarge'
8484
run: |
85+
nix --version
8586
echo "=== BEFORE CLEANUP ==="
8687
df -h
8788
# Remove major space consumers

ansible/vars.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ postgres_major:
99

1010
# Full version strings for each major version
1111
postgres_release:
12-
postgresorioledb-17: "17.5.1.012-orioledb"
13-
postgres17: "17.4.1.069"
14-
postgres15: "15.8.1.126"
12+
postgresorioledb-17: "17.5.1.013-orioledb"
13+
postgres17: "17.4.1.070"
14+
postgres15: "15.8.1.127"
1515

1616
# Non Postgres Extensions
1717
pgbouncer_release: "1.19.0"

nix/ext/index_advisor.nix

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,84 @@
11
{
2+
pkgs,
23
lib,
34
stdenv,
45
fetchFromGitHub,
56
postgresql,
67
}:
78

8-
stdenv.mkDerivation rec {
9+
let
910
pname = "index_advisor";
10-
version = "0.2.0";
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 = "olirice";
16-
repo = pname;
17-
rev = "v${version}";
18-
hash = "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs=";
19-
};
25+
src = fetchFromGitHub {
26+
owner = "olirice";
27+
repo = pname;
28+
rev = "v${version}";
29+
inherit hash;
30+
};
31+
32+
installPhase = ''
33+
mkdir -p $out/{lib,share/postgresql/extension}
34+
35+
create_sql_files() {
36+
echo "Creating SQL files for previous versions..."
37+
if [[ "${version}" == "${latestVersion}" ]]; then
38+
cp *.sql $out/share/postgresql/extension
39+
fi
40+
}
41+
42+
create_control_files() {
43+
sed -e "/^default_version =/d" \
44+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
45+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
46+
47+
if [[ "${version}" == "${latestVersion}" ]]; then
48+
{
49+
echo "default_version = '${latestVersion}'"
50+
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
51+
} > $out/share/postgresql/extension/${pname}.control
52+
fi
53+
}
2054
21-
installPhase = ''
22-
mkdir -p $out/{lib,share/postgresql/extension}
55+
create_sql_files
56+
create_control_files
57+
'';
2358

24-
cp *.sql $out/share/postgresql/extension
25-
cp *.control $out/share/postgresql/extension
26-
'';
59+
meta = with lib; {
60+
description = "Recommend indexes to improve query performance in PostgreSQL";
61+
homepage = "https://github.com/olirice/index_advisor";
62+
license = licenses.postgresql;
63+
inherit (postgresql.meta) platforms;
64+
};
65+
};
66+
packages = builtins.attrValues (
67+
lib.mapAttrs (name: value: build name value.hash) supportedVersions
68+
);
69+
in
70+
pkgs.buildEnv {
71+
name = pname;
72+
paths = packages;
73+
pathsToLink = [
74+
"/lib"
75+
"/share/postgresql/extension"
76+
];
2777

28-
meta = with lib; {
29-
description = "Recommend indexes to improve query performance in PostgreSQL";
30-
homepage = "https://github.com/olirice/index_advisor";
31-
platforms = postgresql.meta.platforms;
32-
license = licenses.postgresql;
78+
passthru = {
79+
inherit versions numberOfVersions;
80+
pname = "${pname}-all";
81+
version =
82+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
3383
};
3484
}

nix/ext/tests/index_advisor.nix

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

nix/ext/versions.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,15 @@
1010
"pgrx": "0.14.3",
1111
"rust": "1.87.0"
1212
}
13+
},
14+
"index_advisor": {
15+
"0.2.0": {
16+
"postgresql": [
17+
"15",
18+
"17",
19+
"orioledb-17"
20+
],
21+
"hash": "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs="
22+
}
1323
}
1424
}

0 commit comments

Comments
 (0)