Skip to content

Commit e2e0f70

Browse files
authored
feat: add VectorChord extension for PG17
feat: add VectorChord extension for PG17 --- Merge pull request #10 from KBVE/feat/vectorchord
2 parents 618a652 + 58ff165 commit e2e0f70

12 files changed

Lines changed: 324 additions & 1 deletion

File tree

.github/workflows/ci-kilobase-runner.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,20 @@ jobs:
156156
echo "=== Test basic SQL ==="
157157
docker exec pg-test-17 psql -U supabase_admin -h localhost -d postgres -c "CREATE TABLE test_health (id serial PRIMARY KEY, data text); INSERT INTO test_health (data) VALUES ('ok'); SELECT * FROM test_health; DROP TABLE test_health;"
158158
159+
- name: Test KBVE extensions
160+
run: |
161+
echo "=== Test pgvector ==="
162+
docker exec pg-test-17 psql -U supabase_admin -h localhost -d postgres -c "CREATE EXTENSION IF NOT EXISTS vector; SELECT extname, extversion FROM pg_extension WHERE extname = 'vector';"
163+
164+
echo "=== Test kilobase ==="
165+
docker exec pg-test-17 psql -U supabase_admin -h localhost -d postgres -c "CREATE EXTENSION kilobase; SELECT extname, extversion FROM pg_extension WHERE extname = 'kilobase';"
166+
167+
echo "=== Test vchord ==="
168+
docker exec pg-test-17 psql -U supabase_admin -h localhost -d postgres -c "CREATE EXTENSION vchord; SELECT extname, extversion FROM pg_extension WHERE extname = 'vchord';"
169+
170+
echo "=== Verify all loaded ==="
171+
docker exec pg-test-17 psql -U supabase_admin -h localhost -d postgres -c "SELECT extname, extversion FROM pg_extension WHERE extname IN ('vector', 'kilobase', 'vchord') ORDER BY extname;"
172+
159173
- name: Cleanup test container
160174
if: always()
161175
run: docker rm -f pg-test-17 || true
@@ -201,6 +215,7 @@ jobs:
201215
202216
### Fork Customizations
203217
- kilobase (pgrx 0.16.1 extension)
218+
- vchord / VectorChord (pgrx 0.17.0 — scalable vector search)
204219
- pg_failover_slots (logical replication slot failover)
205220
- All standard Supabase PostgreSQL extensions
206221

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ common-nix.vars.pkr.hcl
3333
nixos.qcow2
3434
.lsp
3535
.clj-kondo
36+
tools/pgrx-hash/output/result.json

nix/cargo-pgrx/default.nix

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,10 @@ in
8282
hash = "sha256-3TsNpEqNm3Uol5XPW1i0XEbP2fF2+RKB2d7lO6BDnvQ=";
8383
cargoHash = "sha256-LZUXhjMxkBs3O5feH4X5NQC7Qk4Ja6M5+sAYaSCikrY=";
8484
};
85+
cargo-pgrx_0_17_0 = mkCargoPgrx {
86+
version = "0.17.0";
87+
hash = "sha256-Ld7m7ggxlf8FufpeiAE9qcu49X0SgX6XXHS6KIewGyA=";
88+
cargoHash = "sha256-hNj39YzJna8iZxnlrLz+uLduxaD+uvggQRM7ng3MN1k=";
89+
};
8590
inherit mkCargoPgrx;
8691
}

nix/cargo-pgrx/versions.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,13 @@
115115
"cargoHash": "sha256-95DHq5GLnAqb3bbKwwaeBeKEmkfRh81ZTRaJ7L59DAg="
116116
}
117117
}
118+
},
119+
"0.17.0": {
120+
"hash": "sha256-Ld7m7ggxlf8FufpeiAE9qcu49X0SgX6XXHS6KIewGyA=",
121+
"rust": {
122+
"1.90.0": {
123+
"cargoHash": "sha256-hNj39YzJna8iZxnlrLz+uLduxaD+uvggQRM7ng3MN1k="
124+
}
125+
}
118126
}
119127
}

