Compare commits

..

2 Commits

Author SHA1 Message Date
Andrew Kane
0ff9f6511a Use f32 [skip ci] 2024-04-27 23:02:00 -07:00
Andrew Kane
17855c9861 Started Neon intrinsics [skip ci] 2024-04-27 22:50:47 -07:00
74 changed files with 424 additions and 1209 deletions

View File

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

View File

@@ -1,26 +1,4 @@
## 0.7.4 (2024-08-05) ## 0.7.0 (unreleased)
- 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 - Added `halfvec` type
- Added `sparsevec` type - Added `sparsevec` 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.4", "version": "0.6.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.4", "version": "0.6.2",
"abstract": "Open-source vector similarity search for Postgres" "abstract": "Open-source vector similarity search for Postgres"
} }
}, },

View File

@@ -1,9 +1,8 @@
EXTENSION = vector EXTENSION = vector
EXTVERSION = 0.7.4 EXTVERSION = 0.6.2
MODULE_big = vector 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 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 HEADERS = src/halfvec.h src/sparsevec.h src/vector.h
@@ -43,6 +42,8 @@ all: sql/$(EXTENSION)--$(EXTVERSION).sql
sql/$(EXTENSION)--$(EXTVERSION).sql: sql/$(EXTENSION).sql sql/$(EXTENSION)--$(EXTVERSION).sql: sql/$(EXTENSION).sql
cp $< $@ cp $< $@
EXTRA_CLEAN = sql/$(EXTENSION)--$(EXTVERSION).sql
PG_CONFIG ?= pg_config PG_CONFIG ?= pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs) PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS) include $(PGXS)
@@ -52,7 +53,7 @@ ifeq ($(PROVE),)
PROVE = prove PROVE = prove
endif endif
# for Postgres < 15 # for Postgres 15
PROVE_FLAGS += -I ./test/perl PROVE_FLAGS += -I ./test/perl
prove_installcheck: prove_installcheck:

View File

@@ -1,11 +1,10 @@
EXTENSION = vector EXTENSION = vector
EXTVERSION = 0.7.4 EXTVERSION = 0.6.2
DATA_built = sql\$(EXTENSION)--$(EXTVERSION).sql
OBJS = src\bitutils.obj src\bitvec.obj src\halfutils.obj src\halfvec.obj src\hnsw.obj src\hnswbuild.obj src\hnswinsert.obj src\hnswscan.obj src\hnswutils.obj src\hnswvacuum.obj src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\sparsevec.obj src\vector.obj 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_type REGRESS = bit btree cast copy halfvec hnsw_bit hnsw_halfvec hnsw_sparsevec hnsw_vector ivfflat_bit ivfflat_halfvec ivfflat_vector sparsevec vector
REGRESS_OPTS = --inputdir=test --load-extension=$(EXTENSION) REGRESS_OPTS = --inputdir=test --load-extension=$(EXTENSION)
# For /arch flags # For /arch flags
@@ -20,6 +19,11 @@ PG_CFLAGS = $(PG_CFLAGS) $(OPTFLAGS) /O2 /fp:fast
# https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/vectorizer-and-parallelizer-messages # https://learn.microsoft.com/en-us/cpp/error-messages/tool-errors/vectorizer-and-parallelizer-messages
# PG_CFLAGS = $(PG_CFLAGS) /Qvec-report:2 # 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 # TODO use pg_config
!ifndef PGROOT !ifndef PGROOT
!error PGROOT is not set !error PGROOT is not set
@@ -39,18 +43,15 @@ SHLIB = $(EXTENSION).dll
LIBS = "$(LIBDIR)\postgres.lib" LIBS = "$(LIBDIR)\postgres.lib"
all: $(SHLIB) $(DATA_built)
.c.obj: .c.obj:
$(CC) $(CFLAGS) /c $< /Fo$@ $(CC) $(CFLAGS) /c $< /Fo$@
$(SHLIB): $(OBJS) $(SHLIB): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(LIBS) /link /DLL /OUT:$(SHLIB) $(CC) $(CFLAGS) $(OBJS) $(LIBS) /link /DLL /OUT:$(SHLIB)
sql\$(EXTENSION)--$(EXTVERSION).sql: sql\$(EXTENSION).sql all: $(SHLIB)
copy sql\$(EXTENSION).sql $@
install: all install:
copy $(SHLIB) "$(PKGLIBDIR)" copy $(SHLIB) "$(PKGLIBDIR)"
copy $(EXTENSION).control "$(SHAREDIR)\extension" copy $(EXTENSION).control "$(SHAREDIR)\extension"
copy sql\$(EXTENSION)--*.sql "$(SHAREDIR)\extension" copy sql\$(EXTENSION)--*.sql "$(SHAREDIR)\extension"
@@ -69,6 +70,6 @@ uninstall:
clean: clean:
del /f $(SHLIB) $(EXTENSION).lib $(EXTENSION).exp del /f $(SHLIB) $(EXTENSION).lib $(EXTENSION).exp
del /f $(DATA_built)
del /f $(OBJS) 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 del /f /s /q results regression.diffs regression.out tmp_check tmp_check_iso log output_iso

