Compare commits

...

28 Commits

Author SHA1 Message Date
Andrew Kane
1bc29ac697 Added tuple stats for HNSW [skip ci] 2024-07-13 08:47:53 -07:00
Andrew Kane
8772c8de68 Fixed compilation error with FreeBSD ARM 2024-06-30 11:23:39 -07:00
Andrew Kane
d1694a93af Added ubuntu-24.04 to CI [skip ci] 2024-06-17 10:45:58 -07:00
Andrew Kane
61870a0244 Fixed compilation warning with MSVC and Postgres 16 - fixes #598
Co-authored-by: Xing Guo <higuoxing@gmail.com>
2024-06-16 12:09:01 -07:00
Andrew Kane
9b89bed701 Version bump to 0.7.2 [skip ci] 2024-06-11 17:26:51 -07:00
Andrew Kane
ad7cad5ecd Improved HnswSearchLayer code 2024-06-11 16:29:14 -07:00
Andrew Kane
2a8b9d689e Moved check 2024-06-11 15:45:03 -07:00
Andrew Kane
18cd8a60c3 Updated comment [skip ci] 2024-06-10 22:02:40 -07:00
Andrew Kane
8c91a9f56a Fixed initialization fork for IVFFlat indexes on unlogged tables - #591 2024-06-10 21:55:17 -07:00
Andrew Kane
9249e7e2de Updated changelog [skip ci] 2024-06-10 21:33:49 -07:00
Andrew Kane
9e91af5989 Added checks for invalid indexes - #591 2024-06-10 21:20:54 -07:00
Narek Galstyan
9dcf1bdc80 Fix init_fork WAL-logging on unlogged indexes (#591)
Currently pgvector does not create any WAL records for unlogged tables

Postgres assumes INIT_FORK of unlogged tables is persistent and uses it
to reset the table index to its default empty state after a server
crash.

This patch makes INIT_FORK of unlogged table WAL-tracked, which ensures
an unlogged table is usable after a crash-restart
2024-06-10 21:16:32 -07:00
Andrew Kane
0eceaa3966 Version bump to 0.7.1 [skip ci] 2024-06-03 13:48:51 -07:00
Andrew Kane
49c1f13095 Improved performance of on-disk HNSW index builds - #570 2024-05-29 12:03:58 -07:00
Andrew Kane
ff9b22977e Updated FAQ [skip ci] 2024-05-20 16:48:38 -04:00
Andrew Kane
0468cbf6e6 Added --pull to Docker build instructions [skip ci] 2024-05-20 11:42:11 -04:00
Andrew Kane
258eaf58fd Added halfvec and sparsevec opclasses to readme - closes #540 [skip ci] 2024-05-08 10:40:55 -07:00
Andrew Kane
fa8d2df1cc Added note about ascending order to troubleshooting docs - #548 [skip ci] 2024-05-08 08:36:24 -07:00
Andrew Kane
69f49290fb Fixed compilation warning with Clang < 14 - closes #546 2024-05-07 20:53:41 -07:00
Andrew Kane
ad91451266 Updated changelog and comment [skip ci] 2024-05-07 18:03:21 -07:00
Andrew Kane
cafd2f6641 Updated comment [skip ci] 2024-05-07 17:53:35 -07:00
Andrew Kane
7923c44efe Switched to __apple_build_version__ [skip ci] 2024-05-07 17:41:16 -07:00
Andrew Kane
9b269e2612 Added separate define for __get_cpuid 2024-05-07 16:55:21 -07:00
Andrew Kane
9894ca3e4e Fixed error with cross-compiling / universal binaries on Mac - #544 [skip ci] 2024-05-07 16:46:47 -07:00
Andrew Kane
19cbbfdd69 Fixed undefined symbol error with GCC 8 - fixes #538 2024-05-02 07:50:06 -07:00
Andrew Kane
24c8a2ff40 Fixed flaky tests [skip ci] 2024-04-29 13:54:30 -07:00
Andrew Kane
6df583a6f6 Fixed regression test for vector type 2024-04-29 13:48:04 -07:00
Andrew Kane
999a2e53dd Updated readme [skip ci] 2024-04-29 10:41:40 -07:00
34 changed files with 909 additions and 156 deletions

View File

@@ -9,9 +9,9 @@ jobs:
matrix: matrix:
include: include:
- postgres: 17 - postgres: 17
os: ubuntu-22.04 os: ubuntu-24.04
- postgres: 16 - postgres: 16
os: ubuntu-22.04 os: ubuntu-24.04
- postgres: 15 - postgres: 15
os: ubuntu-22.04 os: ubuntu-22.04
- postgres: 14 - postgres: 14

View File

@@ -1,3 +1,19 @@
## 0.7.3 (unreleased)
- Fixed compilation error with FreeBSD ARM
- Fixed compilation warning with MSVC and Postgres 16
## 0.7.2 (2024-06-11)
- Fixed initialization fork for indexes on unlogged tables
## 0.7.1 (2024-06-03)
- Improved performance of on-disk HNSW index builds
- Fixed `undefined symbol` error with GCC 8
- Fixed compilation error with universal binaries on Mac
- Fixed compilation warning with Clang < 14
## 0.7.0 (2024-04-29) ## 0.7.0 (2024-04-29)
- Added `halfvec` type - Added `halfvec` type

View File

@@ -2,7 +2,7 @@
"name": "vector", "name": "vector",
"abstract": "Open-source vector similarity search for Postgres", "abstract": "Open-source vector similarity search for Postgres",
"description": "Supports L2 distance, inner product, and cosine distance", "description": "Supports L2 distance, inner product, and cosine distance",
"version": "0.7.0", "version": "0.7.2",
"maintainer": [ "maintainer": [
"Andrew Kane <andrew@ankane.org>" "Andrew Kane <andrew@ankane.org>"
], ],
@@ -20,7 +20,7 @@
"vector": { "vector": {
"file": "sql/vector.sql", "file": "sql/vector.sql",
"docfile": "README.md", "docfile": "README.md",
"version": "0.7.0", "version": "0.7.2",
"abstract": "Open-source vector similarity search for Postgres" "abstract": "Open-source vector similarity search for Postgres"
} }
}, },

View File