nix/ext/vectorchord.nix

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
lib,
3+
stdenv,
4+
callPackages,
5+
postgresql,
6+
rust-bin,
7+
}:
8+
let
9+
pname = "vchord";
10+
version = "1.1.0";
11+
rustVersion = "1.90.0";
12+
pgrxVersion = "0.17.0";
13+
14+
cargo = rust-bin.stable.${rustVersion}.default;
15+
mkPgrxExtension = callPackages ../cargo-pgrx/mkPgrxExtension.nix {
16+
inherit rustVersion pgrxVersion;
17+
};
18+
19+
src = builtins.fetchGit {
20+
url = "https://github.com/tensorchord/VectorChord.git";
21+
rev = "c68a6aec9446899d0ab22662968053bd2820ddd4";
22+
shallow = true;
23+
};
24+
in
25+
mkPgrxExtension {
26+
inherit
27+
pname
28+
version
29+
postgresql
30+
src
31+
;
32+
33+
nativeBuildInputs = [ cargo ];
34+
buildInputs = [ postgresql ];
35+
36+
cargoLock = {
37+
lockFile = "${src}/Cargo.lock";
38+
allowBuiltinFetchGit = true;
39+
};
40+
41+
buildFeatures = [ "pg17" ];
42+
43+
CARGO = "${cargo}/bin/cargo";
44+
45+
env = lib.optionalAttrs stdenv.isDarwin {
46+
POSTGRES_LIB = "${postgresql}/lib";
47+
RUSTFLAGS = "-C link-arg=-undefined -C link-arg=dynamic_lookup";
48+
};
49+
50+
doCheck = false;
51+
auditable = false;
52+
53+
meta = with lib; {
54+
description = "Scalable, fast, and disk-friendly vector search for Postgres";
55+
homepage = "https://github.com/tensorchord/VectorChord";
56+
platforms = postgresql.meta.platforms;
57+
license = licenses.agpl3Plus;
58+
};
59+
}

nix/packages/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
cargo-pgrx_0_12_6
111111
cargo-pgrx_0_12_9
112112
cargo-pgrx_0_14_3
113+
cargo-pgrx_0_17_0
113114
;
114115
}
115116
// lib.optionalAttrs pkgs.stdenv.isDarwin {

nix/packages/postgres.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
) ourExtensions;
6262

6363
orioledbExtensions = orioleFilteredExtensions ++ [ ../ext/orioledb.nix ];
64-
dbExtensions17 = orioleFilteredExtensions ++ [ ../ext/kilobase.nix ];
64+
dbExtensions17 = orioleFilteredExtensions ++ [ ../ext/kilobase.nix ../ext/vectorchord.nix ];
6565