147
README.md
View File

@@ -5,8 +5,7 @@ Open-source vector similarity search for Postgres
Store your vectors with the rest of your data. Supports: Store your vectors with the rest of your data. Supports:
- exact and approximate nearest neighbor search - exact and approximate nearest neighbor search
- single-precision, half-precision, binary, and sparse vectors - L2 distance, inner product, and cosine distance
- L2 distance, inner product, cosine distance, L1 distance, Hamming distance, and Jaccard distance
- any [language](#languages) with a Postgres client - any [language](#languages) with a Postgres client
Plus [ACID](https://en.wikipedia.org/wiki/ACID) compliance, point-in-time recovery, JOINs, and all of the other [great features](https://www.postgresql.org/about/) of Postgres Plus [ACID](https://en.wikipedia.org/wiki/ACID) compliance, point-in-time recovery, JOINs, and all of the other [great features](https://www.postgresql.org/about/) of Postgres
@@ -21,7 +20,7 @@ Compile and install the extension (supports Postgres 12+)
```sh ```sh
cd /tmp cd /tmp
git clone --branch v0.7.4 https://github.com/pgvector/pgvector.git git clone --branch v0.6.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 +45,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.4 https://github.com/pgvector/pgvector.git git clone --branch v0.6.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
@@ -82,7 +81,7 @@ Get the nearest neighbors by L2 distance
SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5; SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;
``` ```
Also supports inner product (`<#>`), cosine distance (`<=>`), and L1 distance (`<+>`, added in 0.7.0) Also supports inner product (`<#>`), cosine distance (`<=>`), and L1 distance (`<+>`, unreleased)
Note: `<#>` returns the negative inner product since Postgres only supports `ASC` order index scans on operators Note: `<#>` returns the negative inner product since Postgres only supports `ASC` order index scans on operators
@@ -144,7 +143,7 @@ Supported distance functions are:
- `<->` - L2 distance - `<->` - L2 distance
- `<#>` - (negative) inner product - `<#>` - (negative) inner product
- `<=>` - cosine distance - `<=>` - cosine distance
- `<+>` - L1 distance (added in 0.7.0) - `<+>` - L1 distance (unreleased)
Get the nearest neighbors to a row Get the nearest neighbors to a row
@@ -217,8 +216,6 @@ 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
@@ -231,19 +228,19 @@ Cosine distance
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops); CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
``` ```
L1 distance - added in 0.7.0 L1 distance - unreleased
```sql ```sql
CREATE INDEX ON items USING hnsw (embedding vector_l1_ops); CREATE INDEX ON items USING hnsw (embedding vector_l1_ops);
``` ```
Hamming distance - added in 0.7.0 Hamming distance - unreleased
```sql ```sql
CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops); CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops);
``` ```
Jaccard distance - added in 0.7.0 Jaccard distance - unreleased
```sql ```sql
CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops); CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
@@ -252,9 +249,9 @@ CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);
Supported types are: Supported types are:
- `vector` - up to 2,000 dimensions - `vector` - up to 2,000 dimensions
- `halfvec` - up to 4,000 dimensions (added in 0.7.0) - `halfvec` - up to 4,000 dimensions (unreleased)
- `bit` - up to 64,000 dimensions (added in 0.7.0) - `bit` - up to 64,000 dimensions (unreleased)
- `sparsevec` - up to 1,000 non-zero elements (added in 0.7.0) - `sparsevec` - up to 1,000 non-zero elements (unreleased)
### Index Options ### Index Options
@@ -347,8 +344,6 @@ 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
@@ -361,7 +356,7 @@ Cosine distance
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100); CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
``` ```
Hamming distance - added in 0.7.0 Hamming distance - unreleased
```sql ```sql
CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 100); CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 100);
@@ -370,8 +365,8 @@ CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 10
Supported types are: Supported types are:
- `vector` - up to 2,000 dimensions - `vector` - up to 2,000 dimensions
- `halfvec` - up to 4,000 dimensions (added in 0.7.0) - `halfvec` - up to 4,000 dimensions (unreleased)
- `bit` - up to 64,000 dimensions (added in 0.7.0) - `bit` - up to 64,000 dimensions (unreleased)
### Query Options ### Query Options
@@ -445,9 +440,9 @@ Use [partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html
CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id); CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id);
``` ```
## Half-Precision Vectors ## Half Vectors
*Added in 0.7.0* *Unreleased*
Use the `halfvec` type to store half-precision vectors Use the `halfvec` type to store half-precision vectors
@@ -455,11 +450,11 @@ Use the `halfvec` type to store half-precision vectors
CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3)); CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));
``` ```
## Half-Precision Indexing ## Half Indexing
*Added in 0.7.0* *Unreleased*
Index vectors at half precision for smaller indexes Index vectors at half precision for smaller indexes and faster build times
```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);
@@ -480,23 +475,23 @@ CREATE TABLE items (id bigserial PRIMARY KEY, embedding bit(3));
INSERT INTO items (embedding) VALUES ('000'), ('111'); INSERT INTO items (embedding) VALUES ('000'), ('111');
``` ```
Get the nearest neighbors by Hamming distance (added in 0.7.0) Get the nearest neighbors by Hamming distance
```sql
SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;
```
Or (before 0.7.0)
```sql ```sql
SELECT * FROM items ORDER BY bit_count(embedding # '101') LIMIT 5; SELECT * FROM items ORDER BY bit_count(embedding # '101') LIMIT 5;
``` ```
Or (unreleased)
```sql
SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;
```
Also supports Jaccard distance (`<%>`) Also supports Jaccard distance (`<%>`)
## Binary Quantization ## Binary Quantization
*Added in 0.7.0* *Unreleased*
Use expression indexing for binary quantization Use expression indexing for binary quantization
@@ -520,7 +515,7 @@ SELECT * FROM (
## Sparse Vectors ## Sparse Vectors
*Added in 0.7.0* *Unreleased*
Use the `sparsevec` type to store sparse vectors Use the `sparsevec` type to store sparse vectors
@@ -555,7 +550,7 @@ You can use [Reciprocal Rank Fusion](https://github.com/pgvector/pgvector-python
## Indexing Subvectors ## Indexing Subvectors
*Added in 0.7.0* *Unreleased*
Use expression indexing to index subvectors Use expression indexing to index subvectors
@@ -731,7 +726,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?
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). Youll need to use [dimensionality reduction](https://en.wikipedia.org/wiki/Dimensionality_reduction) at the moment.
#### Can I store vectors with different dimensions in the same column? #### Can I store vectors with different dimensions in the same column?
@@ -794,7 +789,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) in ascending order. 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.
```sql ```sql
-- index -- index
@@ -869,23 +864,23 @@ Operator | Description | Added
\+ | element-wise addition | \+ | element-wise addition |
\- | element-wise subtraction | \- | element-wise subtraction |
\* | element-wise multiplication | 0.5.0 \* | element-wise multiplication | 0.5.0
\|\| | concatenate | 0.7.0 \|\| | concatenate | unreleased
<-> | Euclidean distance | <-> | Euclidean distance |
<#> | negative inner product | <#> | negative inner product |
<=> | cosine distance | <=> | cosine distance |
<+> | taxicab distance | 0.7.0 <+> | taxicab distance | unreleased
### Vector Functions ### Vector Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
binary_quantize(vector) → bit | binary quantize | 0.7.0 binary_quantize(vector) → bit | binary quantize | unreleased
cosine_distance(vector, vector) → double precision | cosine distance | cosine_distance(vector, vector) → double precision | cosine distance |
inner_product(vector, vector) → double precision | inner product | inner_product(vector, vector) → double precision | inner product |
l1_distance(vector, vector) → double precision | taxicab distance | 0.5.0 l1_distance(vector, vector) → double precision | taxicab distance | 0.5.0
l2_distance(vector, vector) → double precision | Euclidean distance | l2_distance(vector, vector) → double precision | Euclidean distance |
l2_normalize(vector) → vector | Normalize with Euclidean norm | 0.7.0 l2_normalize(vector) → vector | Normalize with Euclidean norm | unreleased
subvector(vector, integer, integer) → vector | subvector | 0.7.0 subvector(vector, integer, integer) → vector | subvector | unreleased
vector_dims(vector) → integer | number of dimensions | vector_dims(vector) → integer | number of dimensions |
vector_norm(vector) → double precision | Euclidean norm | vector_norm(vector) → double precision | Euclidean norm |
@@ -904,35 +899,35 @@ Each half vector takes `2 * dimensions + 8` bytes of storage. Each element is a
Operator | Description | Added Operator | Description | Added
--- | --- | --- --- | --- | ---
\+ | element-wise addition | 0.7.0 \+ | element-wise addition | unreleased
\- | element-wise subtraction | 0.7.0 \- | element-wise subtraction | unreleased
\* | element-wise multiplication | 0.7.0 \* | element-wise multiplication | unreleased
\|\| | concatenate | 0.7.0 \|\| | concatenate | unreleased
<-> | Euclidean distance | 0.7.0 <-> | Euclidean distance | unreleased
<#> | negative inner product | 0.7.0 <#> | negative inner product | unreleased
<=> | cosine distance | 0.7.0 <=> | cosine distance | unreleased
<+> | taxicab distance | 0.7.0 <+> | taxicab distance | unreleased
### Halfvec Functions ### Halfvec Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
binary_quantize(halfvec) → bit | binary quantize | 0.7.0 binary_quantize(halfvec) → bit | binary quantize | unreleased
cosine_distance(halfvec, halfvec) → double precision | cosine distance | 0.7.0 cosine_distance(halfvec, halfvec) → double precision | cosine distance | unreleased
inner_product(halfvec, halfvec) → double precision | inner product | 0.7.0 inner_product(halfvec, halfvec) → double precision | inner product | unreleased
l1_distance(halfvec, halfvec) → double precision | taxicab distance | 0.7.0 l1_distance(halfvec, halfvec) → double precision | taxicab distance | unreleased
l2_distance(halfvec, halfvec) → double precision | Euclidean distance | 0.7.0 l2_distance(halfvec, halfvec) → double precision | Euclidean distance | unreleased
l2_norm(halfvec) → double precision | Euclidean norm | 0.7.0 l2_norm(halfvec) → double precision | Euclidean norm | unreleased
l2_normalize(halfvec) → halfvec | Normalize with Euclidean norm | 0.7.0 l2_normalize(halfvec) → halfvec | Normalize with Euclidean norm | unreleased
subvector(halfvec, integer, integer) → halfvec | subvector | 0.7.0 subvector(halfvec, integer, integer) → halfvec | subvector | unreleased
vector_dims(halfvec) → integer | number of dimensions | 0.7.0 vector_dims(halfvec) → integer | number of dimensions | unreleased
### Halfvec Aggregate Functions ### Halfvec Aggregate Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
avg(halfvec) → halfvec | average | 0.7.0 avg(halfvec) → halfvec | average | unreleased
sum(halfvec) → halfvec | sum | 0.7.0 sum(halfvec) → halfvec | sum | unreleased
### Bit Type ### Bit Type
@@ -942,15 +937,15 @@ Each bit vector takes `dimensions / 8 + 8` bytes of storage. See the [Postgres d
Operator | Description | Added Operator | Description | Added
--- | --- | --- --- | --- | ---
<~> | Hamming distance | 0.7.0 <~> | Hamming distance | unreleased
<%> | Jaccard distance | 0.7.0 <%> | Jaccard distance | unreleased
### Bit Functions ### Bit Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
hamming_distance(bit, bit) → double precision | Hamming distance | 0.7.0 hamming_distance(bit, bit) → double precision | Hamming distance | unreleased
jaccard_distance(bit, bit) → double precision | Jaccard distance | 0.7.0 jaccard_distance(bit, bit) → double precision | Jaccard distance | unreleased
### Sparsevec Type ### Sparsevec Type
@@ -960,21 +955,21 @@ Each sparse vector takes `8 * non-zero elements + 16` bytes of storage. Each ele
Operator | Description | Added Operator | Description | Added
--- | --- | --- --- | --- | ---
<-> | Euclidean distance | 0.7.0 <-> | Euclidean distance | unreleased
<#> | negative inner product | 0.7.0 <#> | negative inner product | unreleased
<=> | cosine distance | 0.7.0 <=> | cosine distance | unreleased
<+> | taxicab distance | 0.7.0 <+> | taxicab distance | unreleased
### Sparsevec Functions ### Sparsevec Functions
Function | Description | Added Function | Description | Added
--- | --- | --- --- | --- | ---
cosine_distance(sparsevec, sparsevec) → double precision | cosine distance | 0.7.0 cosine_distance(sparsevec, sparsevec) → double precision | cosine distance | unreleased
inner_product(sparsevec, sparsevec) → double precision | inner product | 0.7.0 inner_product(sparsevec, sparsevec) → double precision | inner product | unreleased
l1_distance(sparsevec, sparsevec) → double precision | taxicab distance | 0.7.0 l1_distance(sparsevec, sparsevec) → double precision | taxicab distance | unreleased
l2_distance(sparsevec, sparsevec) → double precision | Euclidean distance | 0.7.0 l2_distance(sparsevec, sparsevec) → double precision | Euclidean distance | unreleased
l2_norm(sparsevec) → double precision | Euclidean norm | 0.7.0 l2_norm(sparsevec) → double precision | Euclidean norm | unreleased
l2_normalize(sparsevec) → sparsevec | Normalize with Euclidean norm | 0.7.0 l2_normalize(sparsevec) → sparsevec | Normalize with Euclidean norm | unreleased
## Installation Notes - Linux and Mac ## Installation Notes - Linux and Mac
@@ -1051,9 +1046,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.4 https://github.com/pgvector/pgvector.git git clone --branch v0.6.2 https://github.com/pgvector/pgvector.git
cd pgvector cd pgvector
docker build --pull --build-arg PG_MAJOR=16 -t myuser/pgvector . docker build --build-arg PG_MAJOR=16 -t myuser/pgvector .
``` ```
### Homebrew ### Homebrew

View File

@@ -1,2 +0,0 @@
-- 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

@@ -1,2 +0,0 @@
-- 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

@@ -1,2 +0,0 @@
-- 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

@@ -1,2 +0,0 @@
-- 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 #ifdef BIT_DISPATCH
#include <immintrin.h> #include <immintrin.h>
#if defined(USE__GET_CPUID) #if defined(HAVE__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(USE__GET_CPUID) #if defined(HAVE__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(USE__GET_CPUID) #if defined(HAVE__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,7 +3,6 @@
#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"
@@ -41,7 +40,7 @@ CheckDims(VarBit *a, VarBit *b)
/* /*
* Get the Hamming distance between two bit vectors * Get the Hamming distance between two bit vectors
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hamming_distance); PGDLLEXPORT PG_FUNCTION_INFO_V1(hamming_distance);
Datum Datum
hamming_distance(PG_FUNCTION_ARGS) hamming_distance(PG_FUNCTION_ARGS)
{ {
@@ -56,7 +55,7 @@ hamming_distance(PG_FUNCTION_ARGS)
/* /*
* Get the Jaccard distance between two bit vectors * Get the Jaccard distance between two bit vectors
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(jaccard_distance); PGDLLEXPORT PG_FUNCTION_INFO_V1(jaccard_distance);
Datum Datum
jaccard_distance(PG_FUNCTION_ARGS) jaccard_distance(PG_FUNCTION_ARGS)
{ {

View File

@@ -1,12 +1,14 @@
#include "postgres.h" #include "postgres.h"
#include <arm_neon.h>
#include "halfutils.h" #include "halfutils.h"
#include "halfvec.h" #include "halfvec.h"
#ifdef HALFVEC_DISPATCH #ifdef HALFVEC_DISPATCH
#include <immintrin.h> #include <immintrin.h>
#if defined(USE__GET_CPUID) #if defined(HAVE__GET_CPUID)
#include <cpuid.h> #include <cpuid.h>
#else #else
#include <intrin.h> #include <intrin.h>
@@ -28,9 +30,27 @@ static float
HalfvecL2SquaredDistanceDefault(int dim, half * ax, half * bx) HalfvecL2SquaredDistanceDefault(int dim, half * ax, half * bx)
{ {
float distance = 0.0; float distance = 0.0;
int i = 0;
/* TODO Improve */
#ifdef __ARM_FEATURE_FP16_VECTOR_ARITHMETIC
int count = (dim / 4) * 4;
float32x4_t dist = vmovq_n_f32(0);
for (; i < count; i += 4)
{
float16x4_t axs = vld1_f16((const __fp16 *) (ax + i));
float16x4_t bxs = vld1_f16((const __fp16 *) (bx + i));
float32x4_t diff = vsubq_f32(vcvt_f32_f16(axs), vcvt_f32_f16(bxs));
dist = vfmaq_f32(dist, diff, diff);
}
distance += vaddvq_f32(dist);
#endif
/* Auto-vectorized */ /* Auto-vectorized */
for (int i = 0; i < dim; i++) for (; i < dim; i++)
{ {
float diff = HalfToFloat4(ax[i]) - HalfToFloat4(bx[i]); float diff = HalfToFloat4(ax[i]) - HalfToFloat4(bx[i]);
@@ -254,7 +274,7 @@ SupportsCpuFeature(unsigned int feature)
{ {
unsigned int exx[4] = {0, 0, 0, 0}; unsigned int exx[4] = {0, 0, 0, 0};
#if defined(USE__GET_CPUID) #if defined(HAVE__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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_in); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_out); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_typmod_in); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_recv); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_send); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(array_to_halfvec); PGDLLEXPORT 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[]
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_float4); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_halfvec); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_squared_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_inner_product); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_negative_inner_product); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_cosine_distance); PGDLLEXPORT 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)
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_spherical_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l1_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_vector_dims); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_norm); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_l2_normalize); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_add); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_sub); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_mul); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_concat); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_binary_quantize); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_subvector); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_lt); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_le); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_eq); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_ne); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_ge); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_gt); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_cmp); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_accum); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_avg); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_to_halfvec); PGDLLEXPORT 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__ >= 9 #if defined(__x86_64__) && defined(__GNUC__) && __GNUC__ >= 8
#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,17 +19,9 @@
#endif #endif
/* target_clones requires glibc */ /* target_clones requires glibc */
#if defined(USE_DISPATCH) && defined(__gnu_linux__) && defined(__has_attribute) #if defined(USE_DISPATCH) && defined(__gnu_linux__)
/* 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
@@ -38,7 +30,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) && !defined(__FreeBSD__) && (!defined(__i386__) || defined(__SSE2__)) #elif defined(__FLT16_MAX__) && !defined(HALFVEC_DISPATCH)
#define FLT16_SUPPORT #define FLT16_SUPPORT
#endif #endif

View File

@@ -187,7 +187,7 @@ hnswvalidate(Oid opclassoid)
* *
* See https://www.postgresql.org/docs/current/index-api.html * See https://www.postgresql.org/docs/current/index-api.html
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnswhandler); PGDLLEXPORT PG_FUNCTION_INFO_V1(hnswhandler);
Datum Datum
hnswhandler(PG_FUNCTION_ARGS) 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); 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, float *maxDistance); void HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec);
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

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

View File

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

View File

@@ -300,9 +300,6 @@ 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;
@@ -548,7 +545,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, float *maxDistance) HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index, FmgrInfo *procinfo, Oid collation, bool loadVec)
{ {
Buffer buf; Buffer buf;
Page page; Page page;
@@ -563,6 +560,9 @@ 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,10 +572,6 @@ 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);
} }
@@ -603,7 +599,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, NULL); HnswLoadElement(entryPoint, &hc->distance, &q, index, procinfo, collation, loadVec);
return hc; return hc;
} }
@@ -799,27 +795,25 @@ 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;
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, alwaysAdd ? NULL : &f->distance); HnswLoadElement(eElement, &eDistance, &q, index, procinfo, collation, inserting);
if (eDistance < f->distance || alwaysAdd) Assert(!eElement->deleted);
/* Make robust to issues */
if (eElement->level < lc)
continue;
if (eDistance < f->distance || wlen < ef)
{ {
HnswCandidate *ec;
Assert(!eElement->deleted);
/* Make robust to issues */
if (eElement->level < lc)
continue;
/* Copy e */ /* Copy e */
ec = palloc(sizeof(HnswCandidate)); HnswCandidate *ec = palloc(sizeof(HnswCandidate));
HnswPtrStore(base, ec->element, eElement); HnswPtrStore(base, ec->element, eElement);
ec->distance = eDistance; ec->distance = eDistance;
@@ -1108,7 +1102,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, NULL); HnswLoadElement(hc3Element, &hc3->distance, &q, index, procinfo, collation, true);
else else
hc3->distance = GetCandidateDistance(base, hc3, q, procinfo, collation); hc3->distance = GetCandidateDistance(base, hc3, q, procinfo, collation);
@@ -1305,7 +1299,7 @@ HnswGetTypeInfo(Relation index)
return (const HnswTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid)); return (const HnswTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid));
} }
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnsw_halfvec_support); PGDLLEXPORT PG_FUNCTION_INFO_V1(hnsw_halfvec_support);
Datum Datum
hnsw_halfvec_support(PG_FUNCTION_ARGS) hnsw_halfvec_support(PG_FUNCTION_ARGS)
{ {
@@ -1318,7 +1312,7 @@ hnsw_halfvec_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo); PG_RETURN_POINTER(&typeInfo);
}; };
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnsw_bit_support); PGDLLEXPORT PG_FUNCTION_INFO_V1(hnsw_bit_support);
Datum Datum
hnsw_bit_support(PG_FUNCTION_ARGS) hnsw_bit_support(PG_FUNCTION_ARGS)
{ {
@@ -1331,7 +1325,7 @@ hnsw_bit_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo); PG_RETURN_POINTER(&typeInfo);
}; };
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(hnsw_sparsevec_support); PGDLLEXPORT 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, NULL); HnswLoadElement(highestPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true);
/* 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, NULL); HnswLoadElement(entryPoint, NULL, NULL, index, vacuumstate->procinfo, vacuumstate->collation, true);
if (NeedsUpdated(vacuumstate, entryPoint)) if (NeedsUpdated(vacuumstate, entryPoint))
{ {

View File

@@ -1006,10 +1006,6 @@ 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflathandler); PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflathandler);
Datum Datum
ivfflathandler(PG_FUNCTION_ARGS) ivfflathandler(PG_FUNCTION_ARGS)
{ {

View File

@@ -94,9 +94,6 @@ 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,11 +170,7 @@ IvfflatGetMetaPageInfo(Relation index, int *lists, int *dimensions)
page = BufferGetPage(buf); page = BufferGetPage(buf);
metap = IvfflatPageGetMeta(page); metap = IvfflatPageGetMeta(page);
if (unlikely(metap->magicNumber != IVFFLAT_MAGIC_NUMBER)) *lists = metap->lists;
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;
@@ -342,7 +338,7 @@ IvfflatGetTypeInfo(Relation index)
return (const IvfflatTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid)); return (const IvfflatTypeInfo *) DatumGetPointer(FunctionCall0Coll(procinfo, InvalidOid));
} }
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflat_halfvec_support); PGDLLEXPORT PG_FUNCTION_INFO_V1(ivfflat_halfvec_support);
Datum Datum
ivfflat_halfvec_support(PG_FUNCTION_ARGS) ivfflat_halfvec_support(PG_FUNCTION_ARGS)
{ {
@@ -357,7 +353,7 @@ ivfflat_halfvec_support(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(&typeInfo); PG_RETURN_POINTER(&typeInfo);
}; };
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(ivfflat_bit_support); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_in); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_out); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_typmod_in); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_recv); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_send); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_sparsevec); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_sparsevec); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_squared_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_inner_product); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_negative_inner_product); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_cosine_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l1_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_norm); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_l2_normalize); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_lt); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_le); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_eq); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_ne); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_ge); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_gt); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_cmp); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_in); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_out); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_typmod_in); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_recv); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_send); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(array_to_vector); PGDLLEXPORT 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[]
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_to_float4); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(halfvec_to_vector); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(l2_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_l2_squared_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(inner_product); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_negative_inner_product); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(cosine_distance); PGDLLEXPORT 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)
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_spherical_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(l1_distance); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_dims); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_norm); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(l2_normalize); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_add); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_sub); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_mul); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_concat); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(binary_quantize); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(subvector); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_lt); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_le); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_eq); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_ne); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_ge); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_gt); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_cmp); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_accum); PGDLLEXPORT 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)
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_combine); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(vector_avg); PGDLLEXPORT 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
*/ */
FUNCTION_PREFIX PG_FUNCTION_INFO_V1(sparsevec_to_vector); PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_to_vector);
Datum Datum
sparsevec_to_vector(PG_FUNCTION_ARGS) sparsevec_to_vector(PG_FUNCTION_ARGS)
{ {

View File

@@ -20,11 +20,4 @@ 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

3
test/expected/vector.out Normal file
View File

@@ -0,0 +1,3 @@
-- 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

@@ -1,672 +0,0 @@
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

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

View File

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

View File

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

3
test/perl/TestLib.pm Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,11 @@
use strict; use strict;
use warnings FATAL => 'all'; use warnings;
use PostgreSQL::Test::Cluster; use PostgresNode;
use PostgreSQL::Test::Utils; use TestLib;
use Test::More; use Test::More;
# Initialize node # Initialize node
my $node = PostgreSQL::Test::Cluster->new('node'); my $node = get_new_node('node');
$node->init; $node->init;
$node->start; $node->start;
@@ -53,7 +53,7 @@ sub test_aggregate
else else
{ {
# Does not raise overflow error in this instance due to loss of precision # 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 strict;
use warnings FATAL => 'all'; use warnings;
use PostgreSQL::Test::Cluster; use PostgresNode;
use PostgreSQL::Test::Utils; use TestLib;
use Test::More; use Test::More;
my $dim = 1024; my $dim = 1024;
# Initialize node # Initialize node
my $node = PostgreSQL::Test::Cluster->new('node'); my $node = get_new_node('node');
$node->init; $node->init;
$node->start; $node->start;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,42 +0,0 @@
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' comment = 'vector data type and ivfflat and hnsw access methods'
default_version = '0.7.4' default_version = '0.6.2'
module_pathname = '$libdir/vector' module_pathname = '$libdir/vector'
relocatable = true relocatable = true