Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -26,7 +26,7 @@
# Pin to a specific nixpkgs version that has compatible v8 and curl versions
# for extensions that require older package versions
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";
Expand Down
6 changes: 6 additions & 0 deletions nix/docs/updating-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,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`.
42 changes: 22 additions & 20 deletions nix/ext/pg_net.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
libuv,
makeWrapper,
switch-ext-version,
curl_8_6,
curl,
latestOnly ? false,
}:

let
curl = curl_8_6;
in
let
pname = "pg_net";
build =
Expand Down Expand Up @@ -50,23 +47,28 @@ let
rm sql/pg_net--0.5.1--0.6.sql
'';

# curl >= 8.17 makes <curl/multi.h> pull in the curl_multi_setopt
# typecheck macro, which breaks the declaration in multi.h before 0.20.4.
env.NIX_CFLAGS_COMPILE =
if (lib.versionOlder version "0.19.1") then
"-Wno-error"
else if
(
builtins.elem version [
"0.19.5"
"0.20.0"
]
&& stdenv.isDarwin
)
then
# Fix for dangling pointer warning on darwin with newer clang
# 0.19.5: src/core.c:177, 0.20.0: src/core.c:317
"-Wno-error=dangling-assignment"
else
"";
lib.optionalString (lib.versionOlder version "0.20.4") "-DCURL_DISABLE_TYPECHECK "
+ (
if (lib.versionOlder version "0.19.1") then
"-Wno-error"
else if
(
builtins.elem version [
"0.19.5"
"0.20.0"
]
&& stdenv.isDarwin
)
then
# Fix for dangling pointer warning on darwin with newer clang
# 0.19.5: src/core.c:177, 0.20.0: src/core.c:317
"-Wno-error=dangling-assignment"
else
""
);

installPhase = ''
mkdir -p $out/{lib,share/postgresql/extension}
Expand Down
10 changes: 5 additions & 5 deletions nix/ext/pgroonga/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
msgpack-c,
mecab,
makeWrapper,
xxHash,
xxhash,
buildEnv,
supabase-groonga,
mecab-naist-jdic,
Expand Down Expand Up @@ -64,7 +64,7 @@ let
supabase-groonga
mecab
]
++ lib.optionals stdenv.isDarwin [ xxHash ];
++ lib.optionals stdenv.isDarwin [ xxhash ];

propagatedBuildInputs = [
supabase-groonga
Expand All @@ -89,7 +89,7 @@ let
"-Wno-error=format"
"-Wno-format"
"-I${supabase-groonga}/include/groonga"
"-I${xxHash}/include"
"-I${xxhash}/include"
"-DPGRN_VERSION=\"${version}\""
]
);
Expand All @@ -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"
''}
'';
Expand Down
6 changes: 3 additions & 3 deletions nix/ext/pgroonga/groonga.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
mecab,
pkg-config,
rapidjson,
xxHash,
xxhash,
zstd,
makeWrapper,
suggestSupport ? false,
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions nix/ext/tests/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

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]]


class PostgresExtensionTest(object):
def __init__(
self,
vm: Machine,
vm: QemuMachine,
extension_name: str,
versions: Versions,
sql_test_dir: Path,
Expand Down
1 change: 0 additions & 1 deletion nix/nixpkgs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
};
in
_final: _prev: {
curl_8_6 = oldstable.curl;
v8_oldstable = oldstable.v8;
}
)
Expand Down
127 changes: 127 additions & 0 deletions nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch
Original file line number Diff line number Diff line change
@@ -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
+ * <dlfcn.h>/_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 <tic.h>
#include <termcap.h> /* 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
+ * <dlfcn.h>/_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 <time.h>
#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 <reset_cmd.h>
#include <termcap.h>
#include <transform.h>
+
+/*
+ * 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
+ * <dlfcn.h>/_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 <tty_settings.h>

#if HAVE_GETTTYNAM
11 changes: 10 additions & 1 deletion nix/packages/postgres-portable.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions nix/tests/expected/hstore_copy_binary.out
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------+------
Expand Down
Loading
Loading