Skip to content

Commit 8c158fb

Browse files
jfrochesamrose
authored andcommitted
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 5da417f commit 8c158fb

File tree

4 files changed

+332
-69
lines changed

4 files changed

+332
-69
lines changed

ansible/vars.yml

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

1111
# Full version strings for each major version
1212
postgres_release:
13-
postgresorioledb-17: 17.5.1.032-orioledb
14-
postgres17: 17.6.1.011
15-
postgres15: 15.14.1.011
13+
postgresorioledb-17: 17.5.1.032-orioledb-postgis-1
14+
postgres17: 17.6.1.011-postgis-1
15+
postgres15: 15.14.1.011-postgis-1
1616

1717
# Non Postgres Extensions
1818
pgbouncer_release: 1.19.0

nix/ext/postgis.nix

Lines changed: 158 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -15,88 +15,180 @@
1515
pcre2,
1616
nixosTests,
1717
callPackage,
18+
buildEnv,
1819
}:
1920

2021
let
2122
sfcgal = callPackage ./sfcgal/sfcgal.nix { };
2223
gdal = callPackage ./gdal.nix { inherit postgresql; };
23-
in
24-
stdenv.mkDerivation rec {
2524
pname = "postgis";
26-
version = "3.3.7";
2725

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

33-
src = fetchurl {
34-
url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
35-
sha256 = "sha256-UHJKDd5JrcJT5Z4CTYsY/va+ToU0GUPG1eHhuXTkP84=";
36-
};
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;
3733

38-
buildInputs = [
39-
libxml2
40-
postgresql
41-
geos
42-
proj
43-
gdal
44-
json_c
45-
protobufc
46-
pcre2.dev
47-
sfcgal
48-
] ++ lib.optional stdenv.isDarwin libiconv;
49-
nativeBuildInputs = [
50-
perl
51-
pkg-config
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+
);
41+
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"
5249
];
53-
dontDisableStatic = true;
5450

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

57-
preConfigure = ''
58-
sed -i 's@/usr/bin/file@${file}/bin/file@' configure
59-
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;
6061

61-
makeFlags="PERL=${perl}/bin/perl datadir=$out/share/postgresql pkglibdir=$out/lib bindir=$out/bin docdir=$doc/share/doc/${pname}"
62-
'';
62+
outputs = [
63+
"out"
64+
"doc"
65+
];
6366

64-
postConfigure = ''
65-
sed -i "s|@mkdir -p \$(DESTDIR)\$(PGSQL_BINDIR)||g ;
66-
s|\$(DESTDIR)\$(PGSQL_BINDIR)|$prefix/bin|g
67-
" \
68-
"raster/loader/Makefile";
69-
sed -i "s|\$(DESTDIR)\$(PGSQL_BINDIR)|$prefix/bin|g
70-
" \
71-
"raster/scripts/python/Makefile";
72-
mkdir -p $out/bin
73-
ln -s ${postgresql}/bin/postgres $out/bin/postgres
74-
'';
67+
src = fetchurl {
68+
url = "https://download.osgeo.org/postgis/source/postgis-${version}.tar.gz";
69+
inherit hash;
70+
};
7571

76-
postInstall = ''
77-
rm $out/bin/postgres
78-
for prog in $out/bin/*; do # */
79-
ln -s $prog $prog-${version}
80-
done
81-
# Add function definition and usage to tiger geocoder files
82-
for file in $out/share/postgresql/extension/postgis_tiger_geocoder*--${version}.sql; do
83-
sed -i "/SELECT postgis_extension_AddToSearchPath('tiger');/a SELECT postgis_extension_AddToSearchPath('extensions');" "$file"
84-
done
85-
# Original topology patching
86-
for file in $out/share/postgresql/extension/postgis_topology*--${version}.sql; do
87-
sed -i "/SELECT topology.AddToSearchPath('topology');/i SELECT topology.AddToSearchPath('extensions');" "$file"
88-
done
89-
mkdir -p $doc/share/doc/postgis
90-
mv doc/* $doc/share/doc/postgis/
91-
'';
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+
'';
92109

93-
passthru.tests.postgis = nixosTests.postgis;
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)
179+
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
186+
'';
94187

95-
meta = with lib; {
96-
description = "Geographic Objects for PostgreSQL";
97-
homepage = "https://postgis.net/";
98-
changelog = "https://git.osgeo.org/gitea/postgis/postgis/raw/tag/${version}/NEWS";
99-
license = licenses.gpl2;
100-
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);
101193
};
102194
}

0 commit comments

Comments
 (0)