Compare commits

...

42 Commits

Author SHA1 Message Date
Andrew Kane
103ac50f1a Version bump to 0.7.4 [skip ci] 2024-08-05 10:44:01 -07:00
Andrew Kane
57fb706242 Fixed locking for parallel HNSW index builds - fixes #635 2024-08-04 11:27:51 -07:00
Andrew Kane
020d3edaa9 Changed warnings to errors for TAP tests [skip ci] 2024-07-27 12:28:03 -07:00
Andrew Kane
1e9e355175 Updated TAP tests to use PostgreSQL::Test packages [skip ci] 2024-07-27 12:24:15 -07:00
Andrew Kane
f1d283f565 Updated comment [skip ci] 2024-07-27 11:36:48 -07:00
Andrew Kane
8684c2ba62 Updated formatting [skip ci] 2024-07-27 08:25:09 -07:00
Andrew Kane
6c692ef23f Fixed compilation error with GCC 14 on i386 when SSE2 is not enabled 2024-07-27 06:20:27 -07:00
Andrew Kane
bb424e96e7 Revert "Simplified makefile"
This reverts commit 30911edb7a.
2024-07-24 20:50:14 -07:00
Andrew Kane
30911edb7a Simplified makefile 2024-07-24 20:39:52 -07:00
Andrew Kane
5ae2bd9efb Improved Windows makefile [skip ci] 2024-07-24 20:37:28 -07:00
Andrew Kane
19215317a4 Fixed installation when make is not run before make install on Windows [skip ci] 2024-07-24 02:09:32 -07:00
Andrew Kane
c7ca7f05de Fixed installation when make is not run before make install - closes #631 2024-07-24 01:30:22 -07:00
Andrew Kane
4733cf253b Version bump to 0.7.3 [skip ci] 2024-07-22 09:16:59 -07:00
Andrew Kane
06d1fa1402 Added alignment check to ensure consistency with PageIndexTupleOverwrite 2024-07-19 15:50:24 -07:00
Andrew Kane
8c5a4bfb6c Fixed failed to add index item error with sparsevec - fixes #625 2024-07-19 13:54:36 -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
74 changed files with 1142 additions and 338 deletions

View File

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

View File

@@ -1,3 +1,25 @@
## 0.7.4 (2024-08-05)
- Fixed locking for parallel HNSW index builds
- Fixed compilation error with GCC 14 on i386 when SSE2 is not enabled
## 0.7.3 (2024-07-22)
- Fixed `failed to add index item` error with `sparsevec`
- 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)
- Added `halfvec` type

View File

@@ -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.7.0",
"version": "0.7.4",
"maintainer": [
"Andrew Kane <andrew@ankane.org>"
],
@@ -20,7 +20,7 @@
"vector": {
"file": "sql/vector.sql",
"docfile": "README.md",
"version": "0.7.0",
"version": "0.7.4",
"abstract": "Open-source vector similarity search for Postgres"
}
},

View File

