Skip to content

Commit ac8a377

Browse files
committed
feat: support multiple versions of the postgis extension
Build multiple versions of the postgis extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17.
1 parent 7d78f14 commit ac8a377

File tree

4 files changed

+351
-68
lines changed

4 files changed

+351
-68
lines changed

flake.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,8 @@
13841384
devShell = devShells.default;
13851385
} // pkgs.lib.optionalAttrs (system == "aarch64-linux") {
13861386
inherit (basePackages) postgresql_15_debug postgresql_15_src postgresql_orioledb-17_debug postgresql_orioledb-17_src postgresql_17_debug postgresql_17_src;
1387+
} // pkgs.lib.optionalAttrs (system == "x86_64-linux") {
1388+
postgis = import ./nix/ext/tests/postgis.nix { inherit self; inherit pkgs; };
13871389
};
13881390

13891391
# Apps is a list of names of things that can be executed with 'nix run';

nix/ext/postgis.nix

Lines changed: 176 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,194 @@
1-
{ fetchurl
2-
, lib, stdenv
3-
, perl
4-
, libxml2
5-
, postgresql
6-
, geos
7-
, proj
8-
, json_c
9-
, pkg-config
10-
, file
11-
, protobufc
12-
, libiconv
13-
, pcre2
14-
, nixosTests
15-
, callPackage
1+
{
2+
fetchurl,
3+
lib,
4+
stdenv,
5+
perl,
6+
libxml2,
7+
postgresql,
8+
geos,
9+
proj,
10+
json_c,
11+
pkg-config,
12+
file,
13+
protobufc,
14+
libiconv,
15+
pcre2,
16+
nixosTests,
17+
callPackage,
18+
buildEnv,
1619
}:
1720

1821
let
1922
sfcgal = callPackage ./sfcgal/sfcgal.nix { };
2023
gdal = callPackage ./gdal.nix { inherit postgresql; };
21-
in
22-
stdenv.mkDerivation rec {
2324
pname = "postgis";
24-
version = "3.3.7";
2525

26-
outputs = [ "out" "doc" ];
26+
# Load version configuration from external file
27+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
2728

28-
src = fetchurl {
29-
url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
30-
sha256 = "sha256-UHJKDd5JrcJT5Z4CTYsY/va+ToU0GUPG1eHhuXTkP84=";
31-
};
29+
# Filter versions compatible with current PostgreSQL version
30+
supportedVersions = lib.filterAttrs (
31+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
32+
) allVersions;
3233

33-
buildInputs = [ libxml2 postgresql geos proj gdal json_c protobufc pcre2.dev sfcgal ]
34-
++ lib.optional stdenv.isDarwin libiconv;
35-
nativeBuildInputs = [ perl pkg-config ];
36-
dontDisableStatic = true;
34+
# Derived version information
35+
versions = lib.naturalSort (lib.attrNames supportedVersions);
36+
latestVersion = lib.last versions;
37+
numberOfVersions = builtins.length versions;
38+
packages = builtins.attrValues (
39+
lib.mapAttrs (name: value: build name value.hash) supportedVersions
40+
);
3741

42+
# List of C extensions to be included in the build
43+
cExtensions = [
44+
"address_standardizer"
45+
"postgis"
46+
"postgis_raster"
47+
"postgis_sfcgal"
48+
"postgis_topology"
49+
];
3850

39-
env.NIX_LDFLAGS = "-L${lib.getLib json_c}/lib";
51+
sqlExtensions = [
52+
"address_standardizer_data_us"
53+
"postgis_tiger_geocoder"
54+
];
4055

41-
preConfigure = ''
42-
sed -i 's@/usr/bin/file@${file}/bin/file@' configure
43-
configureFlags="--datadir=$out/share/postgresql --datarootdir=$out/share/postgresql --bindir=$out/bin --docdir=$doc/share/doc/${pname} --with-gdalconfig=${gdal}/bin/gdal-config --with-jsondir=${json_c.dev} --disable-extension-upgrades-install --with-sfcgal"
56+
# Build function for individual versions
57+
build =
58+
version: hash:
59+
stdenv.mkDerivation rec {
60+
inherit pname version;
4461

45-
makeFlags="PERL=${perl}/bin/perl datadir=$out/share/postgresql pkglibdir=$out/lib bindir=$out/bin docdir=$doc/share/doc/${pname}"
46-
'';
62+
outputs = [
63+
"out"
64+
"doc"
65+
];
66+
67+
src = fetchurl {
68+
url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
69+
inherit hash;
70+
};
71+
72+
buildInputs = [
73+
libxml2
74+
postgresql
75+
geos
76+
proj
77+
gdal
78+
json_c
79+
protobufc
80+
pcre2.dev
81+
sfcgal
82+
] ++ lib.optional stdenv.isDarwin libiconv;
83+
nativeBuildInputs = [
84+
perl
85+
pkg-config
86+
];
87+
dontDisableStatic = true;
88+
89+
env.NIX_LDFLAGS = "-L${lib.getLib json_c}/lib";
90+
91+
preConfigure = ''
92+
sed -i 's@/usr/bin/file@${file}/bin/file@' configure
93+
configureFlags="--datadir=$out/share/postgresql --datarootdir=$out/share/postgresql --bindir=$out/bin --docdir=$doc/share/doc/${pname} --with-gdalconfig=${gdal}/bin/gdal-config --with-jsondir=${json_c.dev} --with-sfcgal --with-library-minor-version"
94+
95+
makeFlags="PERL=${perl}/bin/perl datadir=$out/share/postgresql pkglibdir=$out/lib bindir=$out/bin docdir=$doc/share/doc/${pname}"
96+
'';
97+
98+
postConfigure = ''
99+
sed -i "s|@mkdir -p \$(DESTDIR)\$(PGSQL_BINDIR)||g ;
100+
s|\$(DESTDIR)\$(PGSQL_BINDIR)|$prefix/bin|g
101+
" \
102+
"raster/loader/Makefile";
103+
sed -i "s|\$(DESTDIR)\$(PGSQL_BINDIR)|$prefix/bin|g
104+
" \
105+
"raster/scripts/python/Makefile";
106+
mkdir -p $out/bin
107+
ln -s ${postgresql}/bin/postgres $out/bin/postgres
108+
'';
109+
110+
postInstall = ''
111+
MIN_MAJ_VERSION=${lib.concatStringsSep "." (lib.take 2 (builtins.splitVersion version))}
112+
rm $out/bin/postgres
113+
114+
# move control files
115+
for ext in ${lib.concatStringsSep " " (cExtensions ++ sqlExtensions)}; do
116+
sed -e "/^default_version =/d" \
117+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/$ext'|" \
118+
$out/share/postgresql/extension/$ext.control > $out/share/postgresql/extension/$ext--$MIN_MAJ_VERSION.control
119+
rm $out/share/postgresql/extension/$ext.control
120+
ln -s $out/share/postgresql/extension/$ext--${version}.sql $out/share/postgresql/extension/$ext--$MIN_MAJ_VERSION.sql
121+
done
122+
123+
# Add function definition and usage to tiger geocoder files
124+
for file in $out/share/postgresql/extension/postgis_tiger_geocoder*--${version}.sql; do
125+
sed -i "/SELECT postgis_extension_AddToSearchPath('tiger');/a SELECT postgis_extension_AddToSearchPath('extensions');" "$file"
126+
done
127+
# Original topology patching
128+
for file in $out/share/postgresql/extension/postgis_topology*--${version}.sql; do
129+
sed -i "/SELECT topology.AddToSearchPath('topology');/i SELECT topology.AddToSearchPath('extensions');" "$file"
130+
done
131+
132+
# For the latest version, create default control file and symlink and copy SQL upgrade scripts
133+
if [[ "${version}" == "${latestVersion}" ]]; then
134+
for ext in ${lib.concatStringsSep " " (cExtensions ++ sqlExtensions)}; do
135+
{
136+
echo "default_version = '$MIN_MAJ_VERSION'"
137+
cat $out/share/postgresql/extension/$ext--$MIN_MAJ_VERSION.control
138+
} > $out/share/postgresql/extension/$ext.control
139+
done
140+
for prog in $out/bin/*; do # */
141+
ln -s $prog $prog-$MIN_MAJ_VERSION
142+
done
143+
else
144+
# remove migration scripts for non-latest version
145+
find $out/share/postgresql/extension -regex '.*--.*--.*\.sql' -delete
146+
147+
for prog in $out/bin/*; do # */
148+
mv $prog $prog-$MIN_MAJ_VERSION
149+
done
150+
fi
151+
152+
mkdir -p $doc/share/doc/postgis
153+
mv doc/* $doc/share/doc/postgis/
154+
'';
155+
156+
passthru.tests.postgis = nixosTests.postgis;
157+
158+
meta = with lib; {
159+
description = "Geographic Objects for PostgreSQL";
160+
homepage = "https://postgis.net/";
161+
changelog = "https://git.osgeo.org/gitea/postgis/postgis/raw/tag/${version}/NEWS";
162+
license = licenses.gpl2;
163+
inherit (postgresql.meta) platforms;
164+
};
165+
};
166+
in
167+
buildEnv {
168+
name = pname;
169+
paths = packages;
170+
171+
pathsToLink = [
172+
"/lib"
173+
"/share/postgresql/extension"
174+
];
175+
postBuild = ''
176+
# Verify all expected library files are present
177+
expectedFiles=${toString (numberOfVersions * builtins.length cExtensions)}
178+
actualFiles=$(ls -A $out/lib/*${postgresql.dlSuffix} | wc -l)
47179
48-
postConfigure = ''
49-
sed -i "s|@mkdir -p \$(DESTDIR)\$(PGSQL_BINDIR)||g ;
50-
s|\$(DESTDIR)\$(PGSQL_BINDIR)|$prefix/bin|g
51-
" \
52-
"raster/loader/Makefile";
53-
sed -i "s|\$(DESTDIR)\$(PGSQL_BINDIR)|$prefix/bin|g
54-
" \
55-
"raster/scripts/python/Makefile";
56-
mkdir -p $out/bin
57-
ln -s ${postgresql}/bin/postgres $out/bin/postgres
180+
if [[ "$actualFiles" != "$expectedFiles" ]]; then
181+
echo "Error: Expected $expectedFiles library files, found $actualFiles"
182+
echo "Files found:"
183+
ls -la $out/lib/${pname}*${postgresql.dlSuffix} || true
184+
exit 1
185+
fi
58186
'';
59187

60-
postInstall = ''
61-
rm $out/bin/postgres
62-
for prog in $out/bin/*; do # */
63-
ln -s $prog $prog-${version}
64-
done
65-
# Add function definition and usage to tiger geocoder files
66-
for file in $out/share/postgresql/extension/postgis_tiger_geocoder*--${version}.sql; do
67-
sed -i "/SELECT postgis_extension_AddToSearchPath('tiger');/a SELECT postgis_extension_AddToSearchPath('extensions');" "$file"
68-
done
69-
# Original topology patching
70-
for file in $out/share/postgresql/extension/postgis_topology*--${version}.sql; do
71-
sed -i "/SELECT topology.AddToSearchPath('topology');/i SELECT topology.AddToSearchPath('extensions');" "$file"
72-
done
73-
mkdir -p $doc/share/doc/postgis
74-
mv doc/* $doc/share/doc/postgis/
75-
'';
76-
77-
passthru.tests.postgis = nixosTests.postgis;
78-
79-
meta = with lib; {
80-
description = "Geographic Objects for PostgreSQL";
81-
homepage = "https://postgis.net/";
82-
changelog = "https://git.osgeo.org/gitea/postgis/postgis/raw/tag/${version}/NEWS";
83-
license = licenses.gpl2;
84-
inherit (postgresql.meta) platforms;
188+
passthru = {
189+
inherit versions numberOfVersions;
190+
pname = "${pname}-all";
191+
version =
192+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
85193
};
86194
}

0 commit comments

Comments
 (0)