Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package pgvector for openSUSE:Factory checked in at 2026-03-23 17:16:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/pgvector (Old) and /work/SRC/openSUSE:Factory/.pgvector.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pgvector" Mon Mar 23 17:16:16 2026 rev:5 rq:1342055 version:0.8.2 Changes: -------- --- /work/SRC/openSUSE:Factory/pgvector/pgvector.changes 2025-10-01 18:57:39.920184652 +0200 +++ /work/SRC/openSUSE:Factory/.pgvector.new.8177/pgvector.changes 2026-03-23 17:18:02.333326922 +0100 @@ -1,0 +2,8 @@ +Mon Mar 23 14:12:42 UTC 2026 - Reinhard Max <[email protected]> + +- Update to 0.8.2: + * bsc#1258945, CVE-2026-3172: Fixed buffer overflow with parallel + HNSW index build. + * Fixed Index Searches in EXPLAIN output for Postgres 18 + +------------------------------------------------------------------- Old: ---- pgvector-0.8.1.tar.gz New: ---- pgvector-0.8.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ pgvector.spec ++++++ --- /var/tmp/diff_new_pack.xmo1a0/_old 2026-03-23 17:18:02.869349151 +0100 +++ /var/tmp/diff_new_pack.xmo1a0/_new 2026-03-23 17:18:02.869349151 +0100 @@ -1,7 +1,7 @@ # # spec file for package pgvector # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -33,7 +33,7 @@ BuildRequires: %{pg_name}-server-devel %pg_server_requires %endif -Version: 0.8.1 +Version: 0.8.2 Release: 0 Summary: Open-source vector similarity search for Postgres License: PostgreSQL ++++++ pgvector-0.8.1.tar.gz -> pgvector-0.8.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/.github/workflows/build.yml new/pgvector-0.8.2/.github/workflows/build.yml --- old/pgvector-0.8.1/.github/workflows/build.yml 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/.github/workflows/build.yml 2026-02-25 19:46:57.000000000 +0100 @@ -23,14 +23,14 @@ - postgres: 13 os: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: ankane/setup-postgres@v1 with: postgres-version: ${{ matrix.postgres }} dev-files: true - run: make env: - PG_CFLAGS: ${{ matrix.postgres >= 18 && '-Wno-missing-field-initializers' || '' }} -DUSE_ASSERT_CHECKING -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare + PG_CFLAGS: -DUSE_ASSERT_CHECKING -Wall -Wextra -Werror -Wno-unused-parameter -Wno-sign-compare ${{ matrix.postgres >= 18 && '-Wno-missing-field-initializers' || '' }} - run: | export PG_CONFIG=`which pg_config` sudo --preserve-env=PG_CONFIG make install @@ -48,18 +48,18 @@ fail-fast: false matrix: include: - - postgres: 17 - os: macos-15 + - postgres: 18 + os: macos-26 - postgres: 14 - os: macos-13 + os: macos-15-intel steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: ankane/setup-postgres@v1 with: postgres-version: ${{ matrix.postgres }} - run: make env: - PG_CFLAGS: -DUSE_ASSERT_CHECKING -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unknown-warning-option + PG_CFLAGS: -DUSE_ASSERT_CHECKING -Wall -Wextra -Werror -Wno-unused-parameter -Wno-unknown-warning-option ${{ matrix.postgres >= 18 && '-Wno-missing-field-initializers' || '' }} - run: make install - run: make installcheck - if: ${{ failure() }} @@ -72,27 +72,35 @@ tar xf $TAG.tar.gz mv postgres-$TAG postgres env: - TAG: ${{ matrix.postgres == 17 && 'REL_17_2' || 'REL_14_15' }} + TAG: ${{ matrix.postgres == 18 && 'REL_18_2' || 'REL_14_21' }} - run: make prove_installcheck PROVE_FLAGS="-I ./postgres/src/test/perl -I ./test/perl" env: PERL5LIB: /Users/runner/perl5/lib/perl5 - run: make clean && $(brew --prefix llvm@$LLVM_VERSION)/bin/scan-build --status-bugs make env: - LLVM_VERSION: ${{ matrix.os == 'macos-15' && 18 || 15 }} + LLVM_VERSION: ${{ matrix.os == 'macos-26' && 20 || 18 }} PG_CFLAGS: -DUSE_ASSERT_CHECKING windows: - runs-on: windows-latest + runs-on: ${{ matrix.os }} if: ${{ !startsWith(github.ref_name, 'mac') }} + strategy: + fail-fast: false + matrix: + include: + - postgres: 17 + os: windows-2025 + - postgres: 14 + os: windows-2022 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: ankane/setup-postgres@v1 with: - postgres-version: 14 + postgres-version: ${{ matrix.postgres }} - run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" && ^ nmake /NOLOGO /F Makefile.win && ^ nmake /NOLOGO /F Makefile.win install && ^ - nmake /NOLOGO /F Makefile.win installcheck && ^ + nmake /NOLOGO /F Makefile.win installcheck ${{ matrix.postgres != 17 && 'PG_REGRESS=$(PGROOT)\bin\pg_regress' || '' }} && ^ nmake /NOLOGO /F Makefile.win clean && ^ nmake /NOLOGO /F Makefile.win uninstall shell: cmd @@ -125,10 +133,10 @@ if: ${{ !startsWith(github.ref_name, 'mac') && !startsWith(github.ref_name, 'windows') }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: ankane/setup-postgres-valgrind@v1 with: - postgres-version: 17 + postgres-version: 18 check-ub: yes - run: make OPTFLAGS="" - run: sudo --preserve-env=PG_CONFIG make install diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/CHANGELOG.md new/pgvector-0.8.2/CHANGELOG.md --- old/pgvector-0.8.1/CHANGELOG.md 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/CHANGELOG.md 2026-02-25 19:46:57.000000000 +0100 @@ -1,3 +1,9 @@ +## 0.8.2 (2026-02-25) + +- Fixed buffer overflow with parallel HNSW index build +- Improved `install` target on Windows +- Fixed `Index Searches` in `EXPLAIN` output for Postgres 18 + ## 0.8.1 (2025-09-04) - Added support for Postgres 18 rc1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/Dockerfile new/pgvector-0.8.2/Dockerfile --- old/pgvector-0.8.1/Dockerfile 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/Dockerfile 2026-02-25 19:46:57.000000000 +0100 @@ -5,7 +5,7 @@ FROM postgres:$PG_MAJOR-$DEBIAN_CODENAME ARG PG_MAJOR -ADD https://github.com/pgvector/pgvector.git#v0.8.1 /tmp/pgvector +ADD https://github.com/pgvector/pgvector.git#v0.8.2 /tmp/pgvector RUN apt-get update && \ apt-mark hold locales && \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/LICENSE new/pgvector-0.8.2/LICENSE --- old/pgvector-0.8.1/LICENSE 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/LICENSE 2026-02-25 19:46:57.000000000 +0100 @@ -1,4 +1,4 @@ -Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group +Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of California diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/META.json new/pgvector-0.8.2/META.json --- old/pgvector-0.8.1/META.json 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/META.json 2026-02-25 19:46:57.000000000 +0100 @@ -2,7 +2,7 @@ "name": "vector", "abstract": "Open-source vector similarity search for Postgres", "description": "Supports L2 distance, inner product, and cosine distance", - "version": "0.8.1", + "version": "0.8.2", "maintainer": [ "Andrew Kane <[email protected]>" ], @@ -20,7 +20,7 @@ "vector": { "file": "sql/vector.sql", "docfile": "README.md", - "version": "0.8.1", + "version": "0.8.2", "abstract": "Open-source vector similarity search for Postgres" } }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/Makefile new/pgvector-0.8.2/Makefile --- old/pgvector-0.8.1/Makefile 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/Makefile 2026-02-25 19:46:57.000000000 +0100 @@ -1,5 +1,5 @@ EXTENSION = vector -EXTVERSION = 0.8.1 +EXTVERSION = 0.8.2 MODULE_big = vector DATA = $(wildcard sql/*--*--*.sql) @@ -27,6 +27,11 @@ OPTFLAGS = endif +# RISC-V64 doesn't support -march=native +ifeq ($(shell uname -m), riscv64) + OPTFLAGS = +endif + # For auto-vectorization: # - GCC (needs -ftree-vectorize OR -O3) - https://gcc.gnu.org/projects/tree-ssa/vectorization.html # - Clang (could use pragma instead) - https://llvm.org/docs/Vectorizers.html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/Makefile.win new/pgvector-0.8.2/Makefile.win --- old/pgvector-0.8.1/Makefile.win 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/Makefile.win 2026-02-25 19:46:57.000000000 +0100 @@ -1,5 +1,5 @@ EXTENSION = vector -EXTVERSION = 0.8.1 +EXTVERSION = 0.8.2 DATA_built = sql\$(EXTENSION)--$(EXTVERSION).sql OBJS = src\bitutils.obj src\bitvec.obj src\halfutils.obj src\halfvec.obj src\hnsw.obj src\hnswbuild.obj src\hnswinsert.obj src\hnswscan.obj src\hnswutils.obj src\hnswvacuum.obj src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\sparsevec.obj src\vector.obj @@ -31,6 +31,9 @@ PKGLIBDIR = $(PGROOT)\lib SHAREDIR = $(PGROOT)\share +# Use $(PGROOT)\bin\pg_regress for Postgres < 17 +PG_REGRESS = $(LIBDIR)\pgxs\src\test\regress\pg_regress + CFLAGS = /nologo /I"$(INCLUDEDIR_SERVER)\port\win32_msvc" /I"$(INCLUDEDIR_SERVER)\port\win32" /I"$(INCLUDEDIR_SERVER)" /I"$(INCLUDEDIR)" CFLAGS = $(CFLAGS) $(PG_CFLAGS) @@ -54,11 +57,11 @@ copy $(SHLIB) "$(PKGLIBDIR)" copy $(EXTENSION).control "$(SHAREDIR)\extension" copy sql\$(EXTENSION)--*.sql "$(SHAREDIR)\extension" - mkdir "$(INCLUDEDIR_SERVER)\extension\$(EXTENSION)" + if not exist "$(INCLUDEDIR_SERVER)\extension\$(EXTENSION)" mkdir "$(INCLUDEDIR_SERVER)\extension\$(EXTENSION)" for %f in ($(HEADERS)) do copy %f "$(INCLUDEDIR_SERVER)\extension\$(EXTENSION)" installcheck: - "$(BINDIR)\pg_regress" --bindir="$(BINDIR)" $(REGRESS_OPTS) $(REGRESS) + "$(PG_REGRESS)" --bindir="$(BINDIR)" $(REGRESS_OPTS) $(REGRESS) uninstall: del /f "$(PKGLIBDIR)\$(SHLIB)" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/README.md new/pgvector-0.8.2/README.md --- old/pgvector-0.8.1/README.md 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/README.md 2026-02-25 19:46:57.000000000 +0100 @@ -21,7 +21,7 @@ ```sh cd /tmp -git clone --branch v0.8.1 https://github.com/pgvector/pgvector.git +git clone --branch v0.8.2 https://github.com/pgvector/pgvector.git cd pgvector make make install # may need sudo @@ -29,16 +29,16 @@ See the [installation notes](#installation-notes---linux-and-mac) if you run into issues -You can also install it with [Docker](#docker), [Homebrew](#homebrew), [PGXN](#pgxn), [APT](#apt), [Yum](#yum), [pkg](#pkg), or [conda-forge](#conda-forge), and it comes preinstalled with [Postgres.app](#postgresapp) and many [hosted providers](#hosted-postgres). There are also instructions for [GitHub Actions](https://github.com/pgvector/setup-pgvector). +You can also install it with [Docker](#docker), [Homebrew](#homebrew), [PGXN](#pgxn), [APT](#apt), [Yum](#yum), [pkg](#pkg), [APK](#apk), or [conda-forge](#conda-forge), and it comes preinstalled with [Postgres.app](#postgresapp) and many [hosted providers](#hosted-postgres). There are also instructions for [GitHub Actions](https://github.com/pgvector/setup-pgvector). ### Windows Ensure [C++ support in Visual Studio](https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-170#download-and-install-the-tools) is installed and run `x64 Native Tools Command Prompt for VS [version]` as administrator. Then use `nmake` to build: ```cmd -set "PGROOT=C:\Program Files\PostgreSQL\17" +set "PGROOT=C:\Program Files\PostgreSQL\18" cd %TEMP% -git clone --branch v0.8.1 https://github.com/pgvector/pgvector.git +git clone --branch v0.8.2 https://github.com/pgvector/pgvector.git cd pgvector nmake /F Makefile.win nmake /F Makefile.win install @@ -695,10 +695,10 @@ ### Querying -Use `EXPLAIN ANALYZE` to debug performance. +Use `EXPLAIN (ANALYZE, BUFFERS)` to debug performance. ```sql -EXPLAIN ANALYZE SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5; +EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5; ``` #### Exact Search @@ -771,9 +771,12 @@ Language | Libraries / Examples --- | --- +Ada | [pgvector-ada](https://github.com/pgvector/pgvector-ada) +Algol | [pgvector-algol](https://github.com/pgvector/pgvector-algol) C | [pgvector-c](https://github.com/pgvector/pgvector-c) C++ | [pgvector-cpp](https://github.com/pgvector/pgvector-cpp) C#, F#, Visual Basic | [pgvector-dotnet](https://github.com/pgvector/pgvector-dotnet) +COBOL | [pgvector-cobol](https://github.com/pgvector/pgvector-cobol) Crystal | [pgvector-crystal](https://github.com/pgvector/pgvector-crystal) D | [pgvector-d](https://github.com/pgvector/pgvector-d) Dart | [pgvector-dart](https://github.com/pgvector/pgvector-dart) @@ -790,14 +793,18 @@ Lua | [pgvector-lua](https://github.com/pgvector/pgvector-lua) Nim | [pgvector-nim](https://github.com/pgvector/pgvector-nim) OCaml | [pgvector-ocaml](https://github.com/pgvector/pgvector-ocaml) +Pascal | [pgvector-pascal](https://github.com/pgvector/pgvector-pascal) Perl | [pgvector-perl](https://github.com/pgvector/pgvector-perl) PHP | [pgvector-php](https://github.com/pgvector/pgvector-php) +Prolog | [pgvector-prolog](https://github.com/pgvector/pgvector-prolog) Python | [pgvector-python](https://github.com/pgvector/pgvector-python) R | [pgvector-r](https://github.com/pgvector/pgvector-r) +Racket | [pgvector-racket](https://github.com/pgvector/pgvector-racket) Raku | [pgvector-raku](https://github.com/pgvector/pgvector-raku) Ruby | [pgvector-ruby](https://github.com/pgvector/pgvector-ruby), [Neighbor](https://github.com/ankane/neighbor) Rust | [pgvector-rust](https://github.com/pgvector/pgvector-rust) Swift | [pgvector-swift](https://github.com/pgvector/pgvector-swift) +Tcl | [pgvector-tcl](https://github.com/pgvector/pgvector-tcl) Zig | [pgvector-zig](https://github.com/pgvector/pgvector-zig) ## Frequently Asked Questions @@ -812,7 +819,7 @@ #### What if I want to index vectors with more than 2,000 dimensions? -You can use [half-precision indexing](#half-precision-indexing) to index up to 4,000 dimensions or [binary quantization](#binary-quantization) to index up to 64,000 dimensions. Another option is [dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction). +You can use [half-precision vectors](#half-precision-vectors) or [half-precision indexing](#half-precision-indexing) to index up to 4,000 dimensions or [binary quantization](#binary-quantization) to index up to 64,000 dimensions. Other options are [indexing subvectors](#indexing-subvectors) (for models that support it) or [dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction). #### Can I store vectors with different dimensions in the same column? @@ -1064,7 +1071,7 @@ If your machine has multiple Postgres installations, specify the path to [pg_config](https://www.postgresql.org/docs/current/app-pgconfig.html) with: ```sh -export PG_CONFIG=/Library/PostgreSQL/17/bin/pg_config +export PG_CONFIG=/Library/PostgreSQL/18/bin/pg_config ``` Then re-run the installation instructions (run `make clean` before `make` if needed). If `sudo` is needed for `make install`, use: @@ -1075,11 +1082,11 @@ A few common paths on Mac are: -- EDB installer - `/Library/PostgreSQL/17/bin/pg_config` -- Homebrew (arm64) - `/opt/homebrew/opt/postgresql@17/bin/pg_config` -- Homebrew (x86-64) - `/usr/local/opt/postgresql@17/bin/pg_config` +- EDB installer - `/Library/PostgreSQL/18/bin/pg_config` +- Homebrew (arm64) - `/opt/homebrew/opt/postgresql@18/bin/pg_config` +- Homebrew (x86-64) - `/usr/local/opt/postgresql@18/bin/pg_config` -Note: Replace `17` with your Postgres server version +Note: Replace `18` with your Postgres server version ### Missing Header @@ -1088,10 +1095,10 @@ For Ubuntu and Debian, use: ```sh -sudo apt install postgresql-server-dev-17 +sudo apt install postgresql-server-dev-18 ``` -Note: Replace `17` with your Postgres server version +Note: Replace `18` with your Postgres server version ### Missing SDK @@ -1138,30 +1145,32 @@ Get the [Docker image](https://hub.docker.com/r/pgvector/pgvector) with: ```sh -docker pull pgvector/pgvector:pg17-trixie +docker pull pgvector/pgvector:pg18-trixie ``` -This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres) (replace `17` with your Postgres server version, and run it the same way). +This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres) (replace `18` with your Postgres server version, and run it the same way). Supported tags are: -- `pg17-trixie`, `0.8.1-pg17-trixie` -- `pg17-bookworm`, `0.8.1-pg17-bookworm`, `pg17`, `0.8.1-pg17` -- `pg16-trixie`, `0.8.1-pg16-trixie` -- `pg16-bookworm`, `0.8.1-pg16-bookworm`, `pg16`, `0.8.1-pg16` -- `pg15-trixie`, `0.8.1-pg15-trixie` -- `pg15-bookworm`, `0.8.1-pg15-bookworm`, `pg15`, `0.8.1-pg15` -- `pg14-trixie`, `0.8.1-pg14-trixie` -- `pg14-bookworm`, `0.8.1-pg14-bookworm`, `pg14`, `0.8.1-pg14` -- `pg13-trixie`, `0.8.1-pg13-trixie` -- `pg13-bookworm`, `0.8.1-pg13-bookworm`, `pg13`, `0.8.1-pg13` +- `pg18-trixie`, `0.8.2-pg18-trixie` +- `pg18-bookworm`, `0.8.2-pg18-bookworm`, `pg18`, `0.8.2-pg18` +- `pg17-trixie`, `0.8.2-pg17-trixie` +- `pg17-bookworm`, `0.8.2-pg17-bookworm`, `pg17`, `0.8.2-pg17` +- `pg16-trixie`, `0.8.2-pg16-trixie` +- `pg16-bookworm`, `0.8.2-pg16-bookworm`, `pg16`, `0.8.2-pg16` +- `pg15-trixie`, `0.8.2-pg15-trixie` +- `pg15-bookworm`, `0.8.2-pg15-bookworm`, `pg15`, `0.8.2-pg15` +- `pg14-trixie`, `0.8.2-pg14-trixie` +- `pg14-bookworm`, `0.8.2-pg14-bookworm`, `pg14`, `0.8.2-pg14` +- `pg13-trixie`, `0.8.2-pg13-trixie` +- `pg13-bookworm`, `0.8.2-pg13-bookworm`, `pg13`, `0.8.2-pg13` You can also build the image manually: ```sh -git clone --branch v0.8.1 https://github.com/pgvector/pgvector.git +git clone --branch v0.8.2 https://github.com/pgvector/pgvector.git cd pgvector -docker build --pull --build-arg PG_MAJOR=17 -t myuser/pgvector . +docker build --pull --build-arg PG_MAJOR=18 -t myuser/pgvector . ``` If you increase `maintenance_work_mem`, make sure `--shm-size` is at least that size to avoid an error with parallel HNSW index builds. @@ -1178,7 +1187,7 @@ brew install pgvector ``` -Note: This only adds it to the `postgresql@17` and `postgresql@14` formulas +Note: This only adds it to the `postgresql@18` and `postgresql@17` formulas ### PGXN @@ -1193,22 +1202,22 @@ Debian and Ubuntu packages are available from the [PostgreSQL APT Repository](https://wiki.postgresql.org/wiki/Apt). Follow the [setup instructions](https://wiki.postgresql.org/wiki/Apt#Quickstart) and run: ```sh -sudo apt install postgresql-17-pgvector +sudo apt install postgresql-18-pgvector ``` -Note: Replace `17` with your Postgres server version +Note: Replace `18` with your Postgres server version ### Yum RPM packages are available from the [PostgreSQL Yum Repository](https://yum.postgresql.org/). Follow the [setup instructions](https://www.postgresql.org/download/linux/redhat/) for your distribution and run: ```sh -sudo yum install pgvector_17 +sudo yum install pgvector_18 # or -sudo dnf install pgvector_17 +sudo dnf install pgvector_18 ``` -Note: Replace `17` with your Postgres server version +Note: Replace `18` with your Postgres server version ### pkg @@ -1225,6 +1234,14 @@ make install ``` +### APK + +Install the Alpine package with: + +```sh +apk add postgresql-pgvector +``` + ### conda-forge With Conda Postgres, install from [conda-forge](https://anaconda.org/conda-forge/pgvector) with: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/sql/vector--0.8.1--0.8.2.sql new/pgvector-0.8.2/sql/vector--0.8.1--0.8.2.sql --- old/pgvector-0.8.1/sql/vector--0.8.1--0.8.2.sql 1970-01-01 01:00:00.000000000 +0100 +++ new/pgvector-0.8.2/sql/vector--0.8.1--0.8.2.sql 2026-02-25 19:46:57.000000000 +0100 @@ -0,0 +1,2 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION vector UPDATE TO '0.8.2'" to load this file. \quit diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/bitvec.c new/pgvector-0.8.2/src/bitvec.c --- old/pgvector-0.8.1/src/bitvec.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/bitvec.c 2026-02-25 19:46:57.000000000 +0100 @@ -2,6 +2,7 @@ #include "bitutils.h" #include "bitvec.h" +#include "fmgr.h" #include "utils/varbit.h" #include "vector.h" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/halfutils.c new/pgvector-0.8.2/src/halfutils.c --- old/pgvector-0.8.1/src/halfutils.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/halfutils.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,5 +1,7 @@ #include "postgres.h" +#include <math.h> + #include "halfutils.h" #include "halfvec.h" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/halfvec.c new/pgvector-0.8.2/src/halfvec.c --- old/pgvector-0.8.1/src/halfvec.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/halfvec.c 2026-02-25 19:46:57.000000000 +0100 @@ -13,12 +13,20 @@ #include "port.h" /* for strtof() */ #include "sparsevec.h" #include "utils/array.h" -#include "utils/builtins.h" #include "utils/float.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" -#include "utils/numeric.h" +#include "utils/varbit.h" #include "vector.h" +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif + +#if PG_VERSION_NUM >= 170000 +#include "parser/scansup.h" +#endif + #define STATE_DIMS(x) (ARR_DIMS(x)[0] - 1) #define CreateStateDatums(dim) palloc(sizeof(Datum) * (dim + 1)) @@ -129,9 +137,9 @@ return result; } -/* - * Check for whitespace, since array_isspace() is static - */ +#if PG_VERSION_NUM >= 170000 +#define halfvec_isspace(ch) scanner_isspace(ch) +#else static inline bool halfvec_isspace(char ch) { @@ -144,6 +152,7 @@ return true; return false; } +#endif /* * Check state array diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnsw.c new/pgvector-0.8.2/src/hnsw.c --- old/pgvector-0.8.1/src/hnsw.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnsw.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,18 +1,24 @@ #include "postgres.h" #include <float.h> +#include <limits.h> #include <math.h> #include "access/amapi.h" +#include "access/genam.h" #include "access/reloptions.h" #include "commands/progress.h" #include "commands/vacuum.h" +#include "fmgr.h" #include "hnsw.h" #include "miscadmin.h" +#include "nodes/pg_list.h" #include "utils/float.h" #include "utils/guc.h" +#include "utils/relcache.h" #include "utils/selfuncs.h" #include "utils/spccache.h" +#include "vector.h" #if PG_VERSION_NUM < 150000 #define MarkGUCPrefixReserved(x) EmitWarningsOnPlaceholders(x) @@ -260,6 +266,64 @@ Datum hnswhandler(PG_FUNCTION_ARGS) { +#if PG_VERSION_NUM >= 190000 + static const IndexAmRoutine amroutine = { + .type = T_IndexAmRoutine, + .amstrategies = 0, + .amsupport = 3, + .amoptsprocnum = 0, + .amcanorder = false, + .amcanorderbyop = true, + .amcanhash = false, + .amconsistentequality = false, + .amconsistentordering = false, + .amcanbackward = false, + .amcanunique = false, + .amcanmulticol = false, + .amoptionalkey = true, + .amsearcharray = false, + .amsearchnulls = false, + .amstorage = false, + .amclusterable = false, + .ampredlocks = false, + .amcanparallel = false, + .amcanbuildparallel = true, + .amcaninclude = false, + .amusemaintenanceworkmem = false, + .amsummarizing = false, + .amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL, + .amkeytype = InvalidOid, + + .ambuild = hnswbuild, + .ambuildempty = hnswbuildempty, + .aminsert = hnswinsert, + .aminsertcleanup = NULL, + .ambulkdelete = hnswbulkdelete, + .amvacuumcleanup = hnswvacuumcleanup, + .amcanreturn = NULL, + .amcostestimate = hnswcostestimate, + .amgettreeheight = NULL, + .amoptions = hnswoptions, + .amproperty = NULL, + .ambuildphasename = hnswbuildphasename, + .amvalidate = hnswvalidate, + .amadjustmembers = NULL, + .ambeginscan = hnswbeginscan, + .amrescan = hnswrescan, + .amgettuple = hnswgettuple, + .amgetbitmap = NULL, + .amendscan = hnswendscan, + .ammarkpos = NULL, + .amrestrpos = NULL, + .amestimateparallelscan = NULL, + .aminitparallelscan = NULL, + .amparallelrescan = NULL, + .amtranslatestrategy = NULL, + .amtranslatecmptype = NULL, + }; + + PG_RETURN_POINTER(&amroutine); +#else IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); amroutine->amstrategies = 0; @@ -333,4 +397,5 @@ #endif PG_RETURN_POINTER(amroutine); +#endif } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnsw.h new/pgvector-0.8.2/src/hnsw.h --- old/pgvector-0.8.1/src/hnsw.h 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnsw.h 2026-02-25 19:46:57.000000000 +0100 @@ -3,6 +3,8 @@ #include "postgres.h" +#include <math.h> + #include "access/genam.h" #include "access/parallel.h" #include "lib/pairingheap.h" @@ -12,6 +14,10 @@ #include "utils/sampling.h" #include "vector.h" +#if PG_VERSION_NUM >= 190000 +typedef Pointer Item; +#endif + #define HNSW_MAX_DIM 2000 #define HNSW_MAX_NNZ 1000 @@ -424,7 +430,7 @@ HnswElement HnswInitElement(char *base, ItemPointer tid, int m, double ml, int maxLevel, HnswAllocator * alloc); HnswElement HnswInitElementFromBlock(BlockNumber blkno, OffsetNumber offno); void HnswFindElementNeighbors(char *base, HnswElement element, HnswElement entryPoint, Relation index, HnswSupport * support, int m, int efConstruction, bool existing); -HnswSearchCandidate *HnswEntryCandidate(char *base, HnswElement em, HnswQuery * q, Relation rel, HnswSupport * support, bool loadVec); +HnswSearchCandidate *HnswEntryCandidate(char *base, HnswElement entryPoint, HnswQuery * q, Relation index, HnswSupport * support, bool loadVec); void HnswUpdateMetaPage(Relation index, int updateEntry, HnswElement entryPoint, BlockNumber insertPage, ForkNumber forkNum, bool building); void HnswSetNeighborTuple(char *base, HnswNeighborTuple ntup, HnswElement e, int m); void HnswAddHeapTid(HnswElement element, ItemPointer heaptid); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnswbuild.c new/pgvector-0.8.2/src/hnswbuild.c --- old/pgvector-0.8.1/src/hnswbuild.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnswbuild.c 2026-02-25 19:46:57.000000000 +0100 @@ -36,11 +36,12 @@ */ #include "postgres.h" -#include <math.h> - +#include "access/genam.h" #include "access/parallel.h" +#include "access/relscan.h" #include "access/table.h" #include "access/tableam.h" +#include "access/tupdesc.h" #include "access/xact.h" #include "access/xloginsert.h" #include "catalog/index.h" @@ -48,11 +49,18 @@ #include "commands/progress.h" #include "hnsw.h" #include "miscadmin.h" +#include "nodes/execnodes.h" #include "optimizer/optimizer.h" #include "storage/bufmgr.h" #include "tcop/tcopprot.h" #include "utils/datum.h" #include "utils/memutils.h" +#include "utils/rel.h" +#include "utils/snapmgr.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif #if PG_VERSION_NUM >= 140000 #include "utils/backend_progress.h" @@ -69,6 +77,8 @@ #define PARALLEL_KEY_HNSW_AREA UINT64CONST(0xA000000000000002) #define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xA000000000000003) +#define HNSW_MAX_GRAPH_MEMORY (SIZE_MAX / 2) + /* * Create the metapage */ @@ -398,7 +408,7 @@ * Update graph in memory */ static void -UpdateGraphInMemory(HnswSupport * support, HnswElement element, int m, int efConstruction, HnswElement entryPoint, HnswBuildState * buildstate) +UpdateGraphInMemory(HnswSupport * support, HnswElement element, int m, HnswElement entryPoint, HnswBuildState * buildstate) { HnswGraph *graph = buildstate->graph; char *base = buildstate->hnswarea; @@ -460,7 +470,7 @@ HnswFindElementNeighbors(base, element, entryPoint, NULL, support, m, efConstruction, false); /* Update graph in memory */ - UpdateGraphInMemory(support, element, m, efConstruction, entryPoint, buildstate); + UpdateGraphInMemory(support, element, m, entryPoint, buildstate); /* Release entry lock */ LWLockRelease(entryLock); @@ -481,6 +491,7 @@ LWLock *flushLock = &graph->flushLock; char *base = buildstate->hnswarea; Datum value; + Size memoryMargin; /* Form index value */ if (!HnswFormIndexValue(&value, values, isnull, buildstate->typeInfo, support)) @@ -489,6 +500,9 @@ /* Get datum size */ valueSize = VARSIZE_ANY(DatumGetPointer(value)); + /* In a parallel build, add a margin so allocations never fail */ + memoryMargin = base == NULL ? 0 : 1024 * 1024; + /* Ensure graph not flushed when inserting */ LWLockAcquire(flushLock, LW_SHARED); @@ -510,7 +524,7 @@ * Check that we have enough memory available for the new element now that * we have the allocator lock, and flush pages if needed. */ - if (graph->memoryUsed >= graph->memoryTotal) + if (graph->memoryUsed + memoryMargin >= graph->memoryTotal) { LWLockRelease(&graph->allocatorLock); @@ -545,7 +559,7 @@ /* Copy the datum */ memcpy(valuePtr, DatumGetPointer(value), valueSize); - HnswPtrStore(base, element->value, valuePtr); + HnswPtrStore(base, element->value, (char *) valuePtr); /* Create a lock for the element */ LWLockInitialize(&element->lock, hnsw_lock_tranche_id); @@ -603,7 +617,7 @@ HnswPtrStore(base, graph->head, (HnswElement) NULL); HnswPtrStore(base, graph->entryPoint, (HnswElement) NULL); graph->memoryUsed = 0; - graph->memoryTotal = memoryTotal; + graph->memoryTotal = Min(memoryTotal, HNSW_MAX_GRAPH_MEMORY); graph->flushed = false; graph->indtuples = 0; SpinLockInit(&graph->lock); @@ -644,9 +658,17 @@ HnswSharedMemoryAlloc(Size size, void *state) { HnswBuildState *buildstate = (HnswBuildState *) state; - void *chunk = buildstate->hnswarea + buildstate->graph->memoryUsed; + Size alignedSize = MAXALIGN(size); + void *chunk; + + if (alignedSize > 1024 * 1024) + elog(ERROR, "hnsw allocation too large"); - buildstate->graph->memoryUsed += MAXALIGN(size); + if (buildstate->graph->memoryUsed + alignedSize > buildstate->graph->memoryTotal) + elog(ERROR, "hnsw allocator out of memory"); + + chunk = buildstate->hnswarea + buildstate->graph->memoryUsed; + buildstate->graph->memoryUsed += alignedSize; return chunk; } @@ -932,6 +954,8 @@ if (esthnswarea > estother) esthnswarea -= estother; + esthnswarea = Min(esthnswarea, HNSW_MAX_GRAPH_MEMORY); + shm_toc_estimate_chunk(&pcxt->estimator, esthnswarea); shm_toc_estimate_keys(&pcxt->estimator, 2); @@ -974,8 +998,7 @@ snapshot); hnswarea = (char *) shm_toc_allocate(pcxt->toc, esthnswarea); - /* Report less than allocated so never fails */ - InitGraph(&hnswshared->graphData, hnswarea, esthnswarea - 1024 * 1024); + InitGraph(&hnswshared->graphData, hnswarea, esthnswarea); /* * Avoid base address for relptr for Postgres < 14.5 @@ -1054,7 +1077,7 @@ * Build graph */ static void -BuildGraph(HnswBuildState * buildstate, ForkNumber forkNum) +BuildGraph(HnswBuildState * buildstate) { int parallel_workers = 0; @@ -1102,7 +1125,7 @@ InitBuildState(buildstate, heap, index, indexInfo, forkNum); - BuildGraph(buildstate, forkNum); + BuildGraph(buildstate); if (RelationNeedsWAL(index) || forkNum == INIT_FORKNUM) log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocksInFork(index, forkNum), true); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnswinsert.c new/pgvector-0.8.2/src/hnswinsert.c --- old/pgvector-0.8.1/src/hnswinsert.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnswinsert.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,13 +1,18 @@ #include "postgres.h" -#include <math.h> - +#include "access/genam.h" #include "access/generic_xlog.h" #include "hnsw.h" +#include "nodes/execnodes.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "utils/datum.h" #include "utils/memutils.h" +#include "utils/rel.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif /* * Get the insert page @@ -660,7 +665,7 @@ * Update graph on disk */ static void -UpdateGraphOnDisk(Relation index, HnswSupport * support, HnswElement element, int m, int efConstruction, HnswElement entryPoint, bool building) +UpdateGraphOnDisk(Relation index, HnswSupport * support, HnswElement element, int m, HnswElement entryPoint, bool building) { BlockNumber newInsertPage = InvalidBlockNumber; @@ -708,7 +713,7 @@ /* Create an element */ element = HnswInitElement(base, heaptid, m, HnswGetMl(m), HnswGetMaxLevel(m), NULL); - HnswPtrStore(base, element->value, DatumGetPointer(value)); + HnswPtrStore(base, element->value, (char *) DatumGetPointer(value)); /* Prevent concurrent inserts when likely updating entry point */ if (entryPoint == NULL || element->level > entryPoint->level) @@ -728,7 +733,7 @@ HnswFindElementNeighbors(base, element, entryPoint, index, support, m, efConstruction, false); /* Update graph on disk */ - UpdateGraphOnDisk(index, support, element, m, efConstruction, entryPoint, building); + UpdateGraphOnDisk(index, support, element, m, entryPoint, building); /* Release lock */ UnlockPage(index, HNSW_UPDATE_LOCK, lockmode); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnswscan.c new/pgvector-0.8.2/src/hnswscan.c --- old/pgvector-0.8.1/src/hnswscan.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnswscan.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,12 +1,21 @@ #include "postgres.h" +#include "access/genam.h" #include "access/relscan.h" #include "hnsw.h" +#include "lib/pairingheap.h" +#include "miscadmin.h" +#include "nodes/pg_list.h" #include "pgstat.h" -#include "storage/bufmgr.h" #include "storage/lmgr.h" #include "utils/float.h" #include "utils/memutils.h" +#include "utils/relcache.h" +#include "utils/snapmgr.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif /* * Algorithm 5 from paper @@ -193,6 +202,10 @@ /* Count index scan for stats */ pgstat_count_index_scan(scan->indexRelation); +#if PG_VERSION_NUM >= 180000 + if (scan->instrument) + scan->instrument->nsearches++; +#endif /* Safety check */ if (scan->orderByData == NULL) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnswutils.c new/pgvector-0.8.2/src/hnswutils.c --- old/pgvector-0.8.1/src/hnswutils.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnswutils.c 2026-02-25 19:46:57.000000000 +0100 @@ -2,18 +2,24 @@ #include <math.h> +#include "access/genam.h" #include "access/generic_xlog.h" -#include "catalog/pg_type.h" -#include "catalog/pg_type_d.h" #include "common/hashfn.h" #include "fmgr.h" #include "hnsw.h" #include "lib/pairingheap.h" +#include "nodes/pg_list.h" +#include "port/atomics.h" #include "sparsevec.h" #include "storage/bufmgr.h" #include "utils/datum.h" #include "utils/memdebug.h" #include "utils/rel.h" +#include "vector.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif #if PG_VERSION_NUM < 170000 static inline uint64 @@ -256,7 +262,7 @@ HnswInitNeighbors(base, element, m, allocator); - HnswPtrStore(base, element->value, (Pointer) NULL); + HnswPtrStore(base, element->value, (char *) NULL); return element; } @@ -282,7 +288,7 @@ element->blkno = blkno; element->offno = offno; HnswPtrStore(base, element->neighbors, (HnswNeighborArrayPtr *) NULL); - HnswPtrStore(base, element->value, (Pointer) NULL); + HnswPtrStore(base, element->value, (char *) NULL); return element; } @@ -508,7 +514,7 @@ char *base = NULL; Datum value = datumCopy(PointerGetDatum(&etup->data), false, -1); - HnswPtrStore(base, element->value, DatumGetPointer(value)); + HnswPtrStore(base, element->value, (char *) DatumGetPointer(value)); } } @@ -922,7 +928,7 @@ continue; } - if (eElement == NULL || !(eDistance < f->distance || alwaysAdd)) + if (!(eDistance < f->distance || alwaysAdd)) { if (discarded != NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/hnswvacuum.c new/pgvector-0.8.2/src/hnswvacuum.c --- old/pgvector-0.8.1/src/hnswvacuum.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/hnswvacuum.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,13 +1,18 @@ #include "postgres.h" -#include <math.h> - +#include "access/genam.h" #include "access/generic_xlog.h" #include "commands/vacuum.h" #include "hnsw.h" +#include "nodes/pg_list.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "utils/memutils.h" +#include "utils/rel.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif #if PG_VERSION_NUM >= 180000 #define vacuum_delay_point() vacuum_delay_point(false) @@ -174,7 +179,12 @@ /* Also update if layer 0 is not full */ /* This could indicate too many candidates being deleted during insert */ if (!needsUpdated) + { + /* Keep clang-tidy happy */ + Assert(ntup->count > 0); + needsUpdated = !ItemPointerIsValid(&ntup->indextids[ntup->count - 1]); + } UnlockReleaseBuffer(buf); @@ -524,8 +534,9 @@ ntup = (HnswNeighborTuple) PageGetItem(npage, PageGetItemId(npage, neighborOffno)); /* Overwrite element */ + /* Use memset instead of MemSet to keep clang-tidy happy */ etup->deleted = 1; - MemSet(&etup->data, 0, VARSIZE_ANY(&etup->data)); + memset(&etup->data, 0, VARSIZE_ANY(&etup->data)); /* Overwrite neighbors */ for (int i = 0; i < ntup->count; i++) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfbuild.c new/pgvector-0.8.2/src/ivfbuild.c --- old/pgvector-0.8.1/src/ivfbuild.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfbuild.c 2026-02-25 19:46:57.000000000 +0100 @@ -2,23 +2,36 @@ #include <float.h> +#include "access/genam.h" +#include "access/generic_xlog.h" +#include "access/itup.h" +#include "access/relscan.h" #include "access/table.h" #include "access/tableam.h" +#include "access/tupdesc.h" #include "access/parallel.h" #include "access/xact.h" -#include "bitvec.h" +#include "access/xloginsert.h" #include "catalog/index.h" #include "catalog/pg_operator_d.h" #include "catalog/pg_type_d.h" #include "commands/progress.h" -#include "halfvec.h" +#include "fmgr.h" #include "ivfflat.h" #include "miscadmin.h" +#include "nodes/execnodes.h" #include "optimizer/optimizer.h" #include "storage/bufmgr.h" #include "tcop/tcopprot.h" #include "utils/memutils.h" -#include "vector.h" +#include "utils/rel.h" +#include "utils/sampling.h" +#include "utils/snapmgr.h" +#include "utils/tuplesort.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif #if PG_VERSION_NUM >= 140000 #include "utils/backend_progress.h" @@ -138,7 +151,7 @@ * Add tuple to sort */ static void -AddTupleToSort(Relation index, ItemPointer tid, Datum *values, IvfflatBuildState * buildstate) +AddTupleToSort(ItemPointer tid, Datum *values, IvfflatBuildState * buildstate) { double distance; double minDistance = DBL_MAX; @@ -215,7 +228,7 @@ oldCtx = MemoryContextSwitchTo(buildstate->tmpCtx); /* Add tuple to sort */ - AddTupleToSort(index, tid, values, buildstate); + AddTupleToSort(tid, values, buildstate); /* Reset memory context */ MemoryContextSwitchTo(oldCtx); @@ -470,8 +483,8 @@ * Create list pages */ static void -CreateListPages(Relation index, VectorArray centers, int dimensions, - int lists, ForkNumber forkNum, ListInfo * *listInfo) +CreateListPages(Relation index, VectorArray centers, int lists, + ForkNumber forkNum, ListInfo * *listInfo) { Buffer buf; Page page; @@ -1004,7 +1017,7 @@ /* Create pages */ CreateMetaPage(index, buildstate->dimensions, buildstate->lists, forkNum); - CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo); + CreateListPages(index, buildstate->centers, buildstate->lists, forkNum, &buildstate->listInfo); CreateEntryPages(buildstate, forkNum); /* Write WAL for initialization fork since GenericXLog functions do not */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfflat.c new/pgvector-0.8.2/src/ivfflat.c --- old/pgvector-0.8.1/src/ivfflat.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfflat.c 2026-02-25 19:46:57.000000000 +0100 @@ -3,14 +3,19 @@ #include <float.h> #include "access/amapi.h" +#include "access/genam.h" #include "access/reloptions.h" #include "commands/progress.h" #include "commands/vacuum.h" +#include "fmgr.h" #include "ivfflat.h" +#include "nodes/pg_list.h" #include "utils/float.h" #include "utils/guc.h" +#include "utils/relcache.h" #include "utils/selfuncs.h" #include "utils/spccache.h" +#include "vector.h" #if PG_VERSION_NUM < 150000 #define MarkGUCPrefixReserved(x) EmitWarningsOnPlaceholders(x) @@ -179,6 +184,64 @@ Datum ivfflathandler(PG_FUNCTION_ARGS) { +#if PG_VERSION_NUM >= 190000 + static const IndexAmRoutine amroutine = { + .type = T_IndexAmRoutine, + .amstrategies = 0, + .amsupport = 5, + .amoptsprocnum = 0, + .amcanorder = false, + .amcanorderbyop = true, + .amcanhash = false, + .amconsistentequality = false, + .amconsistentordering = false, + .amcanbackward = false, + .amcanunique = false, + .amcanmulticol = false, + .amoptionalkey = true, + .amsearcharray = false, + .amsearchnulls = false, + .amstorage = false, + .amclusterable = false, + .ampredlocks = false, + .amcanparallel = false, + .amcanbuildparallel = true, + .amcaninclude = false, + .amusemaintenanceworkmem = false, + .amsummarizing = false, + .amparallelvacuumoptions = VACUUM_OPTION_PARALLEL_BULKDEL, + .amkeytype = InvalidOid, + + .ambuild = ivfflatbuild, + .ambuildempty = ivfflatbuildempty, + .aminsert = ivfflatinsert, + .aminsertcleanup = NULL, + .ambulkdelete = ivfflatbulkdelete, + .amvacuumcleanup = ivfflatvacuumcleanup, + .amcanreturn = NULL, + .amcostestimate = ivfflatcostestimate, + .amgettreeheight = NULL, + .amoptions = ivfflatoptions, + .amproperty = NULL, + .ambuildphasename = ivfflatbuildphasename, + .amvalidate = ivfflatvalidate, + .amadjustmembers = NULL, + .ambeginscan = ivfflatbeginscan, + .amrescan = ivfflatrescan, + .amgettuple = ivfflatgettuple, + .amgetbitmap = NULL, + .amendscan = ivfflatendscan, + .ammarkpos = NULL, + .amrestrpos = NULL, + .amestimateparallelscan = NULL, + .aminitparallelscan = NULL, + .amparallelrescan = NULL, + .amtranslatestrategy = NULL, + .amtranslatecmptype = NULL, + }; + + PG_RETURN_POINTER(&amroutine); +#else IndexAmRoutine *amroutine = makeNode(IndexAmRoutine); amroutine->amstrategies = 0; @@ -252,4 +315,5 @@ #endif PG_RETURN_POINTER(amroutine); +#endif } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfflat.h new/pgvector-0.8.2/src/ivfflat.h --- old/pgvector-0.8.1/src/ivfflat.h 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfflat.h 2026-02-25 19:46:57.000000000 +0100 @@ -13,6 +13,10 @@ #include "utils/tuplesort.h" #include "vector.h" +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif + #if PG_VERSION_NUM >= 150000 #include "common/pg_prng.h" #endif @@ -21,6 +25,10 @@ #include "portability/instr_time.h" #endif +#if PG_VERSION_NUM >= 190000 +typedef Pointer Item; +#endif + #define IVFFLAT_MAX_DIM 2000 /* Support functions */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfinsert.c new/pgvector-0.8.2/src/ivfinsert.c --- old/pgvector-0.8.1/src/ivfinsert.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfinsert.c 2026-02-25 19:46:57.000000000 +0100 @@ -2,11 +2,16 @@ #include <float.h> +#include "access/genam.h" #include "access/generic_xlog.h" +#include "access/itup.h" +#include "fmgr.h" #include "ivfflat.h" +#include "nodes/execnodes.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "utils/memutils.h" +#include "utils/rel.h" /* * Find the list that minimizes the distance function @@ -65,7 +70,7 @@ * Insert a tuple into the index */ static void -InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid, Relation heapRel) +InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid) { const IvfflatTypeInfo *typeInfo = IvfflatGetTypeInfo(index); IndexTuple itup; @@ -204,7 +209,7 @@ oldCtx = MemoryContextSwitchTo(insertCtx); /* Insert tuple */ - InsertTuple(index, values, isnull, heap_tid, heap); + InsertTuple(index, values, isnull, heap_tid); /* Delete memory context */ MemoryContextSwitchTo(oldCtx); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfkmeans.c new/pgvector-0.8.2/src/ivfkmeans.c --- old/pgvector-0.8.1/src/ivfkmeans.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfkmeans.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,17 +1,19 @@ #include "postgres.h" #include <float.h> +#include <limits.h> #include <math.h> -#include "bitvec.h" -#include "halfutils.h" -#include "halfvec.h" +#include "access/genam.h" +#include "fmgr.h" #include "ivfflat.h" #include "miscadmin.h" -#include "utils/builtins.h" -#include "utils/datum.h" #include "utils/memutils.h" -#include "vector.h" +#include "utils/relcache.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif /* * Initialize with kmeans++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfscan.c new/pgvector-0.8.2/src/ivfscan.c --- old/pgvector-0.8.1/src/ivfscan.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfscan.c 2026-02-25 19:46:57.000000000 +0100 @@ -2,15 +2,26 @@ #include <float.h> +#include "access/genam.h" +#include "access/itup.h" #include "access/relscan.h" +#include "access/tupdesc.h" #include "catalog/pg_operator_d.h" #include "catalog/pg_type_d.h" +#include "fmgr.h" #include "lib/pairingheap.h" #include "ivfflat.h" #include "miscadmin.h" #include "pgstat.h" #include "storage/bufmgr.h" #include "utils/memutils.h" +#include "utils/rel.h" +#include "utils/snapmgr.h" +#include "utils/tuplesort.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif #define GetScanList(ptr) pairingheap_container(IvfflatScanList, ph_node, ptr) #define GetScanListConst(ptr) pairingheap_const_container(IvfflatScanList, ph_node, ptr) @@ -355,6 +366,10 @@ /* Count index scan for stats */ pgstat_count_index_scan(scan->indexRelation); +#if PG_VERSION_NUM >= 180000 + if (scan->instrument) + scan->instrument->nsearches++; +#endif /* Safety check */ if (scan->orderByData == NULL) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfutils.c new/pgvector-0.8.2/src/ivfutils.c --- old/pgvector-0.8.1/src/ivfutils.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfutils.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,13 +1,19 @@ #include "postgres.h" +#include "access/genam.h" #include "access/generic_xlog.h" -#include "bitvec.h" -#include "catalog/pg_type.h" #include "fmgr.h" #include "halfutils.h" #include "halfvec.h" #include "ivfflat.h" #include "storage/bufmgr.h" +#include "utils/relcache.h" +#include "utils/varbit.h" +#include "vector.h" + +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif /* * Allocate a vector array diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/ivfvacuum.c new/pgvector-0.8.2/src/ivfvacuum.c --- old/pgvector-0.8.1/src/ivfvacuum.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/ivfvacuum.c 2026-02-25 19:46:57.000000000 +0100 @@ -1,9 +1,12 @@ #include "postgres.h" +#include "access/genam.h" #include "access/generic_xlog.h" +#include "access/itup.h" #include "commands/vacuum.h" #include "ivfflat.h" #include "storage/bufmgr.h" +#include "utils/relcache.h" #if PG_VERSION_NUM >= 180000 #define vacuum_delay_point() vacuum_delay_point(false) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/sparsevec.c new/pgvector-0.8.2/src/sparsevec.c --- old/pgvector-0.8.1/src/sparsevec.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/sparsevec.c 2026-02-25 19:46:57.000000000 +0100 @@ -5,18 +5,27 @@ #include "catalog/pg_type.h" #include "common/shortest_dec.h" -#include "common/string.h" #include "fmgr.h" #include "halfutils.h" #include "halfvec.h" +#include "lib/stringinfo.h" #include "libpq/pqformat.h" #include "sparsevec.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/float.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" #include "vector.h" +#if PG_VERSION_NUM >= 160000 +#include "varatt.h" +#endif + +#if PG_VERSION_NUM >= 170000 +#include "parser/scansup.h" +#endif + typedef struct SparseInputElement { int32 index; @@ -150,9 +159,9 @@ return result; } -/* - * Check for whitespace, since array_isspace() is static - */ +#if PG_VERSION_NUM >= 170000 +#define sparsevec_isspace(ch) scanner_isspace(ch) +#else static inline bool sparsevec_isspace(char ch) { @@ -165,6 +174,7 @@ return true; return false; } +#endif /* * Compare indices diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/src/vector.c new/pgvector-0.8.2/src/vector.c --- old/pgvector-0.8.1/src/vector.c 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/src/vector.c 2026-02-25 19:46:57.000000000 +0100 @@ -16,16 +16,20 @@ #include "port.h" /* for strtof() */ #include "sparsevec.h" #include "utils/array.h" -#include "utils/builtins.h" #include "utils/float.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" -#include "utils/numeric.h" +#include "utils/varbit.h" #include "vector.h" #if PG_VERSION_NUM >= 160000 #include "varatt.h" #endif +#if PG_VERSION_NUM >= 170000 +#include "parser/scansup.h" +#endif + #define STATE_DIMS(x) (ARR_DIMS(x)[0] - 1) #define CreateStateDatums(dim) palloc(sizeof(Datum) * (dim + 1)) @@ -36,7 +40,7 @@ #endif #if PG_VERSION_NUM >= 180000 -PG_MODULE_MAGIC_EXT(.name = "vector",.version = "0.8.1"); +PG_MODULE_MAGIC_EXT(.name = "vector",.version = "0.8.2"); #else PG_MODULE_MAGIC; #endif @@ -129,9 +133,9 @@ return result; } -/* - * Check for whitespace, since array_isspace() is static - */ +#if PG_VERSION_NUM >= 170000 +#define vector_isspace(ch) scanner_isspace(ch) +#else static inline bool vector_isspace(char ch) { @@ -144,6 +148,7 @@ return true; return false; } +#endif /* * Check state array diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/test/t/005_ivfflat_query_recall.pl new/pgvector-0.8.2/test/t/005_ivfflat_query_recall.pl --- old/pgvector-0.8.1/test/t/005_ivfflat_query_recall.pl 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/test/t/005_ivfflat_query_recall.pl 2026-02-25 19:46:57.000000000 +0100 @@ -16,29 +16,19 @@ "INSERT INTO tst SELECT i, ARRAY[random(), random(), random()] FROM generate_series(1, 100000) i;" ); -# Check each index type -my @operators = ("<->", "<#>", "<=>"); -my @opclasses = ("vector_l2_ops", "vector_ip_ops", "vector_cosine_ops"); +# Add index +$node->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v vector_l2_ops);"); -for my $i (0 .. $#operators) +# Test 100% recall +for (1 .. 20) { - my $operator = $operators[$i]; - my $opclass = $opclasses[$i]; - - # Add index - $node->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v $opclass);"); - - # Test 100% recall - for (1 .. 20) - { - my $id = int(rand() * 100000); - my $query = $node->safe_psql("postgres", "SELECT v FROM tst WHERE i = $id;"); - my $res = $node->safe_psql("postgres", qq( - SET enable_seqscan = off; - SELECT v FROM tst ORDER BY v <-> '$query' LIMIT 1; - )); - is($res, $query); - } + my $id = int(rand() * 100000); + my $query = $node->safe_psql("postgres", "SELECT v FROM tst WHERE i = $id;"); + my $res = $node->safe_psql("postgres", qq( + SET enable_seqscan = off; + SELECT v FROM tst ORDER BY v <-> '$query' LIMIT 1; + )); + is($res, $query); } done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/test/t/045_hnsw_low_memory_build.pl new/pgvector-0.8.2/test/t/045_hnsw_low_memory_build.pl --- old/pgvector-0.8.1/test/t/045_hnsw_low_memory_build.pl 1970-01-01 01:00:00.000000000 +0100 +++ new/pgvector-0.8.2/test/t/045_hnsw_low_memory_build.pl 2026-02-25 19:46:57.000000000 +0100 @@ -0,0 +1,29 @@ +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Initialize node +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init; +$node->start; + +# Create table +$node->safe_psql("postgres", "CREATE EXTENSION vector;"); +$node->safe_psql("postgres", "CREATE TABLE tst (v vector(3));"); +$node->safe_psql("postgres", + "INSERT INTO tst SELECT ARRAY[random(), random(), random()] FROM generate_series(1, 1000) i;" +); + +my ($ret, $stdout, $stderr) = $node->psql("postgres", qq( + SET client_min_messages = DEBUG; + SET maintenance_work_mem = '3073kB'; + ALTER TABLE tst SET (parallel_workers = 1); + CREATE INDEX ON tst USING hnsw (v vector_l2_ops); +)); +is($ret, 0, $stderr); +like($stderr, qr/using \d+ parallel workers/); +like($stderr, qr/hnsw graph no longer fits into maintenance_work_mem after 0 tuples/); + +done_testing(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pgvector-0.8.1/vector.control new/pgvector-0.8.2/vector.control --- old/pgvector-0.8.1/vector.control 2025-09-05 02:51:09.000000000 +0200 +++ new/pgvector-0.8.2/vector.control 2026-02-25 19:46:57.000000000 +0100 @@ -1,4 +1,4 @@ comment = 'vector data type and ivfflat and hnsw access methods' -default_version = '0.8.1' +default_version = '0.8.2' module_pathname = '$libdir/vector' relocatable = true