@@ -1,8 +1,9 @@
EXTENSION = vector
EXTVERSION = 0.7.0
EXTVERSION = 0.7.4
MODULE_big = vector
DATA = $(wildcard sql/*--*.sql)
DATA = $(wildcard sql/*--*--*.sql)
DATA_built = sql/$(EXTENSION)--$(EXTVERSION).sql
OBJS = src/bitutils.o src/bitvec.o src/halfutils.o src/halfvec.o src/hnsw.o src/hnswbuild.o src/hnswinsert.o src/hnswscan.o src/hnswutils.o src/hnswvacuum.o src/ivfbuild.o src/ivfflat.o src/ivfinsert.o src/ivfkmeans.o src/ivfscan.o src/ivfutils.o src/ivfvacuum.o src/sparsevec.o src/vector.o
HEADERS = src/halfvec.h src/sparsevec.h src/vector.h
@@ -42,8 +43,6 @@ all: sql/$(EXTENSION)--$(EXTVERSION).sql
sql/$(EXTENSION)--$(EXTVERSION).sql: sql/$(EXTENSION).sql
cp $< $@
EXTRA_CLEAN = sql/$(EXTENSION)--$(EXTVERSION).sql
PG_CONFIG ?= pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
@@ -53,7 +52,7 @@ ifeq ($(PROVE),)
PROVE = prove
endif
# for Postgres 15
# for Postgres < 15
PROVE_FLAGS += -I ./test/perl
prove_installcheck:

View File

@@ -1,10 +1,11 @@
EXTENSION = vector
EXTVERSION = 0.7.0
EXTVERSION = 0.7.4
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
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)
# For /arch flags
@@ -19,11 +20,6 @@ PG_CFLAGS = $(PG_CFLAGS) $(OPTFLAGS) /O2 /fp:fast
# https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/vectorizer-and-parallelizer-messages
# PG_CFLAGS = $(PG_CFLAGS) /Qvec-report:2
all: sql\$(EXTENSION)--$(EXTVERSION).sql
sql\$(EXTENSION)--$(EXTVERSION).sql: sql\$(EXTENSION).sql
copy sql\$(EXTENSION).sql $@
# TODO use pg_config
!ifndef PGROOT
!error PGROOT is not set
@@ -43,15 +39,18 @@ SHLIB = $(EXTENSION).dll
LIBS = "$(LIBDIR)\postgres.lib"
all: $(SHLIB) $(DATA_built)
.c.obj:
$(CC) $(CFLAGS) /c $< /Fo$@
$(SHLIB): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(LIBS) /link /DLL /OUT:$(SHLIB)
all: $(SHLIB)
sql\$(EXTENSION)--$(EXTVERSION).sql: sql\$(EXTENSION).sql
copy sql\$(EXTENSION).sql $@
install:
install: all
copy $(SHLIB) "$(PKGLIBDIR)"
copy $(EXTENSION).control "$(SHAREDIR)\extension"
copy sql\$(EXTENSION)--*.sql "$(SHAREDIR)\extension"
@@ -70,6 +69,6 @@ uninstall:
clean:
del /f $(SHLIB) $(EXTENSION).lib $(EXTENSION).exp
del /f $(DATA_built)
del /f $(OBJS)
del /f sql\$(EXTENSION)--$(EXTVERSION).sql
del /f /s /q results regression.diffs regression.out tmp_check tmp_check_iso log output_iso

View File

@@ -21,7 +21,7 @@ Compile and install the extension (supports Postgres 12+)
```sh
cd /tmp
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git
git clone --branch v0.7.4 https://github.com/pgvector/pgvector.git
cd pgvector
make
make install # may need sudo
@@ -46,7 +46,7 @@ Then use `nmake` to build:
```cmd
set "PGROOT=C:\Program Files\PostgreSQL\16"
cd %TEMP%
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git
git clone --branch v0.7.4 https://github.com/pgvector/pgvector.git
cd pgvector
nmake /F Makefile.win
nmake /F Makefile.win install
@@ -217,6 +217,8 @@ L2 distance
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
```sql
@@ -345,6 +347,8 @@ L2 distance
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
```sql
@@ -455,7 +459,7 @@ CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
*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
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?
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?
@@ -790,7 +794,7 @@ SELECT pg_size_pretty(pg_relation_size('index_name'));
#### 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
-- 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:
```sh
git clone --branch v0.7.0 https://github.com/pgvector/pgvector.git
git clone --branch v0.7.4 https://github.com/pgvector/pgvector.git
cd pgvector
docker build --build-arg PG_MAJOR=16 -t myuser/pgvector .
docker build --pull --build-arg PG_MAJOR=16 -t myuser/pgvector .
```
### 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

@@ -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.3'" 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.4'" to load this file. \quit

View File

@@ -11,7 +11,7 @@
#ifdef BIT_DISPATCH
#include <immintrin.h>
#if defined(HAVE__GET_CPUID)
#if defined(USE__GET_CPUID)
#include <cpuid.h>
#else
#include <intrin.h>
@@ -173,7 +173,7 @@ SupportsAvx512Popcount()
{
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]);
#else
__cpuid(exx, 1);
@@ -187,7 +187,7 @@ SupportsAvx512Popcount()
if ((_xgetbv(0) & 0xe6) != 0xe6)
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]);
#else
__cpuidex(exx, 7, 0);

View File

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

View File

@@ -6,7 +6,7 @@
#ifdef HALFVEC_DISPATCH
#include <immintrin.h>
#if defined(HAVE__GET_CPUID)
#if defined(USE__GET_CPUID)
#include <cpuid.h>
#else
#include <intrin.h>
@@ -254,7 +254,7 @@ SupportsCpuFeature(unsigned int feature)
{
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]);
#else
__cpuid(exx, 1);

View File

@@ -185,7 +185,7 @@ float_underflow_error(void)
/*
* Convert textual representation to internal representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_in);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_in);
Datum
halfvec_in(PG_FUNCTION_ARGS)
{
@@ -299,7 +299,7 @@ halfvec_in(PG_FUNCTION_ARGS)
/*
* Convert internal representation to textual representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_out);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_out);
Datum
halfvec_out(PG_FUNCTION_ARGS)
{
@@ -345,7 +345,7 @@ halfvec_out(PG_FUNCTION_ARGS)
/*
* Convert type modifier
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_typmod_in);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_typmod_in);
Datum
halfvec_typmod_in(PG_FUNCTION_ARGS)
{
@@ -376,7 +376,7 @@ halfvec_typmod_in(PG_FUNCTION_ARGS)
/*
* Convert external binary representation to internal representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_recv);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_recv);
Datum
halfvec_recv(PG_FUNCTION_ARGS)
{
@@ -410,7 +410,7 @@ halfvec_recv(PG_FUNCTION_ARGS)
/*
* Convert internal representation to the external binary representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_send);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_send);
Datum
halfvec_send(PG_FUNCTION_ARGS)
{
@@ -430,7 +430,7 @@ halfvec_send(PG_FUNCTION_ARGS)
* Convert half vector to half vector
* This is needed to check the type modifier
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec);
Datum
halfvec(PG_FUNCTION_ARGS)
{
@@ -445,7 +445,7 @@ halfvec(PG_FUNCTION_ARGS)
/*
* Convert array to half vector
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(array_to_halfvec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(array_to_halfvec);
Datum
array_to_halfvec(PG_FUNCTION_ARGS)
{
@@ -519,7 +519,7 @@ array_to_halfvec(PG_FUNCTION_ARGS)
/*
* Convert half vector to float4[]
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_to_float4);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_float4);
Datum
halfvec_to_float4(PG_FUNCTION_ARGS)
{
@@ -543,7 +543,7 @@ halfvec_to_float4(PG_FUNCTION_ARGS)
/*
* Convert vector to half vec
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_to_halfvec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_halfvec);
Datum
vector_to_halfvec(PG_FUNCTION_ARGS)
{
@@ -565,7 +565,7 @@ vector_to_halfvec(PG_FUNCTION_ARGS)
/*
* 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
halfvec_l2_distance(PG_FUNCTION_ARGS)
{
@@ -580,7 +580,7 @@ halfvec_l2_distance(PG_FUNCTION_ARGS)
/*
* 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
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
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_inner_product);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_inner_product);
Datum
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
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_negative_inner_product);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_negative_inner_product);
Datum
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
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_cosine_distance);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_cosine_distance);
Datum
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
* 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
halfvec_spherical_distance(PG_FUNCTION_ARGS)
{
@@ -681,7 +681,7 @@ halfvec_spherical_distance(PG_FUNCTION_ARGS)
/*
* 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
halfvec_l1_distance(PG_FUNCTION_ARGS)
{
@@ -696,7 +696,7 @@ halfvec_l1_distance(PG_FUNCTION_ARGS)
/*
* 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
halfvec_vector_dims(PG_FUNCTION_ARGS)
{
@@ -708,7 +708,7 @@ halfvec_vector_dims(PG_FUNCTION_ARGS)
/*
* 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
halfvec_l2_norm(PG_FUNCTION_ARGS)
{
@@ -730,7 +730,7 @@ halfvec_l2_norm(PG_FUNCTION_ARGS)
/*
* 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
halfvec_l2_normalize(PG_FUNCTION_ARGS)
{
@@ -769,7 +769,7 @@ halfvec_l2_normalize(PG_FUNCTION_ARGS)
/*
* Add half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_add);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_add);
Datum
halfvec_add(PG_FUNCTION_ARGS)
{
@@ -808,7 +808,7 @@ halfvec_add(PG_FUNCTION_ARGS)
/*
* Subtract half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_sub);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_sub);
Datum
halfvec_sub(PG_FUNCTION_ARGS)
{
@@ -847,7 +847,7 @@ halfvec_sub(PG_FUNCTION_ARGS)
/*
* Multiply half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_mul);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_mul);
Datum
halfvec_mul(PG_FUNCTION_ARGS)
{
@@ -889,7 +889,7 @@ halfvec_mul(PG_FUNCTION_ARGS)
/*
* Concatenate half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_concat);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_concat);
Datum
halfvec_concat(PG_FUNCTION_ARGS)
{
@@ -913,7 +913,7 @@ halfvec_concat(PG_FUNCTION_ARGS)
/*
* Quantize a half vector
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_binary_quantize);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_binary_quantize);
Datum
halfvec_binary_quantize(PG_FUNCTION_ARGS)
{
@@ -931,7 +931,7 @@ halfvec_binary_quantize(PG_FUNCTION_ARGS)
/*
* Get a subvector
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_subvector);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_subvector);
Datum
halfvec_subvector(PG_FUNCTION_ARGS)
{
@@ -1005,7 +1005,7 @@ halfvec_cmp_internal(HalfVector * a, HalfVector * b)
/*
* Less than
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_lt);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_lt);
Datum
halfvec_lt(PG_FUNCTION_ARGS)
{
@@ -1018,7 +1018,7 @@ halfvec_lt(PG_FUNCTION_ARGS)
/*
* Less than or equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_le);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_le);
Datum
halfvec_le(PG_FUNCTION_ARGS)
{
@@ -1031,7 +1031,7 @@ halfvec_le(PG_FUNCTION_ARGS)
/*
* Equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_eq);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_eq);
Datum
halfvec_eq(PG_FUNCTION_ARGS)
{
@@ -1044,7 +1044,7 @@ halfvec_eq(PG_FUNCTION_ARGS)
/*
* Not equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_ne);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_ne);
Datum
halfvec_ne(PG_FUNCTION_ARGS)
{
@@ -1057,7 +1057,7 @@ halfvec_ne(PG_FUNCTION_ARGS)
/*
* Greater than or equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_ge);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_ge);
Datum
halfvec_ge(PG_FUNCTION_ARGS)
{
@@ -1070,7 +1070,7 @@ halfvec_ge(PG_FUNCTION_ARGS)
/*
* Greater than
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_gt);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_gt);
Datum
halfvec_gt(PG_FUNCTION_ARGS)
{
@@ -1083,7 +1083,7 @@ halfvec_gt(PG_FUNCTION_ARGS)
/*
* Compare half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_cmp);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_cmp);
Datum
halfvec_cmp(PG_FUNCTION_ARGS)
{
@@ -1096,7 +1096,7 @@ halfvec_cmp(PG_FUNCTION_ARGS)
/*
* Accumulate half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_accum);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_accum);
Datum
halfvec_accum(PG_FUNCTION_ARGS)
{
@@ -1157,7 +1157,7 @@ halfvec_accum(PG_FUNCTION_ARGS)
/*
* Average half vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_avg);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_avg);
Datum
halfvec_avg(PG_FUNCTION_ARGS)
{
@@ -1191,7 +1191,7 @@ halfvec_avg(PG_FUNCTION_ARGS)
/*
* Convert sparse vector to half vector
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_to_halfvec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_to_halfvec);
Datum
sparsevec_to_halfvec(PG_FUNCTION_ARGS)
{

View File

@@ -9,7 +9,7 @@
/* TODO Move to better place */
#ifndef DISABLE_DISPATCH
/* 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
#elif defined(__x86_64__) && defined(__clang_major__) && __clang_major__ >= 7
#define USE_DISPATCH
@@ -19,9 +19,17 @@
#endif
/* 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
#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)
#define HALFVEC_DISPATCH
@@ -30,7 +38,7 @@
/* F16C has better performance than _Float16 (on x86-64) */
#if defined(__F16C__)
#define F16C_SUPPORT
#elif defined(__FLT16_MAX__) && !defined(HALFVEC_DISPATCH)
#elif defined(__FLT16_MAX__) && !defined(HALFVEC_DISPATCH) && !defined(__FreeBSD__) && (!defined(__i386__) || defined(__SSE2__))
#define FLT16_SUPPORT
#endif

View File

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

View File

@@ -393,7 +393,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);
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 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 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);

