diff --git a/flake.lock b/flake.lock index 836d098524..cbd114d119 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1764011051, - "narHash": "sha256-M7SZyPZiqZUR/EiiBJnmyUbOi5oE/03tCeFrTiUZchI=", + "lastModified": 1791918082, + "narHash": "sha256-oN9JrhRfHa7MUTdUq+11dHn7u0Z4WfEA4mhzBq0/zoQ=", "owner": "numtide", "repo": "devshell", - "rev": "17ed8d9744ebe70424659b0ef74ad6d41fc87071", + "rev": "9e29c63dde99a2d80c94b3d024c9768c01544558", "type": "github" }, "original": { @@ -23,15 +23,15 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1761588595, - "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", - "owner": "edolstra", + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", "repo": "flake-compat", - "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", "type": "github" }, "original": { - "owner": "edolstra", + "owner": "NixOS", "repo": "flake-compat", "type": "github" } @@ -41,11 +41,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1763759067, - "narHash": "sha256-LlLt2Jo/gMNYAwOgdRQBrsRoOz7BPRkzvNaI/fzXi2Q=", + "lastModified": 1790898470, + "narHash": "sha256-zTwuwezD0w3hpga6a6P8emidzAZFyWqlNeRBlpWOOl8=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "2cccadc7357c0ba201788ae99c4dfa90728ef5e0", + "rev": "024633cd702b10285db5cb19b40ad48d2399ba60", "type": "github" }, "original": { @@ -59,11 +59,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "lastModified": 1791914995, + "narHash": "sha256-Zf/xfQEAasnwnmEfHqW/4hjDE/s44yn2hD4RuVIZRjA=", "owner": "numtide", "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "rev": "b7a79d3fea1e214f6d668d521cecec0c01e26544", "type": "github" }, "original": { @@ -75,17 +75,16 @@ "git-hooks": { "inputs": { "flake-compat": "flake-compat", - "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1765016596, - "narHash": "sha256-rhSqPNxDVow7OQKi4qS5H8Au0P4S3AYbawBSmJNUtBQ=", + "lastModified": 1791909798, + "narHash": "sha256-VAhpCOmrun/KXimYfR8NM88bciKCui7CqHHhThSzgag=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "548fc44fca28a5e81c5d6b846e555e6b9c2a5a3c", + "rev": "1ba1dbfe28738c9a71c266be6efa5b89e75491a9", "type": "github" }, "original": { @@ -94,27 +93,6 @@ "type": "github" } }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "multigres": { "flake": false, "locked": { @@ -134,15 +112,16 @@ "nix": { "flake": false, "locked": { - "lastModified": 1760472641, - "narHash": "sha256-BuKtM7Vr5EcxBXxUENBQPlOBwmNd5mkTRkSmlJi/iQ4=", + "lastModified": 1789275486, + "narHash": "sha256-EI9fkyw+PmuGCshQfVyn3+ttkrvl4Gh3Xse9PF+AuLY=", "owner": "NixOS", "repo": "nix", - "rev": "4041bfdb401ad6d1c31a292fab90392254be506a", + "rev": "88c2bcc16964d092d5ae1ba3f1e8b53dea497556", "type": "github" }, "original": { "owner": "NixOS", + "ref": "2.35-maintenance", "repo": "nix", "type": "github" } @@ -154,15 +133,16 @@ ] }, "locked": { - "lastModified": 1767718503, - "narHash": "sha256-V+VkFs0aSG0ca8p/N3gib7FAf4cq9jyr5Gm+ZBrHQpo=", + "lastModified": 1792800221, + "narHash": "sha256-53jIZEWNh96irEXhsMZFoNhLJgGSU3nYl1i4wFQHAsU=", "owner": "nix-darwin", "repo": "nix-darwin", - "rev": "9f48ffaca1f44b3e590976b4da8666a9e86e6eb1", + "rev": "d31953cf55f9027a56e9be938daf5db8c5655663", "type": "github" }, "original": { "owner": "nix-darwin", + "ref": "nix-darwin-26.05", "repo": "nix-darwin", "type": "github" } @@ -192,9 +172,6 @@ }, "nix-eval-jobs": { "inputs": { - "flake-parts": [ - "flake-parts" - ], "nix": "nix", "nixpkgs": "nixpkgs", "treefmt-nix": [ @@ -202,11 +179,11 @@ ] }, "locked": { - "lastModified": 1760478325, - "narHash": "sha256-hA+NOH8KDcsuvH7vJqSwk74PyZP3MtvI/l+CggZcnTc=", + "lastModified": 1789638029, + "narHash": "sha256-t1FbcjvTWQ1WO3hJNKN+viNXuz4BX9Pte5K4F+IJLDk=", "owner": "nix-community", "repo": "nix-eval-jobs", - "rev": "daa42f9e9c84aeff1e325dd50fda321f53dfd02c", + "rev": "9f1553afabd95f9f59951f5c946e86005af7196a", "type": "github" }, "original": { @@ -222,11 +199,11 @@ ] }, "locked": { - "lastModified": 1761716996, - "narHash": "sha256-vdOuy2pid2/DasUgb08lDOswdPJkN5qjXfBYItVy/R4=", + "lastModified": 1793342482, + "narHash": "sha256-poBaF2bJUH3yGMav3TSOi7k84jy8BnU8HD6PONQAwak=", "owner": "nlewo", "repo": "nix2container", - "rev": "e5496ab66e9de9e3f67dc06f692dfbc471b6316e", + "rev": "42d1df94f001a9416ef08be7b305144074aca9d2", "type": "github" }, "original": { @@ -237,11 +214,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 315532800, - "narHash": "sha256-vhAtaRMIQiEghARviANBmSnhGz9Qf2IQJ+nQgsDXnVs=", - "rev": "c12c63cd6c5eb34c7b4c3076c6a99e00fcab86ec", + "lastModified": 1789264731, + "narHash": "sha256-iR1Jj6svMpvLxPWA40qp+WUpg3MStLXJy5TZrP2cPes=", + "rev": "02f5696b0e6097e589076d886b317b83ff0437d7", "type": "tarball", - "url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre877036.c12c63cd6c5e/nixexprs.tar.xz" + "url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1072974.02f5696b0e60/nixexprs.tar.xz" }, "original": { "type": "tarball", @@ -250,11 +227,11 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1761765539, - "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=", + "lastModified": 1790477367, + "narHash": "sha256-oujbxmVKDhci2E4EM3KyAbRUgp5/IsCoiA/LfEF7OOk=", "owner": "nix-community", "repo": "nixpkgs.lib", - "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc", + "rev": "f7cd230690d9fc982d06129f9189b101fddcfa3b", "type": "github" }, "original": { @@ -281,15 +258,15 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1767379071, - "narHash": "sha256-3xDI4xtzovwqE/eAxCwmXxUqBg6Yoam2L1u0IwRNhW4=", - "rev": "fb7944c166a3b630f177938e478f0378e64ce108", + "lastModified": 1793294725, + "narHash": "sha256-X+Mp4wtwS+b17lw2puLuzn9e63ZrMKFucvlIUG7xf8I=", + "rev": "6f06d204d8f2d8761d9da78778745974a3216381", "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz" + "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.13164.6f06d204d8f2/nixexprs.tar.xz" }, "original": { "type": "tarball", - "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" + "url": "https://channels.nixos.org/nixos-26.05/nixexprs.tar.xz" } }, "root": { @@ -316,11 +293,11 @@ ] }, "locked": { - "lastModified": 1787834454, - "narHash": "sha256-jXSvqn04IOecJCvSvl8+g3PsbDVNP6qKs6dKUs/b16k=", + "lastModified": 1793434469, + "narHash": "sha256-+sgVNI2c67di+XIeMaz5KSei4T65kX68s5Nl0E5Gzbc=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "dc2fd1acc537f3583744e1373597a5731ff7a6e3", + "rev": "6ecf534a7c16e7c969f26838fdd8c93597ae93f3", "type": "github" }, "original": { @@ -351,11 +328,11 @@ ] }, "locked": { - "lastModified": 1762938485, - "narHash": "sha256-AlEObg0syDl+Spi4LsZIBrjw+snSVU4T8MOeuZJUJjM=", + "lastModified": 1791885023, + "narHash": "sha256-C3alQ2MEt0zVrUSho5NUDo3jmhbff72++bfwoqT9Omo=", "owner": "numtide", "repo": "treefmt-nix", - "rev": "5b4ee75aeefd1e2d5a1cc43cf6ba65eba75e83e4", + "rev": "0d6d739a833ba9a9c93034862e4a7b061a062a1c", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b952a57089..db387b955f 100644 --- a/flake.nix +++ b/flake.nix @@ -14,7 +14,7 @@ multigres.url = "github:multigres/multigres"; multigres.flake = false; nix-darwin.inputs.nixpkgs.follows = "nixpkgs"; - nix-darwin.url = "github:nix-darwin/nix-darwin"; + nix-darwin.url = "github:nix-darwin/nix-darwin/nix-darwin-26.05"; nix-editor.inputs.nixpkgs.follows = "nixpkgs"; nix-editor.inputs.utils.follows = "flake-utils"; nix-editor.url = "github:snowfallorg/nix-editor"; @@ -23,10 +23,9 @@ nix-eval-jobs.url = "github:nix-community/nix-eval-jobs"; nix2container.inputs.nixpkgs.follows = "nixpkgs"; nix2container.url = "github:nlewo/nix2container"; - # Pin to a specific nixpkgs version that has compatible v8 and curl versions - # for extensions that require older package versions + # Pin to a specific nixpkgs version that still has the v8 version plv8 needs nixpkgs-oldstable.url = "github:NixOS/nixpkgs/a76c4553d7e741e17f289224eda135423de0491d"; - nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; + nixpkgs.url = "https://channels.nixos.org/nixos-26.05/nixexprs.tar.xz"; rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; rust-overlay.url = "github:oxalica/rust-overlay"; treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/cargo-pgrx/default.nix b/nix/cargo-pgrx/default.nix index f2342c02c8..64e12ec21a 100644 --- a/nix/cargo-pgrx/default.nix +++ b/nix/cargo-pgrx/default.nix @@ -1,6 +1,5 @@ { lib, - pkgs, fetchCrate, openssl, pkg-config, @@ -10,11 +9,10 @@ rustVersion ? "1.85.1", }: let - # TODO: remove once nixpkgs is bumped past NixOS/nixpkgs#512735 - rustPlatform = import ./fix-cargo.nix { inherit pkgs; } (makeRustPlatform { + rustPlatform = makeRustPlatform { cargo = rust-bin.stable.${rustVersion}.default; rustc = rust-bin.stable.${rustVersion}.default; - }); + }; in { mkCargoPgrx = @@ -34,11 +32,7 @@ in auditable = false; inherit pname; inherit version; - # TODO: remove once nixpkgs is bumped past NixOS/nixpkgs#512735 - src = fetchCrate { - inherit version pname hash; - registryDl = "https://static.crates.io/crates"; - }; + src = fetchCrate { inherit version pname hash; }; inherit cargoHash; nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ pkg-config ]; buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ openssl ]; diff --git a/nix/cargo-pgrx/fix-cargo.nix b/nix/cargo-pgrx/fix-cargo.nix deleted file mode 100644 index 13a642cc86..0000000000 --- a/nix/cargo-pgrx/fix-cargo.nix +++ /dev/null @@ -1,60 +0,0 @@ -# workaround: crates.io blocks python-requests' default UA (nixpkgs#512735) -# TODO: remove once nixpkgs pin includes that fix -{ pkgs }: -rustPlatform: -let - fixedUtilBin = rustPlatform.callPackage ( - { writers, python3Packages }: - writers.writePython3Bin "fetch-cargo-vendor-util" - { - libraries = - with python3Packages; - [ - requests - tomli-w - ] - ++ requests.optional-dependencies.socks; - flakeIgnore = [ "E501" ]; - } - ( - builtins.readFile ( - pkgs.fetchurl { - url = "https://raw.githubusercontent.com/NixOS/nixpkgs/941b631956516306effaed1641bd00f2ab2e570b/pkgs/build-support/rust/fetch-cargo-vendor-util-v2.py"; - hash = "sha256-hnL0hh8vFgMBXV8kDDezRV40+CHpwtSVlzG0dyQpZXg="; - } - ) - ) - ) { }; -in -rustPlatform.overrideScope ( - _final: prev: { - fetchCargoVendor = - args: - (prev.fetchCargoVendor args).overrideAttrs (old: { - vendorStaging = old.vendorStaging.overrideAttrs (oldStaging: { - nativeBuildInputs = map ( - x: if (x.pname or x.name or "") == "fetch-cargo-vendor-util" then fixedUtilBin else x - ) oldStaging.nativeBuildInputs; - }); - }); - importCargoLock = - args: - let - orig = prev.importCargoLock ( - args - // { - extraRegistries = { - "https://github.com/rust-lang/crates.io-index" = "https://static.crates.io/crates"; - } - // (args.extraRegistries or { }); - } - ); - in - # strip the duplicate crates-io source stanza extraRegistries adds, or cargo metadata breaks - pkgs.runCommand orig.name { } '' - cp -r ${orig} $out - chmod -R u+w $out - sed -i '\|\[source\."https://github.com/rust-lang/crates.io-index"\]|,+2d' $out/.cargo/config.toml - ''; - } -) diff --git a/nix/cargo-pgrx/mkPgrxExtension.nix b/nix/cargo-pgrx/mkPgrxExtension.nix index d1190817ed..862dcdc074 100644 --- a/nix/cargo-pgrx/mkPgrxExtension.nix +++ b/nix/cargo-pgrx/mkPgrxExtension.nix @@ -1,6 +1,5 @@ { callPackage, - pkgs, rustVersion, pgrxVersion, makeRustPlatform, @@ -10,13 +9,10 @@ let inherit ((callPackage ./default.nix { inherit rustVersion rust-bin; })) mkCargoPgrx; - # TODO: drop the fix-cargo.nix import once nixpkgs is bumped past NixOS/nixpkgs#512735 - rustPlatform = import ./fix-cargo.nix { inherit pkgs; } ( - import ./crate-fetchurl.nix (makeRustPlatform { - cargo = rust-bin.stable.${rustVersion}.default; - rustc = rust-bin.stable.${rustVersion}.default; - }) - ); + rustPlatform = import ./crate-fetchurl.nix (makeRustPlatform { + cargo = rust-bin.stable.${rustVersion}.default; + rustc = rust-bin.stable.${rustVersion}.default; + }); versions = builtins.fromJSON (builtins.readFile ./versions.json); diff --git a/nix/checks.nix b/nix/checks.nix index 875ca9f81f..e0545b0fba 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -957,7 +957,7 @@ ''; collation-version-check = let - baseline = "glibc-2.40-66"; + baseline = "glibc-2.42-103"; check = name: actual: lib.assertMsg (actual == baseline) '' diff --git a/nix/docs/updating-dependencies.md b/nix/docs/updating-dependencies.md index c9157b00da..b46e759c98 100644 --- a/nix/docs/updating-dependencies.md +++ b/nix/docs/updating-dependencies.md @@ -28,3 +28,9 @@ Similar patterns can be followed for other dependencies defined in the nix packa 2. Update version numbers and hashes 3. Run local tests 4. Verify functionality before creating PR + +## Updating nixpkgs + +`nixpkgs` tracks the current NixOS stable channel and builds everything, including Postgres and its extensions. Update it with `nix flake update nixpkgs`. When the stable release changes, also move `nix-darwin` to the matching `nix-darwin-YY.MM` branch. + +A nixpkgs update can change glibc. After a glibc change, Postgres warns that the collation version stored in each database differs from the running one, until each database runs `ALTER DATABASE ... REFRESH COLLATION VERSION`. diff --git a/nix/ext/pgroonga/default.nix b/nix/ext/pgroonga/default.nix index b9c3829a0d..91bdaf9c26 100644 --- a/nix/ext/pgroonga/default.nix +++ b/nix/ext/pgroonga/default.nix @@ -7,7 +7,7 @@ msgpack-c, mecab, makeWrapper, - xxHash, + xxhash, buildEnv, supabase-groonga, mecab-naist-jdic, @@ -64,7 +64,7 @@ let supabase-groonga mecab ] - ++ lib.optionals stdenv.isDarwin [ xxHash ]; + ++ lib.optionals stdenv.isDarwin [ xxhash ]; propagatedBuildInputs = [ supabase-groonga @@ -89,7 +89,7 @@ let "-Wno-error=format" "-Wno-format" "-I${supabase-groonga}/include/groonga" - "-I${xxHash}/include" + "-I${xxhash}/include" "-DPGRN_VERSION=\"${version}\"" ] ); @@ -100,8 +100,8 @@ let export MECAB_CONFIG="${mecab}/bin/mecab-config" export MECAB_DICDIR="${mecab-naist-jdic}/lib/mecab/dic/naist-jdic" ${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 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" ''} ''; diff --git a/nix/ext/pgroonga/groonga.nix b/nix/ext/pgroonga/groonga.nix index c6d734db6c..41eb756ac2 100644 --- a/nix/ext/pgroonga/groonga.nix +++ b/nix/ext/pgroonga/groonga.nix @@ -8,7 +8,7 @@ mecab, pkg-config, rapidjson, - xxHash, + xxhash, zstd, makeWrapper, suggestSupport ? false, @@ -38,14 +38,14 @@ stdenv.mkDerivation (finalAttrs: { ]; buildInputs = [ rapidjson - xxHash + xxhash zstd mecab kytea msgpack-c ] ++ lib.optionals lz4Support [ lz4 ] - ++ lib.optional zlibSupport [ zlib ] + ++ lib.optionals zlibSupport [ zlib ] ++ lib.optionals suggestSupport [ zeromq libevent diff --git a/nix/ext/tests/lib.py b/nix/ext/tests/lib.py index b2cdbb7bc4..5f677f1729 100644 --- a/nix/ext/tests/lib.py +++ b/nix/ext/tests/lib.py @@ -7,7 +7,7 @@ from typing import Sequence, Mapping, Optional from pathlib import Path -from test_driver.machine import Machine +from test_driver.machine import QemuMachine Versions = Mapping[str, Sequence[str]] @@ -15,7 +15,7 @@ class PostgresExtensionTest(object): def __init__( self, - vm: Machine, + vm: QemuMachine, extension_name: str, versions: Versions, sql_test_dir: Path, diff --git a/nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch b/nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch new file mode 100644 index 0000000000..1a1766675c --- /dev/null +++ b/nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch @@ -0,0 +1,127 @@ +--- a/ncurses/tinfo/lib_baudrate.c 2026-07-31 08:24:24 ++++ b/ncurses/tinfo/lib_baudrate.c 2026-07-31 12:03:39 +@@ -45,6 +45,39 @@ + #endif + + /* ++ * On Linux/glibc, resolve cfgetospeed to the old (functionally identical) ++ * GLIBC_2.17 symbol version at runtime, so binaries built against newer ++ * glibc still run on hosts with older glibc that only export that version. ++ * Done via dlvsym rather than a link-time .symver directive, since the ++ * latter conflicts with ncurses' own --version-script linking. Both dlvsym ++ * and its dlsym fallback are declared directly (rather than via ++ * /_GNU_SOURCE, which may already be locked in by earlier headers ++ * in this file), and neither path calls the bare cfgetospeed identifier, so ++ * no versioned reference to it survives in the compiled output. ++ */ ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++static speed_t ++_supabase_compat_cfgetospeed(const struct termios *t) ++{ ++ static int inited = 0; ++ static speed_t (*fn)(const struct termios *) = NULL; ++ if (!inited) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlvsym((void *) 0, "cfgetospeed", "GLIBC_2.17"); ++ if (!fn) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlsym((void *) 0, "cfgetospeed"); ++ } ++ inited = 1; ++ } ++ return fn ? fn(t) : 0; ++} ++#define cfgetospeed(t) _supabase_compat_cfgetospeed(t) ++#endif ++ ++/* + * These systems use similar header files, which define B1200 as 1200, etc., + * but can be overridden by defining USE_OLD_TTY so B1200 is 9, which makes all + * of the indices up to B115200 fit nicely in a 'short', allowing us to retain +--- a/ncurses/tinfo/tinfo_driver.c 2026-07-31 08:24:24 ++++ b/ncurses/tinfo/tinfo_driver.c 2026-07-31 12:03:50 +@@ -37,6 +37,39 @@ + #include + #include /* ospeed */ + ++/* ++ * On Linux/glibc, resolve cfgetospeed to the old (functionally identical) ++ * GLIBC_2.17 symbol version at runtime, so binaries built against newer ++ * glibc still run on hosts with older glibc that only export that version. ++ * Done via dlvsym rather than a link-time .symver directive, since the ++ * latter conflicts with ncurses' own --version-script linking. Both dlvsym ++ * and its dlsym fallback are declared directly (rather than via ++ * /_GNU_SOURCE, which may already be locked in by earlier headers ++ * in this file), and neither path calls the bare cfgetospeed identifier, so ++ * no versioned reference to it survives in the compiled output. ++ */ ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++static speed_t ++_supabase_compat_cfgetospeed(const struct termios *t) ++{ ++ static int inited = 0; ++ static speed_t (*fn)(const struct termios *) = NULL; ++ if (!inited) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlvsym((void *) 0, "cfgetospeed", "GLIBC_2.17"); ++ if (!fn) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlsym((void *) 0, "cfgetospeed"); ++ } ++ inited = 1; ++ } ++ return fn ? fn(t) : 0; ++} ++#define cfgetospeed(t) _supabase_compat_cfgetospeed(t) ++#endif ++ + #if HAVE_NANOSLEEP + #include + #if HAVE_SYS_TIME_H +--- a/progs/tset.c 2026-07-31 08:24:24 ++++ b/progs/tset.c 2026-07-31 12:03:59 +@@ -89,6 +89,40 @@ + #include + #include + #include ++ ++/* ++ * On Linux/glibc, resolve cfgetospeed to the old (functionally identical) ++ * GLIBC_2.17 symbol version at runtime, so binaries built against newer ++ * glibc still run on hosts with older glibc that only export that version. ++ * Done via dlvsym rather than a link-time .symver directive, since the ++ * latter conflicts with ncurses' own --version-script linking. Both dlvsym ++ * and its dlsym fallback are declared directly (rather than via ++ * /_GNU_SOURCE, which may already be locked in by earlier headers ++ * in this file), and neither path calls the bare cfgetospeed identifier, so ++ * no versioned reference to it survives in the compiled output. ++ */ ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++static speed_t ++_supabase_compat_cfgetospeed(const struct termios *t) ++{ ++ static int inited = 0; ++ static speed_t (*fn)(const struct termios *) = NULL; ++ if (!inited) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlvsym((void *) 0, "cfgetospeed", "GLIBC_2.17"); ++ if (!fn) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlsym((void *) 0, "cfgetospeed"); ++ } ++ inited = 1; ++ } ++ return fn ? fn(t) : 0; ++} ++#define cfgetospeed(t) _supabase_compat_cfgetospeed(t) ++#endif ++ + #include + + #if HAVE_GETTTYNAM diff --git a/nix/packages/postgres-portable.nix b/nix/packages/postgres-portable.nix index 5caf370308..9fd60f101d 100644 --- a/nix/packages/postgres-portable.nix +++ b/nix/packages/postgres-portable.nix @@ -3,11 +3,18 @@ stdenv, writeTextFile, patchelf, + ncurses, psql_17_cli, }: let configDir = ./cli-config; + # glibc 2.42 re-versions cfgetospeed. The bundle runs on the host's glibc, + # so ship an ncurses that resolves the older symbol at runtime. + ncursesCompat = ncurses.overrideAttrs (old: { + patches = (old.patches or [ ]) ++ [ ./patches/ncurses-cfgetospeed-old-glibc-compat.patch ]; + }); + receipt = writeTextFile { name = "cli-receipt"; destination = "/receipt.json"; @@ -218,7 +225,9 @@ stdenv.mkDerivation { break fi done - + ${lib.optionalString stdenv.isLinux '' + cp -f ${ncursesCompat}/lib/libncursesw.so.6 $out/lib/libncursesw.so.6 + ''} # Copy share directory if [ -d ${psql_17_cli.bin}/share ]; then cp -rL ${psql_17_cli.bin}/share/* $out/share/ 2>/dev/null || true diff --git a/nix/tests/expected/hstore_copy_binary.out b/nix/tests/expected/hstore_copy_binary.out index c96abb526d..460c6ade48 100644 --- a/nix/tests/expected/hstore_copy_binary.out +++ b/nix/tests/expected/hstore_copy_binary.out @@ -30,14 +30,14 @@ SELECT lo_from_bytea(81000, 81000 (1 row) -SELECT lo_export(81000, '/tmp/pg_regress_hstore_dup.bin') AS exported; +SELECT lo_export(81000, 'pg_regress_hstore_dup.bin') AS exported; exported ---------- 1 (1 row) -- Must not crash the backend; the duplicate key is de-duplicated on receive. -COPY hstore_dst FROM '/tmp/pg_regress_hstore_dup.bin' WITH (FORMAT binary); +COPY hstore_dst FROM 'pg_regress_hstore_dup.bin' WITH (FORMAT binary); SELECT h AS received, akeys(h) AS keys FROM hstore_dst; received | keys ----------+------ diff --git a/nix/tests/sql/hstore_copy_binary.sql b/nix/tests/sql/hstore_copy_binary.sql index 35da4f02cb..299818ee0a 100644 --- a/nix/tests/sql/hstore_copy_binary.sql +++ b/nix/tests/sql/hstore_copy_binary.sql @@ -28,10 +28,10 @@ SELECT lo_from_bytea(81000, '\x00000001'::bytea||'\x61'::bytea||'\x00000001'::bytea||'\x31'::bytea || -- 'a' => '1' '\x00000001'::bytea||'\x61'::bytea||'\xffffffff'::bytea || -- 'a' => NULL '\xffff'::bytea) AS loid; -- COPY trailer -SELECT lo_export(81000, '/tmp/pg_regress_hstore_dup.bin') AS exported; +SELECT lo_export(81000, 'pg_regress_hstore_dup.bin') AS exported; -- Must not crash the backend; the duplicate key is de-duplicated on receive. -COPY hstore_dst FROM '/tmp/pg_regress_hstore_dup.bin' WITH (FORMAT binary); +COPY hstore_dst FROM 'pg_regress_hstore_dup.bin' WITH (FORMAT binary); SELECT h AS received, akeys(h) AS keys FROM hstore_dst;