@@ -1,5 +1,5 @@
EXTENSION = vector EXTENSION = vector
EXTVERSION = 0.7.0 EXTVERSION = 0.7.2
MODULE_big = vector MODULE_big = vector
DATA = $(wildcard sql/*--*.sql) DATA = $(wildcard sql/*--*.sql)

View File

@@ -1,10 +1,10 @@
EXTENSION = vector EXTENSION = vector
EXTVERSION = 0.7.0 EXTVERSION = 0.7.2
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 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
HEADERS = src\halfvec.h src\sparsevec.h src\vector.h HEADERS = src\halfvec.h src\sparsevec.h src\vector.h
REGRESS = bit btree cast copy halfvec hnsw_bit hnsw_halfvec hnsw_sparsevec hnsw_vector ivfflat_bit ivfflat_halfvec ivfflat_vector sparsevec vector REGRESS = bit btree cast copy halfvec hnsw_bit hnsw_halfvec hnsw_sparsevec hnsw_vector ivfflat_bit ivfflat_halfvec ivfflat_vector sparsevec vector_type
REGRESS_OPTS = --inputdir=test --load-extension=$(EXTENSION) REGRESS_OPTS = --inputdir=test --load-extension=$(EXTENSION)
# For /arch flags # For /arch flags

View File

@@ -21,7 +21,7 @@ Compile and install the extension (supports Postgres 12+)
```sh ```sh
cd /tmp cd /tmp
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git git clone --branch v0.7.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
make make
make install # may need sudo make install # may need sudo
@@ -46,7 +46,7 @@ Then use `nmake` to build:
```cmd ```cmd
set "PGROOT=C:\Program Files\PostgreSQL\16" set "PGROOT=C:\Program Files\PostgreSQL\16"
cd %TEMP% cd %TEMP%
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git git clone --branch v0.7.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
nmake /F Makefile.win nmake /F Makefile.win
nmake /F Makefile.win install nmake /F Makefile.win install
@@ -217,6 +217,8 @@ L2 distance
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops); CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);
``` ```
Note: Use `halfvec_l2_ops` for `halfvec` and `sparsevec_l2_ops` for `sparsevec` (and similar with the other distance functions)
Inner product Inner product
```sql ```sql
@@ -345,6 +347,8 @@ L2 distance
CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100); CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
``` ```
Note: Use `halfvec_l2_ops` for `halfvec` (and similar with the other distance functions)
Inner product Inner product
```sql ```sql
@@ -455,7 +459,7 @@ CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
*Added in 0.7.0* *Added in 0.7.0*
Index vectors at half precision for smaller indexes and faster build times Index vectors at half precision for smaller indexes
```sql ```sql
CREATE INDEX ON items USING hnsw ((embedding::halfvec(3)) halfvec_l2_ops); CREATE INDEX ON items USING hnsw ((embedding::halfvec(3)) halfvec_l2_ops);
@@ -727,7 +731,7 @@ Yes, pgvector uses the write-ahead log (WAL), which allows for replication and p
#### What if I want to index vectors with more than 2,000 dimensions? #### What if I want to index vectors with more than 2,000 dimensions?
Youll need to use [dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction) at the moment. 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).
#### Can I store vectors with different dimensions in the same column? #### Can I store vectors with different dimensions in the same column?
@@ -790,7 +794,7 @@ SELECT pg_size_pretty(pg_relation_size('index_name'));
#### Why isnt a query using an index? #### Why isnt a query using an index?
The query needs to have an `ORDER BY` and `LIMIT`, and the `ORDER BY` must be the result of a distance operator, not an expression. The query needs to have an `ORDER BY` and `LIMIT`, and the `ORDER BY` must be the result of a distance operator (not an expression) in ascending order.
```sql ```sql
-- index -- index
@@ -1047,9 +1051,9 @@ This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres) (r
You can also build the image manually: You can also build the image manually:
```sh ```sh
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git git clone --branch v0.7.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
docker build --build-arg PG_MAJOR=16 -t myuser/pgvector . docker build --pull --build-arg PG_MAJOR=16 -t myuser/pgvector .
``` ```
### Homebrew ### Homebrew

View File

@@ -0,0 +1,2 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION vector UPDATE TO '0.7.1'" to load this file. \quit

View File

@@ -0,0 +1,2 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION vector UPDATE TO '0.7.2'" to load this file. \quit

View File

@@ -11,7 +11,7 @@
#ifdef BIT_DISPATCH #ifdef BIT_DISPATCH
#include <immintrin.h> #include <immintrin.h>
#if defined(HAVE__GET_CPUID) #if defined(USE__GET_CPUID)
#include <cpuid.h> #include <cpuid.h>
#else #else
#include <intrin.h> #include <intrin.h>
@@ -173,7 +173,7 @@ SupportsAvx512Popcount()
{ {
unsigned int exx[4] = {0, 0, 0, 0}; unsigned int exx[4] = {0, 0, 0, 0};
#if defined(HAVE__GET_CPUID) #if defined(USE__GET_CPUID)
__get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
#else #else
__cpuid(exx, 1); __cpuid(exx, 1);
@@ -187,7 +187,7 @@ SupportsAvx512Popcount()
if ((_xgetbv(0) & 0xe6) != 0xe6) if ((_xgetbv(0) & 0xe6) != 0xe6)
return false; return false;
#if defined(HAVE__GET_CPUID) #if defined(USE__GET_CPUID)
__get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]); __get_cpuid_count(7, 0, &exx[0], &exx[1], &exx[2], &exx[3]);
#else #else
__cpuidex(exx, 7, 0); __cpuidex(exx, 7, 0);

View File

@@ -3,6 +3,7 @@
#include "bitutils.h" #include "bitutils.h"
#include "bitvec.h" #include "bitvec.h"
#include "utils/varbit.h" #include "utils/varbit.h"
#include "vector.h"
#if PG_VERSION_NUM >= 160000 #if PG_VERSION_NUM >= 160000
#include "varatt.h" #include "varatt.h"
@@ -40,7 +41,7 @@ CheckDims(VarBit *a, VarBit *b)
/* /*
* Get the Hamming distance between two bit vectors * Get the Hamming distance between two bit vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(hamming_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hamming_distance);
Datum Datum
hamming_distance(PG_FUNCTION_ARGS) hamming_distance(PG_FUNCTION_ARGS)
{ {
@@ -55,7 +56,7 @@ hamming_distance(PG_FUNCTION_ARGS)
/* /*
* Get the Jaccard distance between two bit vectors * Get the Jaccard distance between two bit vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(jaccard_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(jaccard_distance);
Datum Datum
jaccard_distance(PG_FUNCTION_ARGS) jaccard_distance(PG_FUNCTION_ARGS)
{ {

View File

@@ -6,7 +6,7 @@
#ifdef HALFVEC_DISPATCH #ifdef HALFVEC_DISPATCH
#include <immintrin.h> #include <immintrin.h>
#if defined(HAVE__GET_CPUID) #if defined(USE__GET_CPUID)
#include <cpuid.h> #include <cpuid.h>
#else #else
#include <intrin.h> #include <intrin.h>
@@ -254,7 +254,7 @@ SupportsCpuFeature(unsigned int feature)
{ {
unsigned int exx[4] = {0, 0, 0, 0}; unsigned int exx[4] = {0, 0, 0, 0};
#if defined(HAVE__GET_CPUID) #if defined(USE__GET_CPUID)
__get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]); __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
#else #else
__cpuid(exx, 1); __cpuid(exx, 1);

View File

@@ -185,7 +185,7 @@ float_underflow_error(void)
/* /*
* Convert textual representation to internal representation * Convert textual representation to internal representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_in); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_in);
Datum Datum
halfvec_in(PG_FUNCTION_ARGS) halfvec_in(PG_FUNCTION_ARGS)
{ {
@@ -299,7 +299,7 @@ halfvec_in(PG_FUNCTION_ARGS)
/* /*
* Convert internal representation to textual representation * Convert internal representation to textual representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_out); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_out);
Datum Datum
halfvec_out(PG_FUNCTION_ARGS) halfvec_out(PG_FUNCTION_ARGS)
{ {
@@ -345,7 +345,7 @@ halfvec_out(PG_FUNCTION_ARGS)
/* /*
* Convert type modifier * Convert type modifier
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_typmod_in); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_typmod_in);
Datum Datum
halfvec_typmod_in(PG_FUNCTION_ARGS) halfvec_typmod_in(PG_FUNCTION_ARGS)
{ {
@@ -376,7 +376,7 @@ halfvec_typmod_in(PG_FUNCTION_ARGS)
/* /*
* Convert external binary representation to internal representation * Convert external binary representation to internal representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_recv); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_recv);
Datum Datum
halfvec_recv(PG_FUNCTION_ARGS) halfvec_recv(PG_FUNCTION_ARGS)
{ {
@@ -410,7 +410,7 @@ halfvec_recv(PG_FUNCTION_ARGS)
/* /*
* Convert internal representation to the external binary representation * Convert internal representation to the external binary representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_send); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_send);
Datum Datum
halfvec_send(PG_FUNCTION_ARGS) halfvec_send(PG_FUNCTION_ARGS)
{ {
@@ -430,7 +430,7 @@ halfvec_send(PG_FUNCTION_ARGS)
* Convert half vector to half vector * Convert half vector to half vector
* This is needed to check the type modifier * This is needed to check the type modifier
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec);
Datum Datum
halfvec(PG_FUNCTION_ARGS) halfvec(PG_FUNCTION_ARGS)
{ {
@@ -445,7 +445,7 @@ halfvec(PG_FUNCTION_ARGS)
/* /*
* Convert array to half vector * Convert array to half vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(array_to_halfvec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(array_to_halfvec);
Datum Datum
array_to_halfvec(PG_FUNCTION_ARGS) array_to_halfvec(PG_FUNCTION_ARGS)
{ {
@@ -519,7 +519,7 @@ array_to_halfvec(PG_FUNCTION_ARGS)
/* /*
* Convert half vector to float4[] * Convert half vector to float4[]
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_to_float4); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_float4);
Datum Datum
halfvec_to_float4(PG_FUNCTION_ARGS) halfvec_to_float4(PG_FUNCTION_ARGS)
{ {
@@ -543,7 +543,7 @@ halfvec_to_float4(PG_FUNCTION_ARGS)
/* /*
* Convert vector to half vec * Convert vector to half vec
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_to_halfvec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_halfvec);
Datum Datum
vector_to_halfvec(PG_FUNCTION_ARGS) vector_to_halfvec(PG_FUNCTION_ARGS)
{ {
@@ -565,7 +565,7 @@ vector_to_halfvec(PG_FUNCTION_ARGS)
/* /*
* Get the L2 distance between half vectors * Get the L2 distance between half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_l2_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_distance);
Datum Datum
halfvec_l2_distance(PG_FUNCTION_ARGS) halfvec_l2_distance(PG_FUNCTION_ARGS)
{ {
@@ -580,7 +580,7 @@ halfvec_l2_distance(PG_FUNCTION_ARGS)
/* /*
* Get the L2 squared distance between half vectors * Get the L2 squared distance between half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_l2_squared_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_squared_distance);
Datum Datum
halfvec_l2_squared_distance(PG_FUNCTION_ARGS) halfvec_l2_squared_distance(PG_FUNCTION_ARGS)
{ {
@@ -595,7 +595,7 @@ halfvec_l2_squared_distance(PG_FUNCTION_ARGS)
/* /*
* Get the inner product of two half vectors * Get the inner product of two half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_inner_product); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_inner_product);
Datum Datum
halfvec_inner_product(PG_FUNCTION_ARGS) halfvec_inner_product(PG_FUNCTION_ARGS)
{ {
@@ -610,7 +610,7 @@ halfvec_inner_product(PG_FUNCTION_ARGS)
/* /*
* Get the negative inner product of two half vectors * Get the negative inner product of two half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_negative_inner_product); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_negative_inner_product);
Datum Datum
halfvec_negative_inner_product(PG_FUNCTION_ARGS) halfvec_negative_inner_product(PG_FUNCTION_ARGS)
{ {
@@ -625,7 +625,7 @@ halfvec_negative_inner_product(PG_FUNCTION_ARGS)
/* /*
* Get the cosine distance between two half vectors * Get the cosine distance between two half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_cosine_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_cosine_distance);
Datum Datum
halfvec_cosine_distance(PG_FUNCTION_ARGS) halfvec_cosine_distance(PG_FUNCTION_ARGS)
{ {
@@ -657,7 +657,7 @@ halfvec_cosine_distance(PG_FUNCTION_ARGS)
* Currently uses angular distance since needs to satisfy triangle inequality * Currently uses angular distance since needs to satisfy triangle inequality
* Assumes inputs are unit vectors (skips norm) * Assumes inputs are unit vectors (skips norm)
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_spherical_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_spherical_distance);
Datum Datum
halfvec_spherical_distance(PG_FUNCTION_ARGS) halfvec_spherical_distance(PG_FUNCTION_ARGS)
{ {
@@ -681,7 +681,7 @@ halfvec_spherical_distance(PG_FUNCTION_ARGS)
/* /*
* Get the L1 distance between two half vectors * Get the L1 distance between two half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_l1_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l1_distance);
Datum Datum
halfvec_l1_distance(PG_FUNCTION_ARGS) halfvec_l1_distance(PG_FUNCTION_ARGS)
{ {
@@ -696,7 +696,7 @@ halfvec_l1_distance(PG_FUNCTION_ARGS)
/* /*
* Get the dimensions of a half vector * Get the dimensions of a half vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_vector_dims); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_vector_dims);
Datum Datum
halfvec_vector_dims(PG_FUNCTION_ARGS) halfvec_vector_dims(PG_FUNCTION_ARGS)
{ {
@@ -708,7 +708,7 @@ halfvec_vector_dims(PG_FUNCTION_ARGS)
/* /*
* Get the L2 norm of a half vector * Get the L2 norm of a half vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_l2_norm); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_norm);
Datum Datum
halfvec_l2_norm(PG_FUNCTION_ARGS) halfvec_l2_norm(PG_FUNCTION_ARGS)
{ {
@@ -730,7 +730,7 @@ halfvec_l2_norm(PG_FUNCTION_ARGS)
/* /*
* Normalize a half vector with the L2 norm * Normalize a half vector with the L2 norm
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_l2_normalize); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_normalize);
Datum Datum
halfvec_l2_normalize(PG_FUNCTION_ARGS) halfvec_l2_normalize(PG_FUNCTION_ARGS)
{ {
@@ -769,7 +769,7 @@ halfvec_l2_normalize(PG_FUNCTION_ARGS)
/* /*
* Add half vectors * Add half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_add); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_add);
Datum Datum
halfvec_add(PG_FUNCTION_ARGS) halfvec_add(PG_FUNCTION_ARGS)
{ {
@@ -808,7 +808,7 @@ halfvec_add(PG_FUNCTION_ARGS)
/* /*
* Subtract half vectors * Subtract half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_sub); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_sub);
Datum Datum
halfvec_sub(PG_FUNCTION_ARGS) halfvec_sub(PG_FUNCTION_ARGS)
{ {
@@ -847,7 +847,7 @@ halfvec_sub(PG_FUNCTION_ARGS)
/* /*
* Multiply half vectors * Multiply half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_mul); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_mul);
Datum Datum
halfvec_mul(PG_FUNCTION_ARGS) halfvec_mul(PG_FUNCTION_ARGS)
{ {
@@ -889,7 +889,7 @@ halfvec_mul(PG_FUNCTION_ARGS)
/* /*
* Concatenate half vectors * Concatenate half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_concat); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_concat);
Datum Datum
halfvec_concat(PG_FUNCTION_ARGS) halfvec_concat(PG_FUNCTION_ARGS)
{ {
@@ -913,7 +913,7 @@ halfvec_concat(PG_FUNCTION_ARGS)
/* /*
* Quantize a half vector * Quantize a half vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_binary_quantize); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_binary_quantize);
Datum Datum
halfvec_binary_quantize(PG_FUNCTION_ARGS) halfvec_binary_quantize(PG_FUNCTION_ARGS)
{ {
@@ -931,7 +931,7 @@ halfvec_binary_quantize(PG_FUNCTION_ARGS)
/* /*
* Get a subvector * Get a subvector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_subvector); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_subvector);
Datum Datum
halfvec_subvector(PG_FUNCTION_ARGS) halfvec_subvector(PG_FUNCTION_ARGS)
{ {
@@ -1005,7 +1005,7 @@ halfvec_cmp_internal(HalfVector * a, HalfVector * b)
/* /*
* Less than * Less than
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_lt); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_lt);
Datum Datum
halfvec_lt(PG_FUNCTION_ARGS) halfvec_lt(PG_FUNCTION_ARGS)
{ {
@@ -1018,7 +1018,7 @@ halfvec_lt(PG_FUNCTION_ARGS)
/* /*
* Less than or equal * Less than or equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_le); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_le);
Datum Datum
halfvec_le(PG_FUNCTION_ARGS) halfvec_le(PG_FUNCTION_ARGS)
{ {
@@ -1031,7 +1031,7 @@ halfvec_le(PG_FUNCTION_ARGS)
/* /*
* Equal * Equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_eq); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_eq);
Datum Datum
halfvec_eq(PG_FUNCTION_ARGS) halfvec_eq(PG_FUNCTION_ARGS)
{ {
@@ -1044,7 +1044,7 @@ halfvec_eq(PG_FUNCTION_ARGS)
/* /*
* Not equal * Not equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_ne); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_ne);
Datum Datum
halfvec_ne(PG_FUNCTION_ARGS) halfvec_ne(PG_FUNCTION_ARGS)
{ {
@@ -1057,7 +1057,7 @@ halfvec_ne(PG_FUNCTION_ARGS)
/* /*
* Greater than or equal * Greater than or equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_ge); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_ge);
Datum Datum
halfvec_ge(PG_FUNCTION_ARGS) halfvec_ge(PG_FUNCTION_ARGS)
{ {
@@ -1070,7 +1070,7 @@ halfvec_ge(PG_FUNCTION_ARGS)
/* /*
* Greater than * Greater than
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_gt); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_gt);
Datum Datum
halfvec_gt(PG_FUNCTION_ARGS) halfvec_gt(PG_FUNCTION_ARGS)
{ {
@@ -1083,7 +1083,7 @@ halfvec_gt(PG_FUNCTION_ARGS)
/* /*
* Compare half vectors * Compare half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_cmp); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_cmp);
Datum Datum
halfvec_cmp(PG_FUNCTION_ARGS) halfvec_cmp(PG_FUNCTION_ARGS)
{ {
@@ -1096,7 +1096,7 @@ halfvec_cmp(PG_FUNCTION_ARGS)
/* /*
* Accumulate half vectors * Accumulate half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_accum); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_accum);
Datum Datum
halfvec_accum(PG_FUNCTION_ARGS) halfvec_accum(PG_FUNCTION_ARGS)
{ {
@@ -1157,7 +1157,7 @@ halfvec_accum(PG_FUNCTION_ARGS)
/* /*
* Average half vectors * Average half vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_avg); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_avg);
Datum Datum
halfvec_avg(PG_FUNCTION_ARGS) halfvec_avg(PG_FUNCTION_ARGS)
{ {
@@ -1191,7 +1191,7 @@ halfvec_avg(PG_FUNCTION_ARGS)
/* /*
* Convert sparse vector to half vector * Convert sparse vector to half vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_to_halfvec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_to_halfvec);
Datum Datum
sparsevec_to_halfvec(PG_FUNCTION_ARGS) sparsevec_to_halfvec(PG_FUNCTION_ARGS)
{ {

View File

@@ -9,7 +9,7 @@
/* TODO Move to better place */ /* TODO Move to better place */
#ifndef DISABLE_DISPATCH #ifndef DISABLE_DISPATCH
/* Only enable for more recent compilers to keep build process simple */ /* Only enable for more recent compilers to keep build process simple */
#if defined(__x86_64__) && defined(__GNUC__) && __GNUC__ >= 8 #if defined(__x86_64__) && defined(__GNUC__) && __GNUC__ >= 9
#define USE_DISPATCH #define USE_DISPATCH
#elif defined(__x86_64__) && defined(__clang_major__) && __clang_major__ >= 7 #elif defined(__x86_64__) && defined(__clang_major__) && __clang_major__ >= 7
#define USE_DISPATCH #define USE_DISPATCH
@@ -19,9 +19,17 @@
#endif #endif
/* target_clones requires glibc */ /* target_clones requires glibc */
#if defined(USE_DISPATCH) && defined(__gnu_linux__) #if defined(USE_DISPATCH) && defined(__gnu_linux__) && defined(__has_attribute)
/* Use separate line for portability */
#if __has_attribute(target_clones)
#define USE_TARGET_CLONES #define USE_TARGET_CLONES
#endif #endif
#endif
/* Apple clang check needed for universal binaries on Mac */
#if defined(USE_DISPATCH) && (defined(HAVE__GET_CPUID) || defined(__apple_build_version__))
#define USE__GET_CPUID
#endif
#if defined(USE_DISPATCH) #if defined(USE_DISPATCH)
#define HALFVEC_DISPATCH #define HALFVEC_DISPATCH
@@ -30,7 +38,7 @@
/* F16C has better performance than _Float16 (on x86-64) */ /* F16C has better performance than _Float16 (on x86-64) */
#if defined(__F16C__) #if defined(__F16C__)
#define F16C_SUPPORT #define F16C_SUPPORT
#elif defined(__FLT16_MAX__) && !defined(HALFVEC_DISPATCH) #elif defined(__FLT16_MAX__) && !defined(HALFVEC_DISPATCH) && !defined(__FreeBSD__)
#define FLT16_SUPPORT #define FLT16_SUPPORT
#endif #endif

View File

@@ -20,6 +20,10 @@ int hnsw_ef_search;
int hnsw_lock_tranche_id; int hnsw_lock_tranche_id;
static relopt_kind hnsw_relopt_kind; static relopt_kind hnsw_relopt_kind;
#ifdef HNSW_STATS
int hnsw_tuples;
#endif
/* /*
* Assign a tranche ID for our LWLocks. This only needs to be done by one * Assign a tranche ID for our LWLocks. This only needs to be done by one
* backend, as the tranche ID is remembered in shared memory. * backend, as the tranche ID is remembered in shared memory.
@@ -135,6 +139,10 @@ hnswcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
genericcostestimate(root, path, loop_count, &costs); genericcostestimate(root, path, loop_count, &costs);
#ifdef HNSW_STATS
elog(INFO, "estimated tuples = %0.f", costs.numIndexTuples);
#endif
/* Use total cost since most work happens before first tuple is returned */ /* Use total cost since most work happens before first tuple is returned */
*indexStartupCost = costs.indexTotalCost; *indexStartupCost = costs.indexTotalCost;
*indexTotalCost = costs.indexTotalCost; *indexTotalCost = costs.indexTotalCost;
@@ -187,7 +195,7 @@ hnswvalidate(Oid opclassoid)
* *
* See https://www.postgresql.org/docs/current/index-api.html * See https://www.postgresql.org/docs/current/index-api.html
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(hnswhandler); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnswhandler);
Datum Datum
hnswhandler(PG_FUNCTION_ARGS) hnswhandler(PG_FUNCTION_ARGS)
{ {

View File

@@ -113,6 +113,10 @@
extern int hnsw_ef_search; extern int hnsw_ef_search;
extern int hnsw_lock_tranche_id; extern int hnsw_lock_tranche_id;
#ifdef HNSW_STATS
extern int hnsw_tuples;
#endif
typedef struct HnswElementData HnswElementData; typedef struct HnswElementData HnswElementData;
typedef struct HnswNeighborArray HnswNeighborArray; typedef struct HnswNeighborArray HnswNeighborArray;
@@ -393,7 +397,7 @@ void HnswInitNeighbors(char *base, HnswElement element, int m, HnswAllocator *
bool HnswInsertTupleOnDisk(Relation index, Datum value, Datum *values, bool *isnull, ItemPointer heap_tid, bool building); bool HnswInsertTupleOnDisk(Relation index, Datum value, Datum *values, bool *isnull, ItemPointer heap_tid, bool building);
void HnswUpdateNeighborsOnDisk(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m, bool checkExisting, bool building); void HnswUpdateNeighborsOnDisk(Relation index, FmgrInfo *procinfo, Oid collation, HnswElement e, int m, bool checkExisting, bool building);
void HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHeaptids, bool loadVec); void HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHeaptids, bool loadVec);
void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec); void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec, float *maxDistance);
void HnswSetElementTuple(char *base, HnswElementTuple etup, HnswElement element); void HnswSetElementTuple(char *base, HnswElementTuple etup, HnswElement element);
void HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm, int lc, int *updateIdx, Relation index, FmgrInfo *procinfo, Oid collation); void HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm, int lc, int *updateIdx, Relation index, FmgrInfo *procinfo, Oid collation);
void HnswLoadNeighbors(HnswElement element, Relation index, int m); void HnswLoadNeighbors(HnswElement element, Relation index, int m);

