I’m developing a PostgreSQL extension and I want to be able to test it. I’ve managed to get it compiled, so I have the necessary .so, .control, .sql files and all that. They just need to be moved into the right directories in order to be loadable by the CREATE EXTENSION
command. This would normally be automatically done by the Makefile (like this one) using make install
. The problem is that those directories are immutable (/run/current-system/sw/share/postgresql
aka /nix/store/ygqkd75dny3rljgrnrv6zdqgmwnh679b-postgresql-and-plugins-14.10/share/postgresql/
and others).
My thinking is that I’ll need to build a custom postgresql server preloaded with my extension every time I make a change. Unfortunately my nix-fu isn’t strong and looking at package sources for postgresql, postgis, isn’t helping. I would greatly appreciate some guidance here.
Update: I’ve gotten it mostly working with this shell.nix:
{ pkgs ? import <nixpkgs> {} }:
let
myExtension = pkgs.stdenv.mkDerivation rec {
pname = "myExtension";
version = "0.1.0";
src = ./.;
buildInputs = [ pkgs.postgresql ];
makeFlags = [
"USE_PGXS=1"
];
installPhase = ''
mkdir -p $out/lib
mkdir -p $out/share/postgresql/extension
install -D ${pname}.so -t $out/lib
install -D ${pname}.control -t $out/share/postgresql/extension
install -D ${pname}--${version}.sql -t $out/share/postgresql/extension
'';
};
postgresqlSrc = pkgs.fetchurl {
url = "https://ftp.postgresql.org/pub/source/v${pkgs.postgresql.version}/postgresql-${pkgs.postgresql.version}.tar.bz2";
sha256 = "sha256-j1OqldeOuOglNupGtoGHeTtCu6O09lqjQvVAsjybEKY=";
};
modifiedPostgresql = pkgs.postgresql.overrideAttrs (old: {
src = postgresqlSrc;
configureFlags = old.configureFlags ++ [
"--with-includes=${myExtension}/include"
"--with-libraries=${myExtension}/lib"
];
postInstall = ''
${old.postInstall or ""}
# Copy over the extension files
mkdir -p $out/share/postgresql/extension
mkdir -p $lib/lib
cp -r ${myExtension}/share/postgresql/extension/* $out/share/postgresql/extension
cp -r ${myExtension}/lib/* $lib/lib
'';
# postInstall = ''
# ${old.postInstall or ""}
# # Copy over the extension files
# mkdir -p $out/share/postgresql/extension
# cp -r ${myExtension}/share/postgresql/extension/* $out/share/postgresql/extension
# '';
});
in
pkgs.mkShell {
buildInputs = [ modifiedPostgresql ];
shellHook = ''
export PATH=${modifiedPostgresql}/bin:$PATH
'';
}
Makefile:
EXTENSION = myExtension
DATA = myExtension--0.1.0.sql
# Check if nix exists, and set PG_CONFIG accordingly
IS_NIX := $(shell which nix > /dev/null 2>&1 && echo yes || echo no)
ifeq ($(IS_NIX),yes)
PG_CONFIG = ./pg_config_nix
else
PG_CONFIG = pg_config
endif
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
pg_config_nix:
#!/usr/bin/env bash
# pg_config on NixOS returns some wrong outputs
# this wrapper script aims to correct that
set -euo pipefail
INCLUDEDIR=$(nix-store -r $(which postgres) 2>/dev/null)/include
if [[ $# -eq 0 ]]; then
pg_config | grep -v INCLUDEDIR
echo "INCLUDEDIR = $INCLUDEDIR"
echo "PKGINCLUDEDIR = $INCLUDEDIR"
echo "INCLUDEDIR-SERVER = $INCLUDEDIR/server"
exit 0
fi
# Handle specific arguments
for arg in "$@"
do
case $arg in
--includedir) echo $INCLUDEDIR; break;;
--pkgincludedir) echo $INCLUDEDIR; break;;
--includedir-server) echo "$INCLUDEDIR/server"; break;;
*) pg_config $arg; break;;
esac
done
However, every time I want to test the extension again the entirety of postgresql needs to be rebuilt. Still working on a solution for that. Would appreciate any help!
Here’s what I’ve settled on for anyone who runs into the same problem. It seems hacky, unfortunately.
let
postgres = pkgs.postgresql_16;
postgresqlSrc = pkgs.fetchurl {
url = "https://ftp.postgresql.org/pub/source/v${postgres.version}/postgresql-${postgres.version}.tar.bz2";
sha256 = "sha256-zjxNhdGbASH+DT+O8fpgH3GYnob4pm99w61UbdVWT+w=";
};
pwd = builtins.getEnv "PWD";
modifiedPostgresql = postgres.overrideAttrs (old: {
src = postgresqlSrc;
postInstall = ''
${old.postInstall or ""}
# Copy over the extension files
mkdir -p $out/share/postgresql/extension
mkdir -p $lib/lib
ln -s ${pwd}/myExtension.so $lib/lib
ln -s ${pwd}/myExtension.control $out/share/postgresql/extension
ln -s ${pwd}/myExtension--0.1.0.sql $out/share/postgresql/extension
'';
});
in
pkgs.mkShell {
buildInputs = [ modifiedPostgresql ];
shellHook = ''
export PATH=${modifiedPostgresql}/bin:$PATH
'';
}