Skip to content
1 change: 1 addition & 0 deletions .github/workflows/nix-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ jobs:
- name: Aggressive disk cleanup for DuckDB build
if: matrix.runner == 'macos-latest-xlarge'
run: |
nix --version
echo "=== BEFORE CLEANUP ==="
df -h
# Remove major space consumers
Expand Down
6 changes: 3 additions & 3 deletions ansible/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ postgres_major:

# Full version strings for each major version
postgres_release:
postgresorioledb-17: "17.5.1.012-orioledb"
postgres17: "17.4.1.069"
postgres15: "15.8.1.126"
postgresorioledb-17: "17.5.1.013-orioledb"
postgres17: "17.4.1.070"
postgres15: "15.8.1.127"

# Non Postgres Extensions
pgbouncer_release: "1.19.0"
Expand Down
88 changes: 69 additions & 19 deletions nix/ext/index_advisor.nix
Original file line number Diff line number Diff line change
@@ -1,34 +1,84 @@
{
pkgs,
lib,
stdenv,
fetchFromGitHub,
postgresql,
}:

stdenv.mkDerivation rec {
let
pname = "index_advisor";
version = "0.2.0";
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
supportedVersions = lib.filterAttrs (
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
) allVersions;
versions = lib.naturalSort (lib.attrNames supportedVersions);
latestVersion = lib.last versions;
numberOfVersions = builtins.length versions;
build =
version: hash:
stdenv.mkDerivation rec {
inherit pname version;

buildInputs = [ postgresql ];
buildInputs = [ postgresql ];

src = fetchFromGitHub {
owner = "olirice";
repo = pname;
rev = "v${version}";
hash = "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs=";
};
src = fetchFromGitHub {
owner = "olirice";
repo = pname;
rev = "v${version}";
inherit hash;
};

installPhase = ''
mkdir -p $out/{lib,share/postgresql/extension}

create_sql_files() {
echo "Creating SQL files for previous versions..."
if [[ "${version}" == "${latestVersion}" ]]; then
cp *.sql $out/share/postgresql/extension
fi
}

create_control_files() {
sed -e "/^default_version =/d" \
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control

if [[ "${version}" == "${latestVersion}" ]]; then
{
echo "default_version = '${latestVersion}'"
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
} > $out/share/postgresql/extension/${pname}.control
fi
}

installPhase = ''
mkdir -p $out/{lib,share/postgresql/extension}
create_sql_files
create_control_files
'';

cp *.sql $out/share/postgresql/extension
cp *.control $out/share/postgresql/extension
'';
meta = with lib; {
description = "Recommend indexes to improve query performance in PostgreSQL";
homepage = "https://github.com/olirice/index_advisor";
license = licenses.postgresql;
inherit (postgresql.meta) platforms;
};
};
packages = builtins.attrValues (
lib.mapAttrs (name: value: build name value.hash) supportedVersions
);
in
pkgs.buildEnv {
name = pname;
paths = packages;
pathsToLink = [
"/lib"
"/share/postgresql/extension"
];

meta = with lib; {
description = "Recommend indexes to improve query performance in PostgreSQL";
homepage = "https://github.com/olirice/index_advisor";
platforms = postgresql.meta.platforms;
license = licenses.postgresql;
passthru = {
inherit versions numberOfVersions;
pname = "${pname}-all";
version =
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
};
}
147 changes: 147 additions & 0 deletions nix/ext/tests/index_advisor.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
{ self, pkgs }:
let
pname = "index_advisor";
inherit (pkgs) lib;
installedExtension =
postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
postgresqlWithExtension =
postgresql:
let
majorVersion = lib.versions.major postgresql.version;
pkg = pkgs.buildEnv {
name = "postgresql-${majorVersion}-${pname}";
paths = [
postgresql
postgresql.lib
(installedExtension majorVersion)
self.packages.${pkgs.system}."psql_${majorVersion}/exts/hypopg" # dependency
];
passthru = {
inherit (postgresql) version psqlSchema;
lib = pkg;
withPackages = _: pkg;
};
nativeBuildInputs = [ pkgs.makeWrapper ];
pathsToLink = [
"/"
"/bin"
"/lib"
];
postBuild = ''
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
'';
};
in
pkg;
in
self.inputs.nixpkgs.lib.nixos.runTest {
name = pname;
hostPkgs = pkgs;
nodes.server =
{ config, ... }:
{
virtualisation = {
forwardPorts = [
{
from = "host";
host.port = 13022;
guest.port = 22;
}
];
};

services.postgresql = {
enable = true;
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
};

specialisation.postgresql17.configuration = {
services.postgresql = {
package = lib.mkForce (postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17);
};

systemd.services.postgresql-migrate = {
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "postgres";
Group = "postgres";
StateDirectory = "postgresql";
WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
};
script =
let
oldPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
newPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
in
''
if [[ ! -d ${newDataDir} ]]; then
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
${newPostgresql}/bin/initdb -D "${newDataDir}"
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
else
echo "${newDataDir} already exists"
fi
'';
};

systemd.services.postgresql = {
after = [ "postgresql-migrate.service" ];
requires = [ "postgresql-migrate.service" ];
};
};
};
testScript =
{ nodes, ... }:
let
pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
in
''
versions = {
"15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
}

def run_sql(query):
return server.succeed(f"""sudo -u postgres psql -t -A -F\",\" -c \"{query}\" """).strip()

def check_upgrade_path(pg_version):
with subtest("Check ${pname} upgrade path"):
firstVersion = versions[pg_version][0]
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION IF EXISTS ${pname};'")
run_sql(f"""CREATE EXTENSION ${pname} WITH VERSION '{firstVersion}' CASCADE;""")
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
assert installed_version == firstVersion, f"Expected ${pname} version {firstVersion}, but found {installed_version}"
for version in versions[pg_version][1:]:
run_sql(f"""ALTER EXTENSION ${pname} UPDATE TO '{version}';""")
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
assert installed_version == version, f"Expected ${pname} version {version}, but found {installed_version}"

start_all()

server.wait_for_unit("multi-user.target")
server.wait_for_unit("postgresql.service")

check_upgrade_path("15")

with subtest("Check ${pname} latest extension version"):
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION ${pname};'")
server.succeed("sudo -u postgres psql -c 'CREATE EXTENSION ${pname} CASCADE;'")
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
latestVersion = versions["15"][-1]
assert f"${pname},{latestVersion}" in installed_extensions

with subtest("switch to postgresql 17"):
server.succeed(
"${pg17-configuration}/bin/switch-to-configuration test >&2"
)

check_upgrade_path("17")
'';
}
10 changes: 10 additions & 0 deletions nix/ext/versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,15 @@
"pgrx": "0.14.3",
"rust": "1.87.0"
}
},
"index_advisor": {
"0.2.0": {
"postgresql": [
"15",
"17",
"orioledb-17"
],
"hash": "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs="
}
}
}