View File

@@ -1121,8 +1121,8 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
BuildGraph(buildstate, forkNum); BuildGraph(buildstate, forkNum);
if (RelationNeedsWAL(index)) if (RelationNeedsWAL(index) || forkNum == INIT_FORKNUM)
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocks(index), true); log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocksInFork(index, forkNum), true);
FreeBuildState(buildstate); FreeBuildState(buildstate);
} }

View File

@@ -31,13 +31,23 @@ GetScanItems(IndexScanDesc scan, Datum q)
ep = list_make1(HnswEntryCandidate(base, entryPoint, q, index, procinfo, collation, false)); ep = list_make1(HnswEntryCandidate(base, entryPoint, q, index, procinfo, collation, false));
#ifdef HNSW_STATS
hnsw_tuples = 1;
#endif
for (int lc = entryPoint->level; lc >= 1; lc--) for (int lc = entryPoint->level; lc >= 1; lc--)
{ {
w = HnswSearchLayer(base, q, ep, 1, lc, index, procinfo, collation, m, false, NULL); w = HnswSearchLayer(base, q, ep, 1, lc, index, procinfo, collation, m, false, NULL);
ep = w; ep = w;
} }
return HnswSearchLayer(base, q, ep, hnsw_ef_search, 0, index, procinfo, collation, m, false, NULL); w = HnswSearchLayer(base, q, ep, hnsw_ef_search, 0, index, procinfo, collation, m, false, NULL);
#ifdef HNSW_STATS
elog(INFO, "total tuples = %d", hnsw_tuples);
#endif
return w;
} }
/* /*

View File

@@ -300,6 +300,9 @@ HnswGetMetaPageInfo(Relation index, int *m, HnswElement * entryPoint)
page = BufferGetPage(buf); page = BufferGetPage(buf);
metap = HnswPageGetMeta(page); metap = HnswPageGetMeta(page);
if (unlikely(metap->magicNumber != HNSW_MAGIC_NUMBER))
elog(ERROR, "hnsw index is not valid");
if (m != NULL) if (m != NULL)
*m = metap->m; *m = metap->m;
@@ -545,7 +548,7 @@ HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHe
* Load an element and optionally get its distance from q * Load an element and optionally get its distance from q
*/ */
void void
HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec) HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec, float *maxDistance)
{ {
Buffer buf; Buffer buf;
Page page; Page page;
@@ -560,9 +563,6 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
Assert(HnswIsElementTuple(etup)); Assert(HnswIsElementTuple(etup));
/* Load element */
HnswLoadElementFromTuple(element, etup, true, loadVec);
/* Calculate distance */ /* Calculate distance */
if (distance != NULL) if (distance != NULL)
{ {
@@ -572,6 +572,10 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
*distance = (float) DatumGetFloat8(FunctionCall2Coll(procinfo, collation, *q, PointerGetDatum(&etup->data))); *distance = (float) DatumGetFloat8(FunctionCall2Coll(procinfo, collation, *q, PointerGetDatum(&etup->data)));
} }
/* Load element */
if (distance == NULL || maxDistance == NULL || *distance < *maxDistance)
HnswLoadElementFromTuple(element, etup, true, loadVec);
UnlockReleaseBuffer(buf); UnlockReleaseBuffer(buf);
} }
@@ -599,7 +603,7 @@ HnswEntryCandidate(char *base, HnswElement entryPoint, Datum q, Relation index,
if (index == NULL) if (index == NULL)
hc->distance = GetCandidateDistance(base, hc, q, procinfo, collation); hc->distance = GetCandidateDistance(base, hc, q, procinfo, collation);
else else
HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec); HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec, NULL);
return hc; return hc;
} }
@@ -795,25 +799,32 @@ HnswSearchLayer(char *base, Datum q, List *ep, int ef, int lc, Relation index, F
{ {
float eDistance; float eDistance;
HnswElement eElement = HnswPtrAccess(base, e->element); HnswElement eElement = HnswPtrAccess(base, e->element);
bool alwaysAdd = wlen < ef;
#ifdef HNSW_STATS
if (!inserting)
hnsw_tuples++;
#endif
f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner; f = ((HnswPairingHeapNode *) pairingheap_first(W))->inner;
if (index == NULL) if (index == NULL)
eDistance = GetCandidateDistance(base, e, q, procinfo, collation); eDistance = GetCandidateDistance(base, e, q, procinfo, collation);
else else
HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting); HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting, alwaysAdd ? NULL : &f->distance);
Assert(!eElement->deleted); if (eDistance < f->distance || alwaysAdd)
/* Make robust to issues */
if (eElement->level < lc)
continue;
if (eDistance < f->distance || wlen < ef)
{ {
/* Copy e */ HnswCandidate *ec;
HnswCandidate *ec = palloc(sizeof(HnswCandidate));
Assert(!eElement->deleted);
/* Make robust to issues */
if (eElement->level < lc)
continue;
/* Copy e */
ec = palloc(sizeof(HnswCandidate));
HnswPtrStore(base, ec->element, eElement); HnswPtrStore(base, ec->element, eElement);
ec->distance = eDistance; ec->distance = eDistance;
@@ -1102,7 +1113,7 @@ HnswUpdateConnection(char *base, HnswElement element, HnswCandidate * hc, int lm
HnswElement hc3Element = HnswPtrAccess(base, hc3->element); HnswElement hc3Element = HnswPtrAccess(base, hc3->element);
if (HnswPtrIsNull(base, hc3Element->value)) if (HnswPtrIsNull(base, hc3Element->value))
HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true); HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true, NULL);
else else
hc3->distance = GetCandidateDistance(base, hc3, q, procinfo, collation); hc3->distance = GetCandidateDistance(base, hc3, q, procinfo, collation);
@@ -1299,7 +1310,7 @@ HnswGetTypeInfo(Relation index)
return (const HnswTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid)); return (const HnswTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid));
} }
PGDLLEXPORT PG_FUNCTION_INFO_V1(hnsw_halfvec_support); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnsw_halfvec_support);
Datum Datum
hnsw_halfvec_support(PG_FUNCTION_ARGS) hnsw_halfvec_support(PG_FUNCTION_ARGS)
{ {
@@ -1312,7 +1323,7 @@ hnsw_halfvec_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo); PG_RETURN_POINTER(&typeInfo);
}; };
PGDLLEXPORT PG_FUNCTION_INFO_V1(hnsw_bit_support); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnsw_bit_support);
Datum Datum
hnsw_bit_support(PG_FUNCTION_ARGS) hnsw_bit_support(PG_FUNCTION_ARGS)
{ {
@@ -1325,7 +1336,7 @@ hnsw_bit_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo); PG_RETURN_POINTER(&typeInfo);
}; };
PGDLLEXPORT PG_FUNCTION_INFO_V1(hnsw_sparsevec_support); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnsw_sparsevec_support);
Datum Datum
hnsw_sparsevec_support(PG_FUNCTION_ARGS) hnsw_sparsevec_support(PG_FUNCTION_ARGS)
{ {

View File

@@ -256,7 +256,7 @@ RepairGraphEntryPoint(HnswVacuumState * vacuumstate)
LockPage(index, HNSW_UPDATE_LOCK, ShareLock); LockPage(index, HNSW_UPDATE_LOCK, ShareLock);
/* Load element */ /* Load element */
HnswLoadElement(highestPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true); HnswLoadElement(highestPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true, NULL);
/* Repair if needed */ /* Repair if needed */
if (NeedsUpdated(vacuumstate, highestPoint)) if (NeedsUpdated(vacuumstate, highestPoint))
@@ -294,7 +294,7 @@ RepairGraphEntryPoint(HnswVacuumState * vacuumstate)
* is outdated, this can remove connections at higher levels in * is outdated, this can remove connections at higher levels in
* the graph until they are repaired, but this should be fine. * the graph until they are repaired, but this should be fine.
*/ */
HnswLoadElement(entryPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true); HnswLoadElement(entryPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true, NULL);
if (NeedsUpdated(vacuumstate, entryPoint)) if (NeedsUpdated(vacuumstate, entryPoint))
{ {

View File

@@ -1006,6 +1006,10 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo); CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo);
CreateEntryPages(buildstate, forkNum); CreateEntryPages(buildstate, forkNum);
/* Write WAL for initialization fork since GenericXLog functions do not */
if (forkNum == INIT_FORKNUM)
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocksInFork(index, forkNum), true);
FreeBuildState(buildstate); FreeBuildState(buildstate);
} }