View File

@@ -379,7 +379,13 @@ UpdateNeighborsInMemory(char *base, FmgrInfo *procinfo, Oid collation, HnswEleme
for (int lc = e->level; lc >= 0; lc--)
{
int lm = HnswGetLayerM(m, lc);
HnswNeighborArray *neighbors = HnswGetNeighbors(base, e, lc);
Size neighborsSize = HNSW_NEIGHBOR_ARRAY_SIZE(lm);
HnswNeighborArray *neighbors = palloc(neighborsSize);
/* Copy neighbors to local memory */
LWLockAcquire(&e->lock, LW_SHARED);
memcpy(neighbors, HnswGetNeighbors(base, e, lc), neighborsSize);
LWLockRelease(&e->lock);
for (int i = 0; i < neighbors->length; i++)
{
@@ -389,7 +395,6 @@ UpdateNeighborsInMemory(char *base, FmgrInfo *procinfo, Oid collation, HnswEleme
/* Keep scan-build happy on Mac x86-64 */
Assert(neighborElement);
/* Use element for lock instead of hc since hc can be replaced */
LWLockAcquire(&neighborElement->lock, LW_EXCLUSIVE);
HnswUpdateConnection(base, e, hc, lm, lc, NULL, NULL, procinfo, collation);
LWLockRelease(&neighborElement->lock);
@@ -1121,8 +1126,8 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
BuildGraph(buildstate, forkNum);
if (RelationNeedsWAL(index))
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocks(index), true);
if (RelationNeedsWAL(index) || forkNum == INIT_FORKNUM)
log_newpage_range(index, forkNum, 0, RelationGetNumberOfBlocksInFork(index, forkNum), true);
FreeBuildState(buildstate);
}

View File

@@ -36,14 +36,15 @@ GetInsertPage(Relation index)
* Check for a free offset
*/
static bool
HnswFreeOffset(Relation index, Buffer buf, Page page, HnswElement element, Size ntupSize, Buffer *nbuf, Page *npage, OffsetNumber *freeOffno, OffsetNumber *freeNeighborOffno, BlockNumber *newInsertPage)
HnswFreeOffset(Relation index, Buffer buf, Page page, HnswElement element, Size etupSize, Size ntupSize, Buffer *nbuf, Page *npage, OffsetNumber *freeOffno, OffsetNumber *freeNeighborOffno, BlockNumber *newInsertPage)
{
OffsetNumber offno;
OffsetNumber maxoffno = PageGetMaxOffsetNumber(page);
for (offno = FirstOffsetNumber; offno <= maxoffno; offno = OffsetNumberNext(offno))
{
HnswElementTuple etup = (HnswElementTuple) PageGetItem(page, PageGetItemId(page, offno));
ItemId eitemid = PageGetItemId(page, offno);
HnswElementTuple etup = (HnswElementTuple) PageGetItem(page, eitemid);
/* Skip neighbor tuples */
if (!HnswIsElementTuple(etup))
@@ -54,7 +55,9 @@ HnswFreeOffset(Relation index, Buffer buf, Page page, HnswElement element, Size
BlockNumber elementPage = BufferGetBlockNumber(buf);
BlockNumber neighborPage = ItemPointerGetBlockNumber(&etup->neighbortid);
OffsetNumber neighborOffno = ItemPointerGetOffsetNumber(&etup->neighbortid);
ItemId itemid;
ItemId nitemid;
Size pageFree;
Size npageFree;
if (!BlockNumberIsValid(*newInsertPage))
*newInsertPage = elementPage;
@@ -73,10 +76,25 @@ HnswFreeOffset(Relation index, Buffer buf, Page page, HnswElement element, Size
*npage = BufferGetPage(*nbuf);
}
itemid = PageGetItemId(*npage, neighborOffno);
nitemid = PageGetItemId(*npage, neighborOffno);
/* Check for space on neighbor tuple page */
if (PageGetFreeSpace(*npage) + ItemIdGetLength(itemid) - sizeof(ItemIdData) >= ntupSize)
/* Ensure aligned for space check */
Assert(etupSize == MAXALIGN(etupSize));
Assert(ntupSize == MAXALIGN(ntupSize));
/*
* Calculate free space individually since tuples are overwritten
* individually (in separate calls to PageIndexTupleOverwrite)
*/
pageFree = ItemIdGetLength(eitemid) + PageGetExactFreeSpace(page);
npageFree = ItemIdGetLength(nitemid);
if (neighborPage != elementPage)
npageFree += PageGetExactFreeSpace(*npage);
else if (pageFree >= etupSize)
npageFree += pageFree - etupSize;
/* Check for space */
if (pageFree >= etupSize && npageFree >= ntupSize)
{
*freeOffno = offno;
*freeNeighborOffno = neighborOffno;
@@ -184,7 +202,7 @@ AddElementOnDisk(Relation index, HnswElement e, int m, BlockNumber insertPage, B
}
/* Next, try space from a deleted element */
if (HnswFreeOffset(index, buf, page, e, ntupSize, &nbuf, &npage, &freeOffno, &freeNeighborOffno, &newInsertPage))
if (HnswFreeOffset(index, buf, page, e, etupSize, ntupSize, &nbuf, &npage, &freeOffno, &freeNeighborOffno, &newInsertPage))
{
if (nbuf != buf)
{

View File

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

View File

@@ -256,7 +256,7 @@ RepairGraphEntryPoint(HnswVacuumState * vacuumstate)
LockPage(index, HNSW_UPDATE_LOCK, ShareLock);
/* 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 */
if (NeedsUpdated(vacuumstate, highestPoint))
@@ -294,7 +294,7 @@ RepairGraphEntryPoint(HnswVacuumState * vacuumstate)
* is outdated, this can remove connections at higher levels in
* 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))
{

View File

@@ -1006,6 +1006,10 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo);
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);
}

View File

@@ -181,7 +181,7 @@ ivfflatvalidate(Oid opclassoid)
*
* See https://www.postgresql.org/docs/current/index-api.html
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflathandler);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflathandler);
Datum
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);
}
/* Ensure index is valid */
IvfflatGetMetaPageInfo(index, NULL, NULL);
/* Find the insert page - sets the page and list info */
FindInsertPage(index, values, &insertPage, &listInfo);
Assert(BlockNumberIsValid(insertPage));