6666
# CLI extensions - minimal set for Supabase CLI with migration support
6767
cliExtensions = [

tools/pgrx-hash/Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM --platform=linux/amd64 nixos/nix:latest
2+
3+
# Disable sandbox (required for QEMU-emulated builds on ARM hosts)
4+
# and enable flakes
5+
RUN echo "sandbox = false" >> /etc/nix/nix.conf \
6+
&& echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf \
7+
&& echo "filter-syscalls = false" >> /etc/nix/nix.conf
8+
9+
WORKDIR /work
10+
COPY bootstrap.sh /work/bootstrap.sh
11+
RUN chmod +x /work/bootstrap.sh
12+
13+
ENTRYPOINT ["/work/bootstrap.sh"]

tools/pgrx-hash/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# pgrx Hash Bootstrap Tool
2+
3+
Computes Nix SRI hashes for new `cargo-pgrx` versions. Uses Docker (`linux/amd64`) so ARM machines (Apple Silicon) produce correct x86_64 hashes.
4+
5+
## Usage
6+
7+
```bash
8+
# From repo root:
9+
./tools/pgrx-hash/run.sh <pgrx-version> <rust-version>
10+
11+
# Example: bootstrap pgrx 0.17.0 with Rust 1.90.0
12+
./tools/pgrx-hash/run.sh 0.17.0 1.90.0
13+
```
14+
15+
## What It Does
16+
17+
1. Builds a Docker container targeting `linux/amd64` (uses QEMU on ARM hosts)
18+
2. Fetches `cargo-pgrx` crate from crates.io and computes the source SRI hash
19+
3. Builds `cargo-pgrx` to compute the Cargo dependency hash (`cargoHash`)
20+
4. Writes result to `tools/pgrx-hash/output/result.json` (cached locally)
21+
5. Auto-merges into `nix/cargo-pgrx/versions.json` (requires `jq` on host)
22+
23+
## Output
24+
25+
Results are written to `tools/pgrx-hash/output/result.json`:
26+
27+
```json
28+
{
29+
"pgrxVersion": "0.17.0",
30+
"rustVersion": "1.90.0",
31+
"hash": "sha256-...",
32+
"cargoHash": "sha256-..."
33+
}
34+
```
35+
36+
This file is gitignored and persists locally for reference.
37+
38+
## When to Use
39+
40+
Run this tool whenever a new pgrx version is needed for an extension:
41+
42+
- Adding a new extension that requires a newer pgrx (e.g., VectorChord needs 0.17.0)
43+
- Upgrading an existing extension to a newer pgrx version
44+
- Adding support for a new Rust version with an existing pgrx version
45+
46+
## Requirements
47+
48+
- Docker with buildx support (for `--platform linux/amd64`)
49+
- On ARM hosts: QEMU user-static registered (usually automatic with Docker Desktop)
50+
- `jq` on the host for auto-merging into versions.json (optional — results are also in output/)

tools/pgrx-hash/bootstrap.sh

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
PGRX_VERSION="${1:?Usage: bootstrap.sh <pgrx-version> <rust-version>}"
5+
RUST_VERSION="${2:?Usage: bootstrap.sh <pgrx-version> <rust-version>}"
6+
OUTPUT_DIR="${3:-/output}"
7+
8+
echo "=== Bootstrapping pgrx ${PGRX_VERSION} with Rust ${RUST_VERSION} ==="
9+
echo ""
10+
11+
# Step 1: Compute the crate source hash from crates.io
12+
echo "--- Step 1: Fetching cargo-pgrx ${PGRX_VERSION} from crates.io ---"
13+
CRATE_URL="https://static.crates.io/crates/cargo-pgrx/cargo-pgrx-${PGRX_VERSION}.crate"
14+
STORE_PATH=$(nix-prefetch-url --unpack "${CRATE_URL}" 2>/dev/null)
15+
CRATE_HASH=$(nix hash to-sri --type sha256 "${STORE_PATH}")
16+
echo "Crate hash: ${CRATE_HASH}"
17+
echo ""
18+
19+
# Step 2: Build cargo-pgrx in a minimal flake to extract the cargoHash
20+
echo "--- Step 2: Computing cargoHash (this builds cargo-pgrx dependencies) ---"
21+
echo "(This will intentionally fail once to reveal the correct hash)"
22+
TMPDIR=$(mktemp -d)
23+
24+
cat > "${TMPDIR}/flake.nix" << EOF
25+
{
26+
inputs = {
27+
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
28+
rust-overlay = {
29+
url = "github:oxalica/rust-overlay";
30+
inputs.nixpkgs.follows = "nixpkgs";
31+
};
32+
};
33+
outputs = { nixpkgs, rust-overlay, ... }:
34+
let
35+
pkgs = import nixpkgs {
36+
system = "x86_64-linux";
37+
overlays = [ (import rust-overlay) ];
38+
};
39+
rustToolchain = pkgs.rust-bin.stable."${RUST_VERSION}".default;
40+
rustPlatform = pkgs.makeRustPlatform {
41+
cargo = rustToolchain;
42+
rustc = rustToolchain;
43+
};
44+
in {
45+
packages.x86_64-linux.default = rustPlatform.buildRustPackage rec {
46+
pname = "cargo-pgrx";
47+
version = "${PGRX_VERSION}";
48+
src = pkgs.fetchCrate {
49+
inherit pname version;
50+
hash = "${CRATE_HASH}";
51+
};
52+
cargoHash = "";
53+
nativeBuildInputs = [ pkgs.pkg-config ];
54+
buildInputs = [ pkgs.openssl ];
55+
doCheck = false;
56+
auditable = false;
57+
};
58+
};
59+
}
60+
EOF
61+
62+
# The build will fail because cargoHash is empty, but it will print the correct hash
63+
BUILD_OUTPUT=$(nix build "${TMPDIR}#default" -L 2>&1 || true)
64+
65+
# Extract the hash from the error output - try multiple patterns
66+
CARGO_HASH=$(echo "${BUILD_OUTPUT}" | grep -oP 'got:\s+\K\S+' | head -1 || true)
67+
68+
if [ -z "${CARGO_HASH}" ]; then
69+
CARGO_HASH=$(echo "${BUILD_OUTPUT}" | grep "got:" | head -1 | sed 's/.*got:[[:space:]]*//' | tr -d ' ' || true)
70+
fi
71+
72+
rm -rf "${TMPDIR}"
73+
74+
if [ -z "${CARGO_HASH}" ]; then
75+
echo "ERROR: Could not extract cargoHash from build output."
76+
echo "Build output (last 40 lines):"
77+
echo "${BUILD_OUTPUT}" | tail -40
78+
exit 1
79+
fi
80+
echo "Cargo hash: ${CARGO_HASH}"
81+
echo ""
82+
83+
# Step 3: Write result JSON to output directory
84+
echo "--- Step 3: Writing result to ${OUTPUT_DIR}/result.json ---"
85+
mkdir -p "${OUTPUT_DIR}"
86+
87+
cat > "${OUTPUT_DIR}/result.json" << JSON
88+
{
89+
"pgrxVersion": "${PGRX_VERSION}",
90+
"rustVersion": "${RUST_VERSION}",
91+
"hash": "${CRATE_HASH}",
92+
"cargoHash": "${CARGO_HASH}"
93+
}
94+
JSON
95+
96+
echo ""
97+
echo "=== Results ==="
98+
echo "pgrx version: ${PGRX_VERSION}"
99+
echo "rust version: ${RUST_VERSION}"
100+
echo "crate hash: ${CRATE_HASH}"
101+
echo "cargo hash: ${CARGO_HASH}"
102+
echo ""
103+
echo "Result written to ${OUTPUT_DIR}/result.json"

0 commit comments

Comments
 (0)