From b99cccbcb51ff31257fdc197db7ff35379006c7f Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 7 Aug 2025 15:37:57 -0400 Subject: [PATCH 1/3] feat: pg_cron multi-version with new pattern --- nix/ext/pg_cron.nix | 86 ++++++++++++++++++------ nix/ext/pg_cron/pg_cron-1.3.1-pg15.patch | 31 +++++++++ nix/ext/versions.json | 33 +++++++++ 3 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 nix/ext/pg_cron/pg_cron-1.3.1-pg15.patch diff --git a/nix/ext/pg_cron.nix b/nix/ext/pg_cron.nix index bcaaf180c..92c6c9a43 100644 --- a/nix/ext/pg_cron.nix +++ b/nix/ext/pg_cron.nix @@ -1,36 +1,80 @@ { + pkgs, lib, stdenv, fetchFromGitHub, 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 [ ]); + + installPhase = '' + mkdir -p $out/{lib,share/postgresql/extension} + + # Install shared library with version suffix + mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix} + + # Create version-specific control file + sed -e "/^default_version =/d" \ + -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}-${version}'|" \ + ${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control - installPhase = '' - mkdir -p $out/{lib,share/postgresql/extension} + # 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/${pname}--${version}.control + } > $out/share/postgresql/extension/${pname}.control + ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} + cp *.sql $out/share/postgresql/extension + fi + ''; - cp *${postgresql.dlSuffix} $out/lib - cp *.sql $out/share/postgresql/extension - cp *.control $out/share/postgresql/extension - ''; + 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 +pkgs.buildEnv { + name = pname; + paths = packages; + pathsToLink = [ + "/lib" + "/share/postgresql/extension" + ]; - 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; + passthru = { + inherit versions numberOfVersions; + pname = "${pname}-all"; + version = + "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; } 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=" + } } } From 7c0e496aad0aee2182cbfe73c097f0735cb7e1ff Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 7 Aug 2025 16:11:32 -0400 Subject: [PATCH 2/3] feat: pg_cron using the new multi-version pattern not yet complete --- nix/ext/pg_cron.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nix/ext/pg_cron.nix b/nix/ext/pg_cron.nix index 92c6c9a43..3fc20bd3a 100644 --- a/nix/ext/pg_cron.nix +++ b/nix/ext/pg_cron.nix @@ -42,6 +42,9 @@ let -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}-${version}'|" \ ${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control + # Create version-specific SQL file + cp ${pname}.sql $out/share/postgresql/extension/${pname}--${version}.sql + # For the latest version, create default control file and symlink and copy SQL upgrade scripts if [[ "${version}" == "${latestVersion}" ]]; then { From 886a86ba68beda891170154227f74d9f5bcb347f Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 7 Aug 2025 16:53:58 -0400 Subject: [PATCH 3/3] fix: bring in some function from previous version to test --- nix/ext/pg_cron.nix | 145 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 22 deletions(-) diff --git a/nix/ext/pg_cron.nix b/nix/ext/pg_cron.nix index 3fc20bd3a..22b75627a 100644 --- a/nix/ext/pg_cron.nix +++ b/nix/ext/pg_cron.nix @@ -1,5 +1,4 @@ { - pkgs, lib, stdenv, fetchFromGitHub, @@ -31,28 +30,38 @@ let 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 shared library with version suffix - mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix} + # Install versioned library + install -Dm755 ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix} - # Create version-specific control file - sed -e "/^default_version =/d" \ - -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}-${version}'|" \ - ${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control + # Install version-specific files + install -Dm644 ${pname}--${version}.sql $out/share/postgresql/extension/ + install -Dm644 ${pname}--${version}.control $out/share/postgresql/extension/ - # Create version-specific SQL file - cp ${pname}.sql $out/share/postgresql/extension/${pname}--${version}.sql + # 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 and copy SQL upgrade scripts + # 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}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} - cp *.sql $out/share/postgresql/extension + ln -sfn ${pname}-${version}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix} fi ''; @@ -66,18 +75,110 @@ let }; packages = builtins.attrValues (lib.mapAttrs (name: value: build name value) supportedVersions); in -pkgs.buildEnv { - name = pname; - paths = packages; - pathsToLink = [ - "/lib" - "/share/postgresql/extension" - ]; +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,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/') + + # 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; - pname = "${pname}-all"; - version = - "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + }; + + meta = with lib; { + description = "Run Cron jobs through PostgreSQL (multi-version compatible)"; + homepage = "https://github.com/citusdata/pg_cron"; + platforms = postgresql.meta.platforms; + license = licenses.postgresql; }; }