View File

@@ -170,7 +170,11 @@ IvfflatGetMetaPageInfo(Relation index, int *lists, int *dimensions)
page = BufferGetPage(buf);
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)
*dimensions = metap->dimensions;
@@ -338,7 +342,7 @@ IvfflatGetTypeInfo(Relation index)
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
ivfflat_halfvec_support(PG_FUNCTION_ARGS)
{
@@ -353,7 +357,7 @@ ivfflat_halfvec_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo);
};
PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflat_bit_support);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflat_bit_support);
Datum
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
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_in);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_in);
Datum
sparsevec_in(PG_FUNCTION_ARGS)
{
@@ -409,7 +409,7 @@ sparsevec_in(PG_FUNCTION_ARGS)
/*
* Convert internal representation to textual representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_out);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_out);
Datum
sparsevec_out(PG_FUNCTION_ARGS)
{
@@ -462,7 +462,7 @@ sparsevec_out(PG_FUNCTION_ARGS)
/*
* Convert type modifier
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_typmod_in);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_typmod_in);
Datum
sparsevec_typmod_in(PG_FUNCTION_ARGS)
{
@@ -493,7 +493,7 @@ sparsevec_typmod_in(PG_FUNCTION_ARGS)
/*
* Convert external binary representation to internal representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_recv);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_recv);
Datum
sparsevec_recv(PG_FUNCTION_ARGS)
{
@@ -545,7 +545,7 @@ sparsevec_recv(PG_FUNCTION_ARGS)
/*
* Convert internal representation to the external binary representation
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_send);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_send);
Datum
sparsevec_send(PG_FUNCTION_ARGS)
{
@@ -572,7 +572,7 @@ sparsevec_send(PG_FUNCTION_ARGS)
* Convert sparse vector to sparse vector
* This is needed to check the type modifier
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec);
Datum
sparsevec(PG_FUNCTION_ARGS)
{
@@ -587,7 +587,7 @@ sparsevec(PG_FUNCTION_ARGS)
/*
* Convert dense vector to sparse vector
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_to_sparsevec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_sparsevec);
Datum
vector_to_sparsevec(PG_FUNCTION_ARGS)
{
@@ -630,7 +630,7 @@ vector_to_sparsevec(PG_FUNCTION_ARGS)
/*
* Convert half vector to sparse vector
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(halfvec_to_sparsevec);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_sparsevec);
Datum
halfvec_to_sparsevec(PG_FUNCTION_ARGS)
{
@@ -721,7 +721,7 @@ SparsevecL2SquaredDistance(SparseVector * a, SparseVector * b)
/*
* 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
sparsevec_l2_distance(PG_FUNCTION_ARGS)
{
@@ -737,7 +737,7 @@ sparsevec_l2_distance(PG_FUNCTION_ARGS)
* Get the L2 squared distance between sparse vectors
* 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
sparsevec_l2_squared_distance(PG_FUNCTION_ARGS)
{
@@ -788,7 +788,7 @@ SparsevecInnerProduct(SparseVector * a, SparseVector * b)
/*
* 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
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
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_negative_inner_product);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_negative_inner_product);
Datum
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
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_cosine_distance);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_cosine_distance);
Datum
sparsevec_cosine_distance(PG_FUNCTION_ARGS)
{
@@ -863,7 +863,7 @@ sparsevec_cosine_distance(PG_FUNCTION_ARGS)
/*
* 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
sparsevec_l1_distance(PG_FUNCTION_ARGS)
{
@@ -912,7 +912,7 @@ sparsevec_l1_distance(PG_FUNCTION_ARGS)
/*
* 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
sparsevec_l2_norm(PG_FUNCTION_ARGS)
{
@@ -930,7 +930,7 @@ sparsevec_l2_norm(PG_FUNCTION_ARGS)
/*
* 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
sparsevec_l2_normalize(PG_FUNCTION_ARGS)
{
@@ -1040,7 +1040,7 @@ sparsevec_cmp_internal(SparseVector * a, SparseVector * b)
/*
* Less than
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_lt);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_lt);
Datum
sparsevec_lt(PG_FUNCTION_ARGS)
{
@@ -1053,7 +1053,7 @@ sparsevec_lt(PG_FUNCTION_ARGS)
/*
* Less than or equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_le);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_le);
Datum
sparsevec_le(PG_FUNCTION_ARGS)
{
@@ -1066,7 +1066,7 @@ sparsevec_le(PG_FUNCTION_ARGS)
/*
* Equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_eq);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_eq);
Datum
sparsevec_eq(PG_FUNCTION_ARGS)
{
@@ -1079,7 +1079,7 @@ sparsevec_eq(PG_FUNCTION_ARGS)
/*
* Not equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_ne);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_ne);
Datum
sparsevec_ne(PG_FUNCTION_ARGS)
{
@@ -1092,7 +1092,7 @@ sparsevec_ne(PG_FUNCTION_ARGS)
/*
* Greater than or equal
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_ge);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_ge);
Datum
sparsevec_ge(PG_FUNCTION_ARGS)
{
@@ -1105,7 +1105,7 @@ sparsevec_ge(PG_FUNCTION_ARGS)
/*
* Greater than
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_gt);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_gt);
Datum
sparsevec_gt(PG_FUNCTION_ARGS)
{
@@ -1118,7 +1118,7 @@ sparsevec_gt(PG_FUNCTION_ARGS)
/*
* Compare sparse vectors
*/
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_cmp);
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_cmp);
Datum
sparsevec_cmp(PG_FUNCTION_ARGS)
{

View File

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

View File

@@ -20,4 +20,11 @@ Vector *InitVector(int dim);
void PrintVector(char *msg, Vector * vector);
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

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

@@ -0,0 +1,11 @@
package PostgreSQL::Test::Cluster;
use PostgresNode;
sub new
{
my ($class, $name) = @_;
return get_new_node($name);
}
1;

View File

@@ -0,0 +1,5 @@
package PostgreSQL::Test::Utils;
use TestLib;
1;

View File

@@ -1,8 +0,0 @@
use PostgreSQL::Test::Cluster;
sub get_new_node
{
return PostgreSQL::Test::Cluster->new(@_);
}
1;

View File

@@ -1,3 +0,0 @@
use PostgreSQL::Test::Utils;
1;

View File

@@ -2,9 +2,9 @@
# Test generic xlog record work for ivfflat index replication.
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 32;
@@ -49,7 +49,7 @@ sub test_index_replay
my $array_sql = join(",", ('random()') x $dim);
# Initialize primary node
$node_primary = get_new_node('primary');
$node_primary = PostgreSQL::Test::Cluster->new('primary');
$node_primary->init(allows_streaming => 1);
if ($dim > 32)
{
@@ -67,7 +67,7 @@ my $backup_name = 'my_backup';
$node_primary->backup($backup_name);
# Create streaming replica linking to primary
$node_replica = get_new_node('replica');
$node_replica = PostgreSQL::Test::Cluster->new('replica');
$node_replica->init_from_backup($node_primary, $backup_name, has_streaming => 1);
$node_replica->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 3;
@@ -15,7 +15,7 @@ for (1 .. $dim)
my $array_sql = join(", ", @r);
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -49,7 +49,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -48,7 +48,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 768;
@@ -9,7 +9,7 @@ my $dim = 768;
my $array_sql = join(",", ('random()') x $dim);
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 3;
@@ -11,7 +11,7 @@ my $limit = 20;
my $array_sql = join(",", ('random()') x $dim);
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -2,9 +2,9 @@
# Test generic xlog record work for hnsw index replication.
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 32;
@@ -49,7 +49,7 @@ sub test_index_replay
my $array_sql = join(",", ('random()') x $dim);
# Initialize primary node
$node_primary = get_new_node('primary');
$node_primary = PostgreSQL::Test::Cluster->new('primary');
$node_primary->init(allows_streaming => 1);
if ($dim > 32)
{
@@ -67,7 +67,7 @@ my $backup_name = 'my_backup';
$node_primary->backup($backup_name);
# Create streaming replica linking to primary
$node_replica = get_new_node('replica');
$node_replica = PostgreSQL::Test::Cluster->new('replica');
$node_replica->init_from_backup($node_primary, $backup_name, has_streaming => 1);
$node_replica->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 3;
@@ -15,7 +15,7 @@ for (1 .. $dim)
my $array_sql = join(", ", @r);
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -47,7 +47,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;
@@ -91,7 +91,7 @@ for my $i (0 .. $#operators)
));
# Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99;
my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -47,7 +47,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;
@@ -100,7 +100,7 @@ for my $i (0 .. $#operators)
}
# Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99;
my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -48,7 +48,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Ensures elements and neighbors on both same and different pages
@@ -10,7 +10,7 @@ my $dim = 1900;
my $array_sql = join(",", ('random()') x $dim);
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 3;
@@ -11,7 +11,7 @@ my $limit = 20;
my $array_sql = join(",", ('random()') x $dim);
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;
@@ -53,7 +53,7 @@ sub test_aggregate
else
{
# Does not raise overflow error in this instance due to loss of precision
is($res, "[24576,24576,49152]")
is($res, "[24576,24576,49152]");
}
}

View File

@@ -1,13 +1,13 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $dim = 1024;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -51,7 +51,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -51,7 +51,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -51,7 +51,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -48,7 +48,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -48,7 +48,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -48,7 +48,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -47,7 +47,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;
@@ -91,7 +91,7 @@ for my $i (0 .. $#operators)
));
# Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99;
my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -47,7 +47,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;
@@ -100,7 +100,7 @@ for my $i (0 .. $#operators)
}
# Test approximate results
my $min = $operator eq "<#>" ? 0.98 : 0.99;
my $min = $operator eq "<#>" ? 0.97 : 0.99;
test_recall($min, $operator);
$node->safe_psql("postgres", "DROP INDEX idx;");

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -48,7 +48,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -51,7 +51,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,14 +1,14 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
my $array_sql = join(",", ('floor(random() * 2)::int - 1') x 3);
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -10,7 +10,7 @@ my $dim = 5;
my $array_sql = join(",", ('floor(random() * 4)::int - 2') x $dim);
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,7 +1,7 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
my $node;
@@ -51,7 +51,7 @@ sub test_recall
}
# Initialize node
$node = get_new_node('node');
$node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -1,11 +1,11 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use warnings FATAL => 'all';
use PostgreSQL::Test::Cluster;
use PostgreSQL::Test::Utils;
use Test::More;
# Initialize node
my $node = get_new_node('node');
my $node = PostgreSQL::Test::Cluster->new('node');
$node->init;
$node->start;

View File

@@ -0,0 +1,42 @@
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 and index
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
$node->safe_psql("postgres", "CREATE TABLE tst (i serial, v sparsevec(100000));");
$node->safe_psql("postgres", "CREATE INDEX ON tst USING hnsw (v sparsevec_l2_ops);");
for (1 .. 3)
{
for (1 .. 100)
{
my @elements;
my %indices;
for (1 .. int(rand() * 100))
{
my $index = int(rand() * (100000 - 1)) + 1;
if (!exists($indices{$index}))
{
my $value = rand();
push(@elements, "$index:$value");
$indices{$index} = 1;
}
}
my $embedding = "{" . join(",", @elements) . "}/100000";
$node->safe_psql("postgres", "INSERT INTO tst (v) VALUES ('$embedding');");
}
$node->safe_psql("postgres", "DELETE FROM tst WHERE i % 2 = 0;");
$node->safe_psql("postgres", "VACUUM tst;");
is(1, 1);
}
done_testing();

View File

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