diff --git a/nix/ext/pg_cron.nix b/nix/ext/pg_cron.nix index bcaaf180c..22b75627a 100644 --- a/nix/ext/pg_cron.nix +++ b/nix/ext/pg_cron.nix @@ -5,31 +5,179 @@ postgresql, }: -stdenv.mkDerivation rec { +let pname = "pg_cron"; - version = "1.6.4"; + 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: versionData: + stdenv.mkDerivation rec { + inherit pname version; - buildInputs = [ postgresql ]; + buildInputs = [ postgresql ]; - src = fetchFromGitHub { - owner = "citusdata"; - repo = pname; - rev = "v${version}"; - hash = "sha256-t1DpFkPiSfdoGG2NgNT7g1lkvSooZoRoUrix6cBID40="; - }; + src = fetchFromGitHub { + owner = "citusdata"; + repo = pname; + rev = versionData.rev or "v${version}"; + hash = versionData.hash; + }; + + patches = map (p: ./. + "/${p}") (versionData.patches or [ ]); + + buildPhase = '' + make PG_CONFIG=${postgresql}/bin/pg_config + + # Create version-specific SQL file + cp pg_cron.sql pg_cron--${version}.sql + + # Create versioned control file with modified module path + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/pg_cron'|" \ + pg_cron.control > pg_cron--${version}.control + ''; + + installPhase = '' + mkdir -p $out/{lib,share/postgresql/extension} + + # Install versioned library + install -Dm755 ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix} + + # Install version-specific files + install -Dm644 ${pname}--${version}.sql $out/share/postgresql/extension/ + install -Dm644 ${pname}--${version}.control $out/share/postgresql/extension/ + + # Install upgrade scripts + find . -name 'pg_cron--*--*.sql' -exec install -Dm644 {} $out/share/postgresql/extension/ \; + + # For the latest version, create default control file and symlink + if [[ "${version}" == "${latestVersion}" ]]; then + { + echo "default_version = '${version}'" + cat $out/share/postgresql/extension/${pname}--${version}.control + } > $out/share/postgresql/extension/${pname}.control + ln -sfn ${pname}-${version}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} + fi + ''; + + meta = with lib; { + description = "Run Cron jobs through PostgreSQL"; + homepage = "https://github.com/citusdata/pg_cron"; + changelog = "https://github.com/citusdata/pg_cron/raw/v${version}/CHANGELOG.md"; + platforms = postgresql.meta.platforms; + license = licenses.postgresql; + }; + }; + packages = builtins.attrValues (lib.mapAttrs (name: value: build name value) supportedVersions); +in +stdenv.mkDerivation { + pname = "${pname}-all"; + version = + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + + buildInputs = packages; + + dontUnpack = true; + dontConfigure = true; + dontBuild = true; installPhase = '' - mkdir -p $out/{lib,share/postgresql/extension} + mkdir -p $out/{lib,share/postgresql/extension,bin} + + # Install all versions + for drv in ${lib.concatStringsSep " " packages}; do + ln -sv $drv/lib/* $out/lib/ + cp -v --no-clobber $drv/share/postgresql/extension/* $out/share/postgresql/extension/ || true + done + + # Find latest version + latest_control=$(ls -v $out/share/postgresql/extension/${pname}--*.control | tail -n1) + latest_version=$(basename "$latest_control" | sed -E 's/${pname}--([0-9.]+).control/\1/') - cp *${postgresql.dlSuffix} $out/lib - cp *.sql $out/share/postgresql/extension - cp *.control $out/share/postgresql/extension + # Create main control file only if it doesn't exist + if [ ! -f "$out/share/postgresql/extension/${pname}.control" ]; then + # Create main control file with default_version + echo "default_version = '$latest_version'" > $out/share/postgresql/extension/${pname}.control + cat "$latest_control" >> $out/share/postgresql/extension/${pname}.control + fi + + # Library symlink - only if it doesn't exist + if [ ! -f "$out/lib/${pname}${postgresql.dlSuffix}" ]; then + ln -sfnv ${pname}-$latest_version${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} + fi + + # Create version switcher script + cat > $out/bin/switch_pg_cron_version <<'EOF' + #!/bin/sh + set -e + + if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 1.4.2" + exit 1 + fi + + VERSION=$1 + NIX_PROFILE="/var/lib/postgresql/.nix-profile" + + # Follow the complete chain of symlinks to find the multi-version directory + CURRENT_LINK="$NIX_PROFILE/lib/pg_cron-$VERSION${postgresql.dlSuffix}" + echo "Starting with link: $CURRENT_LINK" + + # Follow first two symlinks to get to the multi-version directory + for i in 1 2; do + if [ -L "$CURRENT_LINK" ]; then + NEXT_LINK=$(readlink "$CURRENT_LINK") + echo "Following link: $NEXT_LINK" + if echo "$NEXT_LINK" | grep -q '^/'; then + CURRENT_LINK="$NEXT_LINK" + else + CURRENT_LINK="$(dirname "$CURRENT_LINK")/$NEXT_LINK" + fi + echo "Current link is now: $CURRENT_LINK" + fi + done + + # The multi-version directory should be the parent of the current link + MULTI_VERSION_DIR=$(dirname "$CURRENT_LINK") + echo "Found multi-version directory: $MULTI_VERSION_DIR" + LIB_DIR="$MULTI_VERSION_DIR" + EXTENSION_DIR="$NIX_PROFILE/share/postgresql/extension" + + echo "Looking for file: $LIB_DIR/pg_cron-$VERSION${postgresql.dlSuffix}" + ls -la "$LIB_DIR" || true + + # Check if version exists + if [ ! -f "$LIB_DIR/pg_cron-$VERSION${postgresql.dlSuffix}" ]; then + echo "Error: Version $VERSION not found" + exit 1 + fi + + # Update library symlink + ln -sfnv "pg_cron-$VERSION${postgresql.dlSuffix}" "$LIB_DIR/pg_cron${postgresql.dlSuffix}" + + # Update control file + echo "default_version = '$VERSION'" > "$EXTENSION_DIR/pg_cron.control" + cat "$EXTENSION_DIR/pg_cron--$VERSION.control" >> "$EXTENSION_DIR/pg_cron.control" + + echo "Successfully switched pg_cron to version $VERSION" + EOF + + chmod +x $out/bin/switch_pg_cron_version ''; + passthru = { + inherit versions numberOfVersions; + }; + meta = with lib; { - description = "Run Cron jobs through PostgreSQL"; + description = "Run Cron jobs through PostgreSQL (multi-version compatible)"; homepage = "https://github.com/citusdata/pg_cron"; - changelog = "https://github.com/citusdata/pg_cron/raw/v${version}/CHANGELOG.md"; platforms = postgresql.meta.platforms; license = licenses.postgresql; }; diff --git a/nix/ext/pg_cron/pg_cron-1.3.1-pg15.patch b/nix/ext/pg_cron/pg_cron-1.3.1-pg15.patch new file mode 100644 index 000000000..6e496aabe --- /dev/null +++ b/nix/ext/pg_cron/pg_cron-1.3.1-pg15.patch @@ -0,0 +1,31 @@ +diff --git a/src/pg_cron.c b/src/pg_cron.c +index e0ca973..4d51b2c 100644 +--- a/src/pg_cron.c ++++ b/src/pg_cron.c +@@ -14,6 +14,8 @@ + #include + + #include "postgres.h" ++#include "commands/async.h" ++#include "miscadmin.h" + #include "fmgr.h" + + /* these are always necessary for a bgworker */ +@@ -1908,7 +1910,7 @@ CronBackgroundWorker(Datum main_arg) + /* Post-execution cleanup. */ + disable_timeout(STATEMENT_TIMEOUT, false); + CommitTransactionCommand(); +- ProcessCompletedNotifies(); ++ /* ProcessCompletedNotifies removed */ + pgstat_report_activity(STATE_IDLE, command); + pgstat_report_stat(true); + +@@ -2025,7 +2027,7 @@ ExecuteSqlString(const char *sql) + */ + oldcontext = MemoryContextSwitchTo(parsecontext); + #if PG_VERSION_NUM >= 100000 +- querytree_list = pg_analyze_and_rewrite(parsetree, sql, NULL, 0,NULL); ++ querytree_list = pg_analyze_and_rewrite_fixedparams(parsetree, sql, NULL, 0, NULL); + #else + querytree_list = pg_analyze_and_rewrite(parsetree, sql, NULL, 0); + #endif \ No newline at end of file diff --git a/nix/ext/versions.json b/nix/ext/versions.json index c77b23be6..086efe751 100644 --- a/nix/ext/versions.json +++ b/nix/ext/versions.json @@ -20,5 +20,38 @@ ], "hash": "sha256-G0eQk2bY5CNPMeokN/nb05g03CuiplRf902YXFVQFbs=" } + }, + "pg_cron": { + "1.3.1": { + "postgresql": [ + "15" + ], + "rev": "v1.3.1", + "hash": "sha256-rXotNOtQNmA55ErNxGoNSKZ0pP1uxEVlDGITFHuqGG4=", + "patches": [ "pg_cron/pg_cron-1.3.1-pg15.patch" ] + }, + "1.4.2": { + "postgresql": [ + "15" + ], + "rev": "v1.4.2", + "hash": "sha256-P0Fd10Q1p+KrExb35G6otHpc6pD61WnMll45H2jkevM=" + }, + "1.5.2": { + "postgresql": [ + "15" + ], + "rev": "v1.5.2", + "hash": "sha256-+quVWbKJy6wXpL/zwTk5FF7sYwHA7I97WhWmPO/HSZ4=" + }, + "1.6.4": { + "postgresql": [ + "15", + "17", + "orioledb-17" + ], + "rev": "v1.6.4", + "hash": "sha256-t1DpFkPiSfdoGG2NgNT7g1lkvSooZoRoUrix6cBID40=" + } } }