From 4849d1b9cedb534b0e47a9c58f9b9e47e1becebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roche?= Date: Fri, 27 Jun 2025 00:33:12 +0200 Subject: [PATCH] feat: support multiple versions of the pgroonga extension Build multiple versions of the pgroonga extension on different PostgreSQL versions. Add test for the extensions and their upgrade on PostgreSQL 15 and 17. --- flake.nix | 8 +- nix/ext/pgroonga.nix | 237 +++++++++++++----- nix/ext/pgroonga/default.nix | 181 +++++++++++++ .../do-not-use-vendored-libraries.patch | 0 .../pgroonga}/fix-cmake-install-path.patch | 0 .../pgroonga/supabase-groonga-14.0.5.nix} | 2 +- nix/ext/tests/pgroonga.nix | 155 ++++++++++++ nix/ext/versions.json | 17 ++ 8 files changed, 529 insertions(+), 71 deletions(-) create mode 100644 nix/ext/pgroonga/default.nix rename nix/{ => ext/pgroonga}/do-not-use-vendored-libraries.patch (100%) rename nix/{ => ext/pgroonga}/fix-cmake-install-path.patch (100%) rename nix/{supabase-groonga.nix => ext/pgroonga/supabase-groonga-14.0.5.nix} (97%) create mode 100644 nix/ext/tests/pgroonga.nix create mode 100644 nix/ext/versions.json diff --git a/flake.nix b/flake.nix index 18cd9ba13..8cd68eeb2 100644 --- a/flake.nix +++ b/flake.nix @@ -100,7 +100,7 @@ paramiko ]); sfcgal = pkgs.callPackage ./nix/ext/sfcgal/sfcgal.nix { }; - supabase-groonga = pkgs.callPackage ./nix/supabase-groonga.nix { }; + supabase-groonga = pkgs.callPackage ./nix/ext/pgroonga/supabase-groonga-14.0.5.nix { }; mecab-naist-jdic = pkgs.callPackage ./nix/ext/mecab-naist-jdic/default.nix { }; inherit (pkgs.callPackage ./nix/wal-g.nix { }) wal-g-2 wal-g-3; # Our list of PostgreSQL extensions which come from upstream Nixpkgs. @@ -132,7 +132,7 @@ ./nix/ext/rum.nix ./nix/ext/timescaledb.nix ./nix/ext/timescaledb-2.9.1.nix - ./nix/ext/pgroonga.nix + ./nix/ext/pgroonga ./nix/ext/index_advisor.nix ./nix/ext/wal2json.nix ./nix/ext/pgmq.nix @@ -344,7 +344,7 @@ PG_IDENT = "${paths.pgIdentConfigFile}"; LOCALES = "${localeArchive}"; EXTENSION_CUSTOM_SCRIPTS_DIR = "${paths.postgresqlExtensionCustomScriptsPath}"; - MECAB_LIB = "${basePackages.psql_15.exts.pgroonga}/lib/groonga/plugins/tokenizers/tokenizer_mecab.so"; + MECAB_LIB = "${supabase-groonga}/lib/groonga/plugins/tokenizers/tokenizer_mecab.so"; GROONGA_DIR = "${supabase-groonga}"; MIGRATIONS_DIR = "${paths.migrationsDir}"; POSTGRESQL_SCHEMA_SQL = "${paths.postgresqlSchemaSql}"; @@ -1384,6 +1384,8 @@ devShell = devShells.default; } // pkgs.lib.optionalAttrs (system == "aarch64-linux") { inherit (basePackages) postgresql_15_debug postgresql_15_src postgresql_orioledb-17_debug postgresql_orioledb-17_src postgresql_17_debug postgresql_17_src; + } // pkgs.lib.optionalAttrs (system == "x86_64-linux") { + pgroonga = import ./nix/ext/tests/pgroonga.nix { inherit self; inherit pkgs; }; }; # Apps is a list of names of things that can be executed with 'nix run'; diff --git a/nix/ext/pgroonga.nix b/nix/ext/pgroonga.nix index de0dedc93..2f0b3bdaa 100644 --- a/nix/ext/pgroonga.nix +++ b/nix/ext/pgroonga.nix @@ -1,78 +1,181 @@ -{ lib, stdenv, fetchurl, pkg-config, postgresql, msgpack-c, callPackage, mecab, makeWrapper, xxHash }: +{ + lib, + stdenv, + fetchurl, + pkg-config, + postgresql, + msgpack-c, + callPackage, + mecab, + makeWrapper, + xxHash, + buildEnv, +}: let - supabase-groonga = callPackage ../supabase-groonga.nix { }; -in -stdenv.mkDerivation rec { + supabase-groonga = callPackage ./supabase-groonga { }; pname = "pgroonga"; - version = "3.2.5"; - src = fetchurl { - url = "https://packages.groonga.org/source/${pname}/${pname}-${version}.tar.gz"; - sha256 = "sha256-GM9EOQty72hdE4Ecq8jpDudhZLiH3pP9ODLxs8DXcSY="; - }; - nativeBuildInputs = [ pkg-config makeWrapper ]; - - buildInputs = [ postgresql msgpack-c supabase-groonga mecab ] ++ lib.optionals stdenv.isDarwin [ - xxHash - ]; - propagatedBuildInputs = [ supabase-groonga ]; - configureFlags = [ - "--with-mecab=${mecab}" - "--enable-mecab" - "--with-groonga=${supabase-groonga}" - "--with-groonga-plugin-dir=${supabase-groonga}/lib/groonga/plugins" - ]; + # Load version configuration from external file + allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname}; - makeFlags = [ - "HAVE_MSGPACK=1" - "MSGPACK_PACKAGE_NAME=msgpack-c" - "HAVE_MECAB=1" + # Filter versions compatible with current PostgreSQL version + supportedVersions = lib.filterAttrs ( + _: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql + ) allVersions; + + # Derived version information + versions = lib.naturalSort (lib.attrNames supportedVersions); + latestVersion = lib.last versions; + numberOfVersions = builtins.length versions; + packages = builtins.attrValues ( + lib.mapAttrs (name: value: build name value.hash) supportedVersions + ); + + # List of C extensions to be included in the build + cExtensions = [ + "pgroonga" + "pgroonga_database" ]; - NIX_CFLAGS_COMPILE = lib.optionalString stdenv.isDarwin (builtins.concatStringsSep " " [ - "-Wno-error=incompatible-function-pointer-types" - "-Wno-error=format" - "-Wno-format" - "-I${supabase-groonga}/include/groonga" - "-I${xxHash}/include" - "-DPGRN_VERSION=\"${version}\"" - ]); - - preConfigure = '' - export GROONGA_LIBS="-L${supabase-groonga}/lib -lgroonga" - export GROONGA_CFLAGS="-I${supabase-groonga}/include" - export MECAB_CONFIG="${mecab}/bin/mecab-config" - ${lib.optionalString stdenv.isDarwin '' - export CPPFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" - export CFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" - export PG_CPPFLAGS="-Wno-error=incompatible-function-pointer-types -Wno-error=format" - ''} - ''; + # Build function for individual versions + build = + version: hash: + stdenv.mkDerivation rec { + inherit pname version; + + src = fetchurl { + url = "https://packages.groonga.org/source/${pname}/${pname}-${version}.tar.gz"; + inherit hash; + }; + nativeBuildInputs = [ + pkg-config + makeWrapper + ]; + + buildInputs = + [ + postgresql + msgpack-c + supabase-groonga + mecab + ] + ++ lib.optionals stdenv.isDarwin [ + xxHash + ]; + + propagatedBuildInputs = [ supabase-groonga ]; + configureFlags = [ + "--with-mecab=${mecab}" + "--enable-mecab" + "--with-groonga=${supabase-groonga}" + "--with-groonga-plugin-dir=${supabase-groonga}/lib/groonga/plugins" + ]; + + makeFlags = [ + "HAVE_MSGPACK=1" + "MSGPACK_PACKAGE_NAME=msgpack-c" + "HAVE_MECAB=1" + ]; + + NIX_CFLAGS_COMPILE = lib.optionalString stdenv.isDarwin ( + builtins.concatStringsSep " " [ + "-Wno-error=incompatible-function-pointer-types" + "-Wno-error=format" + "-Wno-format" + "-I${supabase-groonga}/include/groonga" + "-I${xxHash}/include" + "-DPGRN_VERSION=\"${version}\"" + ] + ); + + preConfigure = '' + export GROONGA_LIBS="-L${supabase-groonga}/lib -lgroonga" + export GROONGA_CFLAGS="-I${supabase-groonga}/include" + export MECAB_CONFIG="${mecab}/bin/mecab-config" + ${lib.optionalString stdenv.isDarwin '' + export CPPFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" + export CFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" + export PG_CPPFLAGS="-Wno-error=incompatible-function-pointer-types -Wno-error=format" + ''} + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{lib,share/postgresql/extension} + + for ext in ${lib.concatStringsSep " " cExtensions}; do + # Install shared library with version suffix + mv $ext${postgresql.dlSuffix} $out/lib/$ext-${version}${postgresql.dlSuffix} + + # Create version-specific control file + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/$ext'|" \ + $ext.control > $out/share/postgresql/extension/$ext--${version}.control + + # Copy SQL file to install the specific version + cp data/$ext--${version}.sql $out/share/postgresql/extension + + # Create versioned control file with modified module path + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/$ext'|" \ + $ext.control > $out/share/postgresql/extension/$ext--${version}.control + + # For the latest version, create default control file and symlink and copy SQL upgrade scripts + if [[ "${version}" == "${latestVersion}" ]]; then + { + echo "default_version = '${version}'" + cat $out/share/postgresql/extension/$ext--${version}.control + } > $out/share/postgresql/extension/$ext.control + ln -sfn $ext-${version}${postgresql.dlSuffix} $out/lib/$ext${postgresql.dlSuffix} + cp data/$ext--*--*.sql $out/share/postgresql/extension + fi + done + + echo "Debug: Groonga plugins directory contents:" + ls -l ${supabase-groonga}/lib/groonga/plugins/tokenizers/ + ''; + + meta = with lib; { + description = "A PostgreSQL extension to use Groonga as the index"; + longDescription = '' + PGroonga is a PostgreSQL extension to use Groonga as the index. + PostgreSQL supports full text search against languages that use only alphabet and digit. + It means that PostgreSQL doesn't support full text search against Japanese, Chinese and so on. + You can use super fast full text search feature against all languages by installing PGroonga into your PostgreSQL. + ''; + homepage = "https://pgroonga.github.io/"; + changelog = "https://github.com/pgroonga/pgroonga/releases/tag/${version}"; + license = licenses.postgresql; + inherit (postgresql.meta) platforms; + }; + }; +in +buildEnv { + name = pname; + paths = packages; + + pathsToLink = [ + "/lib" + "/share/postgresql/extension" + ]; + postBuild = '' + # Verify all expected library files are present + expectedFiles=${toString ((numberOfVersions + 1) * (builtins.length cExtensions))} + actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) - installPhase = '' - mkdir -p $out/lib $out/share/postgresql/extension $out/bin - install -D pgroonga${postgresql.dlSuffix} -t $out/lib/ - install -D pgroonga.control -t $out/share/postgresql/extension - install -D data/pgroonga-*.sql -t $out/share/postgresql/extension - install -D pgroonga_database${postgresql.dlSuffix} -t $out/lib/ - install -D pgroonga_database.control -t $out/share/postgresql/extension - install -D data/pgroonga_database-*.sql -t $out/share/postgresql/extension - - echo "Debug: Groonga plugins directory contents:" - ls -l ${supabase-groonga}/lib/groonga/plugins/tokenizers/ + if [[ "$actualFiles" != "$expectedFiles" ]]; then + echo "Error: Expected $expectedFiles library files, found $actualFiles" + echo "Files found:" + ls -la $out/lib/*${postgresql.dlSuffix} || true + exit 1 + fi ''; - meta = with lib; { - description = "A PostgreSQL extension to use Groonga as the index"; - longDescription = '' - PGroonga is a PostgreSQL extension to use Groonga as the index. - PostgreSQL supports full text search against languages that use only alphabet and digit. - It means that PostgreSQL doesn't support full text search against Japanese, Chinese and so on. - You can use super fast full text search feature against all languages by installing PGroonga into your PostgreSQL. - ''; - homepage = "https://pgroonga.github.io/"; - changelog = "https://github.com/pgroonga/pgroonga/releases/tag/${version}"; - license = licenses.postgresql; - platforms = postgresql.meta.platforms; + passthru = { + inherit versions numberOfVersions; + pname = "${pname}-all"; + version = + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } diff --git a/nix/ext/pgroonga/default.nix b/nix/ext/pgroonga/default.nix new file mode 100644 index 000000000..7f59458f6 --- /dev/null +++ b/nix/ext/pgroonga/default.nix @@ -0,0 +1,181 @@ +{ + lib, + stdenv, + fetchurl, + pkg-config, + postgresql, + msgpack-c, + callPackage, + mecab, + makeWrapper, + xxHash, + buildEnv, + system, +}: +let + pname = "pgroonga"; + + # Load version configuration from external file + allVersions = (builtins.fromJSON (builtins.readFile ../versions.json)).${pname}; + + # Filter versions compatible with current PostgreSQL version + supportedVersions = lib.filterAttrs ( + _: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql + ) allVersions; + + # Derived version information + versions = lib.naturalSort (lib.attrNames supportedVersions); + latestVersion = lib.last versions; + numberOfVersions = builtins.length versions; + packages = builtins.attrValues ( + lib.mapAttrs (name: value: build name value.hash) supportedVersions + ); + + # List of C extensions to be included in the build + cExtensions = [ + "pgroonga" + "pgroonga_database" + ]; + + # Build function for individual versions + build = + version: hash: + let + supabase-groonga = callPackage ./supabase-groonga-14.0.5.nix { }; + in + stdenv.mkDerivation rec { + inherit pname version; + + src = fetchurl { + url = "https://packages.groonga.org/source/${pname}/${pname}-${version}.tar.gz"; + inherit hash; + }; + nativeBuildInputs = [ + pkg-config + makeWrapper + ]; + + buildInputs = + [ + postgresql + msgpack-c + supabase-groonga + mecab + ] + ++ lib.optionals stdenv.isDarwin [ + xxHash + ]; + + propagatedBuildInputs = [ supabase-groonga ]; + configureFlags = [ + "--with-mecab=${mecab}" + "--enable-mecab" + "--with-groonga=${supabase-groonga}" + "--with-groonga-plugin-dir=${supabase-groonga}/lib/groonga/plugins" + ]; + + makeFlags = [ + "HAVE_MSGPACK=1" + "MSGPACK_PACKAGE_NAME=msgpack-c" + "HAVE_MECAB=1" + ]; + + NIX_CFLAGS_COMPILE = lib.optionalString stdenv.isDarwin ( + builtins.concatStringsSep " " [ + "-Wno-error=incompatible-function-pointer-types" + "-Wno-error=format" + "-Wno-format" + "-I${supabase-groonga}/include/groonga" + "-I${xxHash}/include" + "-DPGRN_VERSION=\"${version}\"" + ] + ); + + preConfigure = '' + export GROONGA_LIBS="-L${supabase-groonga}/lib -lgroonga" + export GROONGA_CFLAGS="-I${supabase-groonga}/include" + export MECAB_CONFIG="${mecab}/bin/mecab-config" + ${lib.optionalString stdenv.isDarwin '' + export CPPFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" + export CFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" + export PG_CPPFLAGS="-Wno-error=incompatible-function-pointer-types -Wno-error=format" + ''} + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{lib,share/postgresql/extension} + + for ext in ${lib.concatStringsSep " " cExtensions}; do + # Install shared library with version suffix + mv $ext${postgresql.dlSuffix} $out/lib/$ext-${version}${postgresql.dlSuffix} + + # Create version-specific control file + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/$ext'|" \ + $ext.control > $out/share/postgresql/extension/$ext--${version}.control + + # Copy SQL file to install the specific version + cp data/$ext--${version}.sql $out/share/postgresql/extension + + # Create versioned control file with modified module path + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/$ext'|" \ + $ext.control > $out/share/postgresql/extension/$ext--${version}.control + + # For the latest version, create default control file and symlink and copy SQL upgrade scripts + if [[ "${version}" == "${latestVersion}" ]]; then + { + echo "default_version = '${version}'" + cat $out/share/postgresql/extension/$ext--${version}.control + } > $out/share/postgresql/extension/$ext.control + ln -sfn $ext-${version}${postgresql.dlSuffix} $out/lib/$ext${postgresql.dlSuffix} + cp data/$ext--*--*.sql $out/share/postgresql/extension + fi + done + ''; + + meta = with lib; { + description = "A PostgreSQL extension to use Groonga as the index"; + longDescription = '' + PGroonga is a PostgreSQL extension to use Groonga as the index. + PostgreSQL supports full text search against languages that use only alphabet and digit. + It means that PostgreSQL doesn't support full text search against Japanese, Chinese and so on. + You can use super fast full text search feature against all languages by installing PGroonga into your PostgreSQL. + ''; + homepage = "https://pgroonga.github.io/"; + changelog = "https://github.com/pgroonga/pgroonga/releases/tag/${version}"; + license = licenses.postgresql; + inherit (postgresql.meta) platforms; + }; + }; +in +buildEnv { + name = pname; + paths = packages; + + pathsToLink = [ + "/lib" + "/share/postgresql/extension" + ]; + postBuild = '' + # Verify all expected library files are present + expectedFiles=${toString ((numberOfVersions + 1) * (builtins.length cExtensions))} + actualFiles=$(ls -l $out/lib/${pname}*${postgresql.dlSuffix} | wc -l) + + if [[ "$actualFiles" != "$expectedFiles" ]]; then + echo "Error: Expected $expectedFiles library files, found $actualFiles" + echo "Files found:" + ls -la $out/lib/*${postgresql.dlSuffix} || true + exit 1 + fi + ''; + + passthru = { + inherit versions numberOfVersions; + pname = "${pname}-all"; + version = + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + }; +} diff --git a/nix/do-not-use-vendored-libraries.patch b/nix/ext/pgroonga/do-not-use-vendored-libraries.patch similarity index 100% rename from nix/do-not-use-vendored-libraries.patch rename to nix/ext/pgroonga/do-not-use-vendored-libraries.patch diff --git a/nix/fix-cmake-install-path.patch b/nix/ext/pgroonga/fix-cmake-install-path.patch similarity index 100% rename from nix/fix-cmake-install-path.patch rename to nix/ext/pgroonga/fix-cmake-install-path.patch diff --git a/nix/supabase-groonga.nix b/nix/ext/pgroonga/supabase-groonga-14.0.5.nix similarity index 97% rename from nix/supabase-groonga.nix rename to nix/ext/pgroonga/supabase-groonga-14.0.5.nix index 5035f369f..0f376f2f0 100644 --- a/nix/supabase-groonga.nix +++ b/nix/ext/pgroonga/supabase-groonga-14.0.5.nix @@ -2,7 +2,7 @@ , testers, xxHash, zstd, postgresqlPackages, makeWrapper, suggestSupport ? false , zeromq, libevent, openssl, lz4Support ? false, lz4, zlibSupport ? true, zlib , writeShellScriptBin, callPackage }: -let mecab-naist-jdic = callPackage ./ext/mecab-naist-jdic { }; +let mecab-naist-jdic = callPackage ../mecab-naist-jdic { }; in stdenv.mkDerivation (finalAttrs: { pname = "supabase-groonga"; version = "14.0.5"; diff --git a/nix/ext/tests/pgroonga.nix b/nix/ext/tests/pgroonga.nix new file mode 100644 index 000000000..12240cafe --- /dev/null +++ b/nix/ext/tests/pgroonga.nix @@ -0,0 +1,155 @@ +{ self, pkgs }: +let + pname = "pgroonga"; + 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) + ]; + 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.openssh = { + enable = true; + }; + + 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" + ) + + with subtest("Check ${pname} latest extension version after upgrade"): + installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""") + latestVersion = versions["17"][-1] + assert f"${pname},{latestVersion}" in installed_extensions + + check_upgrade_path("17") + ''; +} diff --git a/nix/ext/versions.json b/nix/ext/versions.json new file mode 100644 index 000000000..91fbbbe7d --- /dev/null +++ b/nix/ext/versions.json @@ -0,0 +1,17 @@ +{ + "pgroonga": { + "3.0.7": { + "postgresql": [ + "15" + ], + "hash": "sha256-iF/zh4zDDpAw5fxW1WG8i2bfPt4VYsnYArwOoE/lwgM=" + }, + "3.2.5": { + "postgresql": [ + "15", + "17" + ], + "hash": "sha256-GM9EOQty72hdE4Ecq8jpDudhZLiH3pP9ODLxs8DXcSY=" + } + } +}