View File

@@ -181,7 +181,7 @@ ivfflatvalidate(Oid opclassoid)
* *
* See https://www.postgresql.org/docs/current/index-api.html * See https://www.postgresql.org/docs/current/index-api.html
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflathandler); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflathandler);
Datum Datum
ivfflathandler(PG_FUNCTION_ARGS) ivfflathandler(PG_FUNCTION_ARGS)
{ {

View File

@@ -94,6 +94,9 @@ InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid, R
value = IvfflatNormValue(typeInfo, collation, value); value = IvfflatNormValue(typeInfo, collation, value);
} }
/* Ensure index is valid */
IvfflatGetMetaPageInfo(index, NULL, NULL);
/* Find the insert page - sets the page and list info */ /* Find the insert page - sets the page and list info */
FindInsertPage(index, values, &insertPage, &listInfo); FindInsertPage(index, values, &insertPage, &listInfo);
Assert(BlockNumberIsValid(insertPage)); Assert(BlockNumberIsValid(insertPage));

View File

@@ -170,7 +170,11 @@ IvfflatGetMetaPageInfo(Relation index, int *lists, int *dimensions)
page = BufferGetPage(buf); page = BufferGetPage(buf);
metap = IvfflatPageGetMeta(page); metap = IvfflatPageGetMeta(page);
*lists = metap->lists; if (unlikely(metap->magicNumber != IVFFLAT_MAGIC_NUMBER))
elog(ERROR, "ivfflat index is not valid");
if (lists != NULL)
*lists = metap->lists;
if (dimensions != NULL) if (dimensions != NULL)
*dimensions = metap->dimensions; *dimensions = metap->dimensions;
@@ -338,7 +342,7 @@ IvfflatGetTypeInfo(Relation index)
return (const IvfflatTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid)); return (const IvfflatTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid));
} }
PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflat_halfvec_support); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflat_halfvec_support);
Datum Datum
ivfflat_halfvec_support(PG_FUNCTION_ARGS) ivfflat_halfvec_support(PG_FUNCTION_ARGS)
{ {
@@ -353,7 +357,7 @@ ivfflat_halfvec_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo); PG_RETURN_POINTER(&typeInfo);
}; };
PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflat_bit_support); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflat_bit_support);
Datum Datum
ivfflat_bit_support(PG_FUNCTION_ARGS) ivfflat_bit_support(PG_FUNCTION_ARGS)
{ {

View File

@@ -188,7 +188,7 @@ CompareIndices(const void *a, const void *b)
/* /*
* Convert textual representation to internal representation * Convert textual representation to internal representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_in); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_in);
Datum Datum
sparsevec_in(PG_FUNCTION_ARGS) sparsevec_in(PG_FUNCTION_ARGS)
{ {
@@ -409,7 +409,7 @@ sparsevec_in(PG_FUNCTION_ARGS)
/* /*
* Convert internal representation to textual representation * Convert internal representation to textual representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_out); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_out);
Datum Datum
sparsevec_out(PG_FUNCTION_ARGS) sparsevec_out(PG_FUNCTION_ARGS)
{ {
@@ -462,7 +462,7 @@ sparsevec_out(PG_FUNCTION_ARGS)
/* /*
* Convert type modifier * Convert type modifier
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_typmod_in); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_typmod_in);
Datum Datum
sparsevec_typmod_in(PG_FUNCTION_ARGS) sparsevec_typmod_in(PG_FUNCTION_ARGS)
{ {
@@ -493,7 +493,7 @@ sparsevec_typmod_in(PG_FUNCTION_ARGS)
/* /*
* Convert external binary representation to internal representation * Convert external binary representation to internal representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_recv); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_recv);
Datum Datum
sparsevec_recv(PG_FUNCTION_ARGS) sparsevec_recv(PG_FUNCTION_ARGS)
{ {
@@ -545,7 +545,7 @@ sparsevec_recv(PG_FUNCTION_ARGS)
/* /*
* Convert internal representation to the external binary representation * Convert internal representation to the external binary representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_send); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_send);
Datum Datum
sparsevec_send(PG_FUNCTION_ARGS) sparsevec_send(PG_FUNCTION_ARGS)
{ {
@@ -572,7 +572,7 @@ sparsevec_send(PG_FUNCTION_ARGS)
* Convert sparse vector to sparse vector * Convert sparse vector to sparse vector
* This is needed to check the type modifier * This is needed to check the type modifier
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec);
Datum Datum
sparsevec(PG_FUNCTION_ARGS) sparsevec(PG_FUNCTION_ARGS)
{ {
@@ -587,7 +587,7 @@ sparsevec(PG_FUNCTION_ARGS)
/* /*
* Convert dense vector to sparse vector * Convert dense vector to sparse vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_to_sparsevec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_sparsevec);
Datum Datum
vector_to_sparsevec(PG_FUNCTION_ARGS) vector_to_sparsevec(PG_FUNCTION_ARGS)
{ {
@@ -630,7 +630,7 @@ vector_to_sparsevec(PG_FUNCTION_ARGS)
/* /*
* Convert half vector to sparse vector * Convert half vector to sparse vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_to_sparsevec); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_sparsevec);
Datum Datum
halfvec_to_sparsevec(PG_FUNCTION_ARGS) halfvec_to_sparsevec(PG_FUNCTION_ARGS)
{ {
@@ -721,7 +721,7 @@ SparsevecL2SquaredDistance(SparseVector * a, SparseVector * b)
/* /*
* Get the L2 distance between sparse vectors * Get the L2 distance between sparse vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_l2_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_distance);
Datum Datum
sparsevec_l2_distance(PG_FUNCTION_ARGS) sparsevec_l2_distance(PG_FUNCTION_ARGS)
{ {
@@ -737,7 +737,7 @@ sparsevec_l2_distance(PG_FUNCTION_ARGS)
* Get the L2 squared distance between sparse vectors * Get the L2 squared distance between sparse vectors
* This saves a sqrt calculation * This saves a sqrt calculation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_l2_squared_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_squared_distance);
Datum Datum
sparsevec_l2_squared_distance(PG_FUNCTION_ARGS) sparsevec_l2_squared_distance(PG_FUNCTION_ARGS)
{ {
@@ -788,7 +788,7 @@ SparsevecInnerProduct(SparseVector * a, SparseVector * b)
/* /*
* Get the inner product of two sparse vectors * Get the inner product of two sparse vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_inner_product); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_inner_product);
Datum Datum
sparsevec_inner_product(PG_FUNCTION_ARGS) sparsevec_inner_product(PG_FUNCTION_ARGS)
{ {
@@ -803,7 +803,7 @@ sparsevec_inner_product(PG_FUNCTION_ARGS)
/* /*
* Get the negative inner product of two sparse vectors * Get the negative inner product of two sparse vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_negative_inner_product); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_negative_inner_product);
Datum Datum
sparsevec_negative_inner_product(PG_FUNCTION_ARGS) sparsevec_negative_inner_product(PG_FUNCTION_ARGS)
{ {
@@ -818,7 +818,7 @@ sparsevec_negative_inner_product(PG_FUNCTION_ARGS)
/* /*
* Get the cosine distance between two sparse vectors * Get the cosine distance between two sparse vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_cosine_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_cosine_distance);
Datum Datum
sparsevec_cosine_distance(PG_FUNCTION_ARGS) sparsevec_cosine_distance(PG_FUNCTION_ARGS)
{ {
@@ -863,7 +863,7 @@ sparsevec_cosine_distance(PG_FUNCTION_ARGS)
/* /*
* Get the L1 distance between two sparse vectors * Get the L1 distance between two sparse vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_l1_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l1_distance);
Datum Datum
sparsevec_l1_distance(PG_FUNCTION_ARGS) sparsevec_l1_distance(PG_FUNCTION_ARGS)
{ {
@@ -912,7 +912,7 @@ sparsevec_l1_distance(PG_FUNCTION_ARGS)
/* /*
* Get the L2 norm of a sparse vector * Get the L2 norm of a sparse vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_l2_norm); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_norm);
Datum Datum
sparsevec_l2_norm(PG_FUNCTION_ARGS) sparsevec_l2_norm(PG_FUNCTION_ARGS)
{ {
@@ -930,7 +930,7 @@ sparsevec_l2_norm(PG_FUNCTION_ARGS)
/* /*
* Normalize a sparse vector with the L2 norm * Normalize a sparse vector with the L2 norm
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_l2_normalize); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_normalize);
Datum Datum
sparsevec_l2_normalize(PG_FUNCTION_ARGS) sparsevec_l2_normalize(PG_FUNCTION_ARGS)
{ {
@@ -1040,7 +1040,7 @@ sparsevec_cmp_internal(SparseVector * a, SparseVector * b)
/* /*
* Less than * Less than
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_lt); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_lt);
Datum Datum
sparsevec_lt(PG_FUNCTION_ARGS) sparsevec_lt(PG_FUNCTION_ARGS)
{ {
@@ -1053,7 +1053,7 @@ sparsevec_lt(PG_FUNCTION_ARGS)
/* /*
* Less than or equal * Less than or equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_le); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_le);
Datum Datum
sparsevec_le(PG_FUNCTION_ARGS) sparsevec_le(PG_FUNCTION_ARGS)
{ {
@@ -1066,7 +1066,7 @@ sparsevec_le(PG_FUNCTION_ARGS)
/* /*
* Equal * Equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_eq); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_eq);
Datum Datum
sparsevec_eq(PG_FUNCTION_ARGS) sparsevec_eq(PG_FUNCTION_ARGS)
{ {
@@ -1079,7 +1079,7 @@ sparsevec_eq(PG_FUNCTION_ARGS)
/* /*
* Not equal * Not equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_ne); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_ne);
Datum Datum
sparsevec_ne(PG_FUNCTION_ARGS) sparsevec_ne(PG_FUNCTION_ARGS)
{ {
@@ -1092,7 +1092,7 @@ sparsevec_ne(PG_FUNCTION_ARGS)
/* /*
* Greater than or equal * Greater than or equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_ge); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_ge);
Datum Datum
sparsevec_ge(PG_FUNCTION_ARGS) sparsevec_ge(PG_FUNCTION_ARGS)
{ {
@@ -1105,7 +1105,7 @@ sparsevec_ge(PG_FUNCTION_ARGS)
/* /*
* Greater than * Greater than
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_gt); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_gt);
Datum Datum
sparsevec_gt(PG_FUNCTION_ARGS) sparsevec_gt(PG_FUNCTION_ARGS)
{ {
@@ -1118,7 +1118,7 @@ sparsevec_gt(PG_FUNCTION_ARGS)
/* /*
* Compare sparse vectors * Compare sparse vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_cmp); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_cmp);
Datum Datum
sparsevec_cmp(PG_FUNCTION_ARGS) sparsevec_cmp(PG_FUNCTION_ARGS)
{ {

View File

@@ -181,7 +181,7 @@ float_underflow_error(void)
/* /*
* Convert textual representation to internal representation * Convert textual representation to internal representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_in); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_in);
Datum Datum
vector_in(PG_FUNCTION_ARGS) vector_in(PG_FUNCTION_ARGS)
{ {
@@ -294,7 +294,7 @@ vector_in(PG_FUNCTION_ARGS)
/* /*
* Convert internal representation to textual representation * Convert internal representation to textual representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_out); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_out);
Datum Datum
vector_out(PG_FUNCTION_ARGS) vector_out(PG_FUNCTION_ARGS)
{ {
@@ -348,7 +348,7 @@ PrintVector(char *msg, Vector * vector)
/* /*
* Convert type modifier * Convert type modifier
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_typmod_in); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_typmod_in);
Datum Datum
vector_typmod_in(PG_FUNCTION_ARGS) vector_typmod_in(PG_FUNCTION_ARGS)
{ {
@@ -379,7 +379,7 @@ vector_typmod_in(PG_FUNCTION_ARGS)
/* /*
* Convert external binary representation to internal representation * Convert external binary representation to internal representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_recv); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_recv);
Datum Datum
vector_recv(PG_FUNCTION_ARGS) vector_recv(PG_FUNCTION_ARGS)
{ {
@@ -413,7 +413,7 @@ vector_recv(PG_FUNCTION_ARGS)
/* /*
* Convert internal representation to the external binary representation * Convert internal representation to the external binary representation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_send); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_send);
Datum Datum
vector_send(PG_FUNCTION_ARGS) vector_send(PG_FUNCTION_ARGS)
{ {
@@ -433,7 +433,7 @@ vector_send(PG_FUNCTION_ARGS)
* Convert vector to vector * Convert vector to vector
* This is needed to check the type modifier * This is needed to check the type modifier
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector);
Datum Datum
vector(PG_FUNCTION_ARGS) vector(PG_FUNCTION_ARGS)
{ {
@@ -448,7 +448,7 @@ vector(PG_FUNCTION_ARGS)
/* /*
* Convert array to vector * Convert array to vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(array_to_vector); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(array_to_vector);
Datum Datum
array_to_vector(PG_FUNCTION_ARGS) array_to_vector(PG_FUNCTION_ARGS)
{ {
@@ -522,7 +522,7 @@ array_to_vector(PG_FUNCTION_ARGS)
/* /*
* Convert vector to float4[] * Convert vector to float4[]
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_to_float4); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_float4);
Datum Datum
vector_to_float4(PG_FUNCTION_ARGS) vector_to_float4(PG_FUNCTION_ARGS)
{ {
@@ -546,7 +546,7 @@ vector_to_float4(PG_FUNCTION_ARGS)
/* /*
* Convert half vector to vector * Convert half vector to vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_to_vector); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_vector);
Datum Datum
halfvec_to_vector(PG_FUNCTION_ARGS) halfvec_to_vector(PG_FUNCTION_ARGS)
{ {
@@ -584,7 +584,7 @@ VectorL2SquaredDistance(int dim, float *ax, float *bx)
/* /*
* Get the L2 distance between vectors * Get the L2 distance between vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(l2_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(l2_distance);
Datum Datum
l2_distance(PG_FUNCTION_ARGS) l2_distance(PG_FUNCTION_ARGS)
{ {
@@ -600,7 +600,7 @@ l2_distance(PG_FUNCTION_ARGS)
* Get the L2 squared distance between vectors * Get the L2 squared distance between vectors
* This saves a sqrt calculation * This saves a sqrt calculation
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_l2_squared_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_l2_squared_distance);
Datum Datum
vector_l2_squared_distance(PG_FUNCTION_ARGS) vector_l2_squared_distance(PG_FUNCTION_ARGS)
{ {
@@ -627,7 +627,7 @@ VectorInnerProduct(int dim, float *ax, float *bx)
/* /*
* Get the inner product of two vectors * Get the inner product of two vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(inner_product); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(inner_product);
Datum Datum
inner_product(PG_FUNCTION_ARGS) inner_product(PG_FUNCTION_ARGS)
{ {
@@ -642,7 +642,7 @@ inner_product(PG_FUNCTION_ARGS)
/* /*
* Get the negative inner product of two vectors * Get the negative inner product of two vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_negative_inner_product); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_negative_inner_product);
Datum Datum
vector_negative_inner_product(PG_FUNCTION_ARGS) vector_negative_inner_product(PG_FUNCTION_ARGS)
{ {
@@ -676,7 +676,7 @@ VectorCosineSimilarity(int dim, float *ax, float *bx)
/* /*
* Get the cosine distance between two vectors * Get the cosine distance between two vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(cosine_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(cosine_distance);
Datum Datum
cosine_distance(PG_FUNCTION_ARGS) cosine_distance(PG_FUNCTION_ARGS)
{ {
@@ -708,7 +708,7 @@ cosine_distance(PG_FUNCTION_ARGS)
* Currently uses angular distance since needs to satisfy triangle inequality * Currently uses angular distance since needs to satisfy triangle inequality
* Assumes inputs are unit vectors (skips norm) * Assumes inputs are unit vectors (skips norm)
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_spherical_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_spherical_distance);
Datum Datum
vector_spherical_distance(PG_FUNCTION_ARGS) vector_spherical_distance(PG_FUNCTION_ARGS)
{ {
@@ -745,7 +745,7 @@ VectorL1Distance(int dim, float *ax, float *bx)
/* /*
* Get the L1 distance between two vectors * Get the L1 distance between two vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(l1_distance); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(l1_distance);
Datum Datum
l1_distance(PG_FUNCTION_ARGS) l1_distance(PG_FUNCTION_ARGS)
{ {
@@ -760,7 +760,7 @@ l1_distance(PG_FUNCTION_ARGS)
/* /*
* Get the dimensions of a vector * Get the dimensions of a vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_dims); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_dims);
Datum Datum
vector_dims(PG_FUNCTION_ARGS) vector_dims(PG_FUNCTION_ARGS)
{ {
@@ -772,7 +772,7 @@ vector_dims(PG_FUNCTION_ARGS)
/* /*
* Get the L2 norm of a vector * Get the L2 norm of a vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_norm); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_norm);
Datum Datum
vector_norm(PG_FUNCTION_ARGS) vector_norm(PG_FUNCTION_ARGS)
{ {
@@ -790,7 +790,7 @@ vector_norm(PG_FUNCTION_ARGS)
/* /*
* Normalize a vector with the L2 norm * Normalize a vector with the L2 norm
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(l2_normalize); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(l2_normalize);
Datum Datum
l2_normalize(PG_FUNCTION_ARGS) l2_normalize(PG_FUNCTION_ARGS)
{ {
@@ -829,7 +829,7 @@ l2_normalize(PG_FUNCTION_ARGS)
/* /*
* Add vectors * Add vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_add); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_add);
Datum Datum
vector_add(PG_FUNCTION_ARGS) vector_add(PG_FUNCTION_ARGS)
{ {
@@ -862,7 +862,7 @@ vector_add(PG_FUNCTION_ARGS)
/* /*
* Subtract vectors * Subtract vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_sub); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_sub);
Datum Datum
vector_sub(PG_FUNCTION_ARGS) vector_sub(PG_FUNCTION_ARGS)
{ {
@@ -895,7 +895,7 @@ vector_sub(PG_FUNCTION_ARGS)
/* /*
* Multiply vectors * Multiply vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_mul); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_mul);
Datum Datum
vector_mul(PG_FUNCTION_ARGS) vector_mul(PG_FUNCTION_ARGS)
{ {
@@ -931,7 +931,7 @@ vector_mul(PG_FUNCTION_ARGS)
/* /*
* Concatenate vectors * Concatenate vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_concat); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_concat);
Datum Datum
vector_concat(PG_FUNCTION_ARGS) vector_concat(PG_FUNCTION_ARGS)
{ {
@@ -955,7 +955,7 @@ vector_concat(PG_FUNCTION_ARGS)
/* /*
* Quantize a vector * Quantize a vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(binary_quantize); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(binary_quantize);
Datum Datum
binary_quantize(PG_FUNCTION_ARGS) binary_quantize(PG_FUNCTION_ARGS)
{ {
@@ -973,7 +973,7 @@ binary_quantize(PG_FUNCTION_ARGS)
/* /*
* Get a subvector * Get a subvector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(subvector); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(subvector);
Datum Datum
subvector(PG_FUNCTION_ARGS) subvector(PG_FUNCTION_ARGS)
{ {
@@ -1047,7 +1047,7 @@ vector_cmp_internal(Vector * a, Vector * b)
/* /*
* Less than * Less than
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_lt); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_lt);
Datum Datum
vector_lt(PG_FUNCTION_ARGS) vector_lt(PG_FUNCTION_ARGS)
{ {
@@ -1060,7 +1060,7 @@ vector_lt(PG_FUNCTION_ARGS)
/* /*
* Less than or equal * Less than or equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_le); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_le);
Datum Datum
vector_le(PG_FUNCTION_ARGS) vector_le(PG_FUNCTION_ARGS)
{ {
@@ -1073,7 +1073,7 @@ vector_le(PG_FUNCTION_ARGS)
/* /*
* Equal * Equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_eq); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_eq);
Datum Datum
vector_eq(PG_FUNCTION_ARGS) vector_eq(PG_FUNCTION_ARGS)
{ {
@@ -1086,7 +1086,7 @@ vector_eq(PG_FUNCTION_ARGS)
/* /*
* Not equal * Not equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_ne); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_ne);
Datum Datum
vector_ne(PG_FUNCTION_ARGS) vector_ne(PG_FUNCTION_ARGS)
{ {
@@ -1099,7 +1099,7 @@ vector_ne(PG_FUNCTION_ARGS)
/* /*
* Greater than or equal * Greater than or equal
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_ge); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_ge);
Datum Datum
vector_ge(PG_FUNCTION_ARGS) vector_ge(PG_FUNCTION_ARGS)
{ {
@@ -1112,7 +1112,7 @@ vector_ge(PG_FUNCTION_ARGS)
/* /*
* Greater than * Greater than
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_gt); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_gt);
Datum Datum
vector_gt(PG_FUNCTION_ARGS) vector_gt(PG_FUNCTION_ARGS)
{ {
@@ -1125,7 +1125,7 @@ vector_gt(PG_FUNCTION_ARGS)
/* /*
* Compare vectors * Compare vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_cmp); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_cmp);
Datum Datum
vector_cmp(PG_FUNCTION_ARGS) vector_cmp(PG_FUNCTION_ARGS)
{ {
@@ -1138,7 +1138,7 @@ vector_cmp(PG_FUNCTION_ARGS)
/* /*
* Accumulate vectors * Accumulate vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_accum); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_accum);
Datum Datum
vector_accum(PG_FUNCTION_ARGS) vector_accum(PG_FUNCTION_ARGS)
{ {
@@ -1199,7 +1199,7 @@ vector_accum(PG_FUNCTION_ARGS)
/* /*
* Combine vectors or half vectors (also used for halfvec_combine) * Combine vectors or half vectors (also used for halfvec_combine)
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_combine); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_combine);
Datum Datum
vector_combine(PG_FUNCTION_ARGS) vector_combine(PG_FUNCTION_ARGS)
{ {
@@ -1270,7 +1270,7 @@ vector_combine(PG_FUNCTION_ARGS)
/* /*
* Average vectors * Average vectors
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_avg); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_avg);
Datum Datum
vector_avg(PG_FUNCTION_ARGS) vector_avg(PG_FUNCTION_ARGS)
{ {
@@ -1304,7 +1304,7 @@ vector_avg(PG_FUNCTION_ARGS)
/* /*
* Convert sparse vector to dense vector * Convert sparse vector to dense vector
*/ */
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_to_vector); FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_to_vector);
Datum Datum
sparsevec_to_vector(PG_FUNCTION_ARGS) sparsevec_to_vector(PG_FUNCTION_ARGS)
{ {

View File

@@ -20,4 +20,11 @@ Vector *InitVector(int dim);
void PrintVector(char *msg, Vector * vector); void PrintVector(char *msg, Vector * vector);
int vector_cmp_internal(Vector * a, Vector * b); int vector_cmp_internal(Vector * a, Vector * b);
/* TODO Move to better place */
#if PG_VERSION_NUM >= 160000
#define FUNCTION_PREFIX
#else
#define FUNCTION_PREFIX PGDLLEXPORT
#endif
#endif #endif

View File

@@ -1,3 +0,0 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION vector" to load this file. \quit
Use "CREATE EXTENSION vector" to load this file.

View File

@@ -0,0 +1,672 @@
SELECT '[1,2,3]'::vector;
vector
---------
[1,2,3]
(1 row)
SELECT '[-1,-2,-3]'::vector;
vector
------------
[-1,-2,-3]
(1 row)
SELECT '[1.,2.,3.]'::vector;
vector
---------
[1,2,3]
(1 row)
SELECT ' [ 1, 2 , 3 ] '::vector;
vector
---------
[1,2,3]
(1 row)
SELECT '[1.23456]'::vector;
vector
-----------
[1.23456]
(1 row)
SELECT '[hello,1]'::vector;
ERROR: invalid input syntax for type vector: "[hello,1]"
LINE 1: SELECT '[hello,1]'::vector;
^
SELECT '[NaN,1]'::vector;
ERROR: NaN not allowed in vector
LINE 1: SELECT '[NaN,1]'::vector;
^
SELECT '[Infinity,1]'::vector;
ERROR: infinite value not allowed in vector
LINE 1: SELECT '[Infinity,1]'::vector;
^
SELECT '[-Infinity,1]'::vector;
ERROR: infinite value not allowed in vector
LINE 1: SELECT '[-Infinity,1]'::vector;
^
SELECT '[1.5e38,-1.5e38]'::vector;
vector
--------------------
[1.5e+38,-1.5e+38]
(1 row)
SELECT '[1.5e+38,-1.5e+38]'::vector;
vector
--------------------
[1.5e+38,-1.5e+38]
(1 row)
SELECT '[1.5e-38,-1.5e-38]'::vector;
vector
--------------------
[1.5e-38,-1.5e-38]
(1 row)
SELECT '[4e38,1]'::vector;
ERROR: "4e38" is out of range for type vector
LINE 1: SELECT '[4e38,1]'::vector;
^
SELECT '[-4e38,1]'::vector;
ERROR: "-4e38" is out of range for type vector
LINE 1: SELECT '[-4e38,1]'::vector;
^
SELECT '[1e-46,1]'::vector;
vector
--------
[0,1]
(1 row)
SELECT '[-1e-46,1]'::vector;
vector
--------
[-0,1]
(1 row)
SELECT '[1,2,3'::vector;
ERROR: invalid input syntax for type vector: "[1,2,3"
LINE 1: SELECT '[1,2,3'::vector;
^
SELECT '[1,2,3]9'::vector;
ERROR: invalid input syntax for type vector: "[1,2,3]9"
LINE 1: SELECT '[1,2,3]9'::vector;
^
DETAIL: Junk after closing right brace.
SELECT '1,2,3'::vector;
ERROR: invalid input syntax for type vector: "1,2,3"
LINE 1: SELECT '1,2,3'::vector;
^
DETAIL: Vector contents must start with "[".
SELECT ''::vector;
ERROR: invalid input syntax for type vector: ""
LINE 1: SELECT ''::vector;
^
DETAIL: Vector contents must start with "[".
SELECT '['::vector;
ERROR: invalid input syntax for type vector: "["
LINE 1: SELECT '['::vector;
^
SELECT '[ '::vector;
ERROR: invalid input syntax for type vector: "[ "
LINE 1: SELECT '[ '::vector;
^
SELECT '[,'::vector;
ERROR: invalid input syntax for type vector: "[,"
LINE 1: SELECT '[,'::vector;
^
SELECT '[]'::vector;
ERROR: vector must have at least 1 dimension
LINE 1: SELECT '[]'::vector;
^
SELECT '[ ]'::vector;
ERROR: vector must have at least 1 dimension
LINE 1: SELECT '[ ]'::vector;
^
SELECT '[,]'::vector;
ERROR: invalid input syntax for type vector: "[,]"
LINE 1: SELECT '[,]'::vector;
^
SELECT '[1,]'::vector;
ERROR: invalid input syntax for type vector: "[1,]"
LINE 1: SELECT '[1,]'::vector;
^
SELECT '[1a]'::vector;
ERROR: invalid input syntax for type vector: "[1a]"
LINE 1: SELECT '[1a]'::vector;
^
SELECT '[1,,3]'::vector;
ERROR: invalid input syntax for type vector: "[1,,3]"
LINE 1: SELECT '[1,,3]'::vector;
^
SELECT '[1, ,3]'::vector;
ERROR: invalid input syntax for type vector: "[1, ,3]"
LINE 1: SELECT '[1, ,3]'::vector;
^
SELECT '[1,2,3]'::vector(3);
vector
---------
[1,2,3]
(1 row)
SELECT '[1,2,3]'::vector(2);
ERROR: expected 2 dimensions, not 3
SELECT '[1,2,3]'::vector(3, 2);
ERROR: invalid type modifier
LINE 1: SELECT '[1,2,3]'::vector(3, 2);
^
SELECT '[1,2,3]'::vector('a');
ERROR: invalid input syntax for type integer: "a"
LINE 1: SELECT '[1,2,3]'::vector('a');
^
SELECT '[1,2,3]'::vector(0);
ERROR: dimensions for type vector must be at least 1
LINE 1: SELECT '[1,2,3]'::vector(0);
^
SELECT '[1,2,3]'::vector(16001);
ERROR: dimensions for type vector cannot exceed 16000
LINE 1: SELECT '[1,2,3]'::vector(16001);
^
SELECT unnest('{"[1,2,3]", "[4,5,6]"}'::vector[]);
unnest
---------
[1,2,3]
[4,5,6]
(2 rows)
SELECT '{"[1,2,3]"}'::vector(2)[];
ERROR: expected 2 dimensions, not 3
SELECT '[1,2,3]'::vector + '[4,5,6]';
?column?
----------
[5,7,9]
(1 row)
SELECT '[3e38]'::vector + '[3e38]';
ERROR: value out of range: overflow
SELECT '[1,2]'::vector + '[3]';
ERROR: different vector dimensions 2 and 1
SELECT '[1,2,3]'::vector - '[4,5,6]';
?column?
------------
[-3,-3,-3]
(1 row)
SELECT '[-3e38]'::vector - '[3e38]';
ERROR: value out of range: overflow
SELECT '[1,2]'::vector - '[3]';
ERROR: different vector dimensions 2 and 1
SELECT '[1,2,3]'::vector * '[4,5,6]';
?column?
-----------
[4,10,18]
(1 row)
SELECT '[1e37]'::vector * '[1e37]';
ERROR: value out of range: overflow
SELECT '[1e-37]'::vector * '[1e-37]';
ERROR: value out of range: underflow
SELECT '[1,2]'::vector * '[3]';
ERROR: different vector dimensions 2 and 1
SELECT '[1,2,3]'::vector || '[4,5]';
?column?
-------------
[1,2,3,4,5]
(1 row)
SELECT array_fill(0, ARRAY[16000])::vector || '[1]';
ERROR: vector cannot have more than 16000 dimensions
SELECT '[1,2,3]'::vector < '[1,2,3]';
?column?
----------
f
(1 row)
SELECT '[1,2,3]'::vector < '[1,2]';
?column?
----------
f
(1 row)
SELECT '[1,2,3]'::vector <= '[1,2,3]';
?column?
----------
t
(1 row)
SELECT '[1,2,3]'::vector <= '[1,2]';
?column?
----------
f
(1 row)
SELECT '[1,2,3]'::vector = '[1,2,3]';
?column?
----------
t
(1 row)
SELECT '[1,2,3]'::vector = '[1,2]';
?column?
----------
f
(1 row)
SELECT '[1,2,3]'::vector != '[1,2,3]';
?column?
----------
f
(1 row)
SELECT '[1,2,3]'::vector != '[1,2]';
?column?
----------
t
(1 row)
SELECT '[1,2,3]'::vector >= '[1,2,3]';
?column?
----------
t
(1 row)
SELECT '[1,2,3]'::vector >= '[1,2]';
?column?
----------
t
(1 row)
SELECT '[1,2,3]'::vector > '[1,2,3]';
?column?
----------
f
(1 row)
SELECT '[1,2,3]'::vector > '[1,2]';
?column?
----------
t
(1 row)
SELECT vector_cmp('[1,2,3]', '[1,2,3]');
vector_cmp
------------
0
(1 row)
SELECT vector_cmp('[1,2,3]', '[0,0,0]');
vector_cmp
------------
1
(1 row)
SELECT vector_cmp('[0,0,0]', '[1,2,3]');
vector_cmp
------------
-1
(1 row)
SELECT vector_cmp('[1,2]', '[1,2,3]');
vector_cmp
------------
-1
(1 row)
SELECT vector_cmp('[1,2,3]', '[1,2]');
vector_cmp
------------
1
(1 row)
SELECT vector_cmp('[1,2]', '[2,3,4]');
vector_cmp
------------
-1
(1 row)
SELECT vector_cmp('[2,3]', '[1,2,3]');
vector_cmp
------------
1
(1 row)
SELECT vector_dims('[1,2,3]'::vector);
vector_dims
-------------
3
(1 row)
SELECT round(vector_norm('[1,1]')::numeric, 5);
round
---------
1.41421
(1 row)
SELECT vector_norm('[3,4]');
vector_norm
-------------
5
(1 row)
SELECT vector_norm('[0,1]');
vector_norm
-------------
1
(1 row)
SELECT vector_norm('[3e37,4e37]')::real;
vector_norm
-------------
5e+37
(1 row)
SELECT vector_norm('[0,0]');
vector_norm
-------------
0
(1 row)
SELECT vector_norm('[2]');
vector_norm
-------------
2
(1 row)
SELECT l2_distance('[0,0]'::vector, '[3,4]');
l2_distance
-------------
5
(1 row)
SELECT l2_distance('[0,0]'::vector, '[0,1]');
l2_distance
-------------
1
(1 row)
SELECT l2_distance('[1,2]'::vector, '[3]');
ERROR: different vector dimensions 2 and 1
SELECT l2_distance('[3e38]'::vector, '[-3e38]');
l2_distance
-------------
Infinity
(1 row)
SELECT l2_distance('[1,1,1,1,1,1,1,1,1]'::vector, '[1,1,1,1,1,1,1,4,5]');
l2_distance
-------------
5
(1 row)
SELECT '[0,0]'::vector <-> '[3,4]';
?column?
----------
5
(1 row)
SELECT inner_product('[1,2]'::vector, '[3,4]');
inner_product
---------------
11
(1 row)
SELECT inner_product('[1,2]'::vector, '[3]');
ERROR: different vector dimensions 2 and 1
SELECT inner_product('[3e38]'::vector, '[3e38]');
inner_product
---------------
Infinity
(1 row)
SELECT inner_product('[1,1,1,1,1,1,1,1,1]'::vector, '[1,2,3,4,5,6,7,8,9]');
inner_product
---------------
45
(1 row)
SELECT '[1,2]'::vector <#> '[3,4]';
?column?
----------
-11
(1 row)
SELECT cosine_distance('[1,2]'::vector, '[2,4]');
cosine_distance
-----------------
0
(1 row)
SELECT cosine_distance('[1,2]'::vector, '[0,0]');
cosine_distance
-----------------
NaN
(1 row)
SELECT cosine_distance('[1,1]'::vector, '[1,1]');
cosine_distance
-----------------
0
(1 row)
SELECT cosine_distance('[1,0]'::vector, '[0,2]');
cosine_distance
-----------------
1
(1 row)
SELECT cosine_distance('[1,1]'::vector, '[-1,-1]');
cosine_distance
-----------------
2
(1 row)
SELECT cosine_distance('[1,2]'::vector, '[3]');
ERROR: different vector dimensions 2 and 1
SELECT cosine_distance('[1,1]'::vector, '[1.1,1.1]');
cosine_distance
-----------------
0
(1 row)
SELECT cosine_distance('[1,1]'::vector, '[-1.1,-1.1]');
cosine_distance
-----------------
2
(1 row)
SELECT cosine_distance('[3e38]'::vector, '[3e38]');
cosine_distance
-----------------
NaN
(1 row)
SELECT cosine_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[1,2,3,4,5,6,7,8,9]');
cosine_distance
-----------------
0
(1 row)
SELECT cosine_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[-1,-2,-3,-4,-5,-6,-7,-8,-9]');
cosine_distance
-----------------
2
(1 row)
SELECT '[1,2]'::vector <=> '[2,4]';
?column?
----------
0
(1 row)
SELECT l1_distance('[0,0]'::vector, '[3,4]');
l1_distance
-------------
7
(1 row)
SELECT l1_distance('[0,0]'::vector, '[0,1]');
l1_distance
-------------
1
(1 row)
SELECT l1_distance('[1,2]'::vector, '[3]');
ERROR: different vector dimensions 2 and 1
SELECT l1_distance('[3e38]'::vector, '[-3e38]');
l1_distance
-------------
Infinity
(1 row)
SELECT l1_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[1,2,3,4,5,6,7,8,9]');
l1_distance
-------------
0
(1 row)
SELECT l1_distance('[1,2,3,4,5,6,7,8,9]'::vector, '[0,3,2,5,4,7,6,9,8]');
l1_distance
-------------
9
(1 row)
SELECT '[0,0]'::vector <+> '[3,4]';
?column?
----------
7
(1 row)
SELECT l2_normalize('[3,4]'::vector);
l2_normalize
--------------
[0.6,0.8]
(1 row)
SELECT l2_normalize('[3,0]'::vector);
l2_normalize
--------------
[1,0]
(1 row)
SELECT l2_normalize('[0,0.1]'::vector);
l2_normalize
--------------
[0,1]
(1 row)
SELECT l2_normalize('[0,0]'::vector);
l2_normalize
--------------
[0,0]
(1 row)
SELECT l2_normalize('[3e38]'::vector);
l2_normalize
--------------
[1]
(1 row)
SELECT binary_quantize('[1,0,-1]'::vector);
binary_quantize
-----------------
100
(1 row)
SELECT binary_quantize('[0,0.1,-0.2,-0.3,0.4,0.5,0.6,-0.7,0.8,-0.9,1]'::vector);
binary_quantize
-----------------
01001110101
(1 row)
SELECT subvector('[1,2,3,4,5]'::vector, 1, 3);
subvector
-----------
[1,2,3]
(1 row)
SELECT subvector('[1,2,3,4,5]'::vector, 3, 2);
subvector
-----------
[3,4]
(1 row)
SELECT subvector('[1,2,3,4,5]'::vector, -1, 3);
subvector
-----------
[1]
(1 row)
SELECT subvector('[1,2,3,4,5]'::vector, 3, 9);
subvector
-----------
[3,4,5]
(1 row)
SELECT subvector('[1,2,3,4,5]'::vector, 1, 0);
ERROR: vector must have at least 1 dimension
SELECT subvector('[1,2,3,4,5]'::vector, 3, -1);
ERROR: vector must have at least 1 dimension
SELECT subvector('[1,2,3,4,5]'::vector, -1, 2);
ERROR: vector must have at least 1 dimension
SELECT subvector('[1,2,3,4,5]'::vector, 2147483647, 10);
ERROR: vector must have at least 1 dimension
SELECT subvector('[1,2,3,4,5]'::vector, 3, 2147483647);
subvector
-----------
[3,4,5]
(1 row)
SELECT subvector('[1,2,3,4,5]'::vector, -2147483644, 2147483647);
subvector
-----------
[1,2]
(1 row)
SELECT avg(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]']) v;
avg
-----------
[2,3.5,5]
(1 row)
SELECT avg(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
avg
-----------
[2,3.5,5]
(1 row)
SELECT avg(v) FROM unnest(ARRAY[]::vector[]) v;
avg
-----
(1 row)
SELECT avg(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
ERROR: expected 2 dimensions, not 1
SELECT avg(v) FROM unnest(ARRAY['[3e38]'::vector, '[3e38]']) v;
avg
---------
[3e+38]
(1 row)
SELECT vector_avg(array_agg(n)) FROM generate_series(1, 16002) n;
ERROR: vector cannot have more than 16000 dimensions
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]']) v;
sum
----------
[4,7,10]
(1 row)
SELECT sum(v) FROM unnest(ARRAY['[1,2,3]'::vector, '[3,5,7]', NULL]) v;
sum
----------
[4,7,10]
(1 row)
SELECT sum(v) FROM unnest(ARRAY[]::vector[]) v;
sum
-----
(1 row)
SELECT sum(v) FROM unnest(ARRAY['[1,2]'::vector, '[3]']) v;
ERROR: different vector dimensions 2 and 1
SELECT sum(v) FROM unnest(ARRAY['[3e38]'::vector, '[3e38]']) v;
ERROR: value out of range: overflow

View File

@@ -91,7 +91,7 @@ for my $i (0 .. $#operators)
)); ));
# Test approximate results # Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99; my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator); test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;"); $node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -100,7 +100,7 @@ for my $i (0 .. $#operators)
} }
# Test approximate results # Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99; my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator); test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;"); $node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -91,7 +91,7 @@ for my $i (0 .. $#operators)
)); ));
# Test approximate results # Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99; my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator); test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;"); $node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -100,7 +100,7 @@ for my $i (0 .. $#operators)
} }
# Test approximate results # Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99; my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator); test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;"); $node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -1,4 +1,4 @@
comment = 'vector data type and ivfflat and hnsw access methods' comment = 'vector data type and ivfflat and hnsw access methods'
default_version = '0.7.0' default_version = '0.7.2'
module_pathname = '$libdir/vector' module_pathname = '$libdir/vector'
relocatable = true relocatable = true