Compare commits

...

78 Commits

Author SHA1 Message Date
Andrew Kane
fd93c9db86 Version bump to 0.2.0 [skip ci] 2021-10-03 20:32:45 -07:00
Andrew Kane
8dde26920c Added support for Postgres 14 2021-09-30 16:28:25 -07:00
Andrew Kane
9153a545a7 Added link to pgvector-cpp [skip ci] 2021-09-10 15:22:44 -07:00
Andrew Kane
9c20f04a11 Version bump to 0.1.8 [skip ci] 2021-09-07 14:10:58 -07:00
Andrew Kane
7c12d100ce Fixed build for Postgres < 13 2021-06-20 22:06:14 -07:00
Andrew Kane
d97d9a6561 Added cast for vector to real[] 2021-06-20 21:53:06 -07:00
Andrew Kane
f15ea301c5 Added link to Node library [skip ci] 2021-06-18 15:01:32 -07:00
Andrew Kane
cfa23f2c7a Added note on partitioning [skip ci] 2021-06-17 14:20:43 -07:00
Andrew Kane
b5b7035edc Restored section on partial indexes [skip ci] 2021-06-17 14:05:48 -07:00
Andrew Kane
478d62cdbd Added link to Go library [skip ci] 2021-06-16 17:33:49 -07:00
Andrew Kane
c7df9ef3a1 Updated changelog [skip ci] 2021-06-13 12:58:10 -07:00
Andrew Kane
ea1b094d8e Version bump to 0.1.7 [skip ci] 2021-06-13 12:52:55 -07:00
Andrew Kane
63d2965e8e Added link to pgvector-python [skip ci] 2021-06-12 06:49:44 -07:00
Andrew Kane
e5e7a6ec15 Fixed message [skip ci] 2021-06-11 03:36:06 -07:00
Andrew Kane
ede572d80b Fixed identation [skip ci] 2021-06-11 03:35:17 -07:00
Andrew Kane
154e4334fb Added cast for numeric[] 2021-06-11 03:32:47 -07:00
Andrew Kane
77d54333f6 Updated link [skip ci] 2021-06-09 22:01:38 -07:00
Andrew Kane
c95732340a Version bump to 0.1.6 [skip ci] 2021-06-09 20:48:50 -07:00
Andrew Kane
2af9bdefbb Added link to pgvector.rs [skip ci] 2021-06-09 19:42:40 -07:00
Andrew Kane
bd36231871 Less space [skip ci] 2021-06-09 04:03:06 -07:00
Andrew Kane
523788d964 Improved code 2021-06-09 03:59:00 -07:00
Andrew Kane
1eed57310a Use DBL_MAX for cost 2021-06-09 03:31:41 -07:00
Andrew Kane
57e6a01214 Fixed segmentation fault with COUNT - fixes #9 2021-06-09 03:13:22 -07:00
Andrew Kane
b713cbc3b6 Added instructions for Azure [skip ci] 2021-06-08 23:36:47 -07:00
Andrew Kane
ebeac156c0 Require unused to be 0 2021-05-26 13:40:38 -07:00
Andrew Kane
60bc93f938 Version bump to 0.1.5 [skip ci] 2021-05-25 17:31:02 -07:00
Andrew Kane
87a1b3365e Simplified logic 2021-05-24 18:58:11 -07:00
Andrew Kane
e9a762223b Moved line [skip ci] 2021-05-24 18:48:49 -07:00
Andrew Kane
db83f4faa8 Reduced memory usage during index build - #7 2021-05-24 18:40:34 -07:00
Andrew Kane
2cf71ec6bd Moved test [skip ci] 2021-05-15 00:29:52 -07:00
Andrew Kane
a7510430e3 Added test for max dimensions 2021-05-15 00:28:02 -07:00
Andrew Kane
ea8f06e8f4 Updated readme [skip ci] 2021-05-14 22:05:07 -07:00
Andrew Kane
4e0c1a137c Version bump to 0.1.4 [skip ci] 2021-05-09 14:21:29 -07:00
Andrew Kane
c758b7b188 Simplified upgrade statement [skip ci] 2021-05-09 14:19:05 -07:00
Andrew Kane
3dffc01e31 Improved comment [skip ci] 2021-05-06 22:40:04 -07:00
Andrew Kane
b8f3688e41 Fixed kmeans for inner product 2021-05-06 22:31:17 -07:00
Andrew Kane
67e317141b Fixed multiple definition error with GCC 10 - #4 2021-05-06 16:25:43 -07:00
Andrew Kane
de2ce0b1eb Added dockerignore [skip ci] 2021-05-06 15:30:02 -07:00
Andrew Kane
86c1c95ef4 Updated readme [skip ci] 2021-05-06 14:50:59 -07:00
Andrew Kane
38be81cf20 Version bump to 0.1.3 [skip ci] 2021-05-06 14:35:17 -07:00
Andrew Kane
62cc3398ed Added Dockerfile - #4 [skip ci] 2021-05-06 14:31:32 -07:00
Andrew Kane
af86392a34 Updated tag [skip ci] 2021-05-06 02:34:22 -07:00
Andrew Kane
a9067a8101 Updated tags [skip ci] 2021-05-06 02:33:09 -07:00
Andrew Kane
6deca154e6 Updated tag [skip ci] 2021-05-06 02:28:15 -07:00
Andrew Kane
6342439eb8 Removed version in meta [skip ci] 2021-05-06 02:24:47 -07:00
Andrew Kane
21967765a3 Updated meta [skip ci] 2021-05-06 02:24:09 -07:00
Andrew Kane
d31b7e3997 Updated changelog [skip ci] 2021-05-06 02:18:19 -07:00
Andrew Kane
efa85aaba1 Use recommended pattern 2021-05-06 02:17:30 -07:00
Andrew Kane
3c820b5a50 Updated gitignore [skip ci] 2021-05-06 02:08:18 -07:00
Andrew Kane
199c0e5e34 Renamed test [skip ci] 2021-05-06 02:07:04 -07:00
Andrew Kane
bcab0ad8ae Fixed version 2021-05-06 01:56:05 -07:00
Andrew Kane
09e95fc8f9 Improved Makefile [skip ci] 2021-05-06 01:41:54 -07:00
Andrew Kane
6119cced74 Improved Makefile [skip ci] 2021-05-06 01:40:32 -07:00
Andrew Kane
f8c07edba1 Updated readme [skip ci] 2021-05-05 15:16:45 -07:00
Andrew Kane
baabbaeff9 Moved sql and test files 2021-05-05 15:04:52 -07:00
Andrew Kane
f0993282fe Updated readme [skip ci] 2021-05-05 14:48:58 -07:00
Andrew Kane
01584d3df6 Added PGXN docs [skip ci] 2021-05-05 14:41:45 -07:00
Andrew Kane
6f50c4f5bd Added PGXN files [skip ci] 2021-05-05 14:35:34 -07:00
Andrew Kane
31a953f8db Updated readme [skip ci] 2021-05-03 17:05:02 -07:00
Andrew Kane
7b3d0f2595 Updated readme [skip ci] 2021-05-03 16:53:25 -07:00
Andrew Kane
099b9e9027 Added partial indexes section [skip ci] 2021-05-03 16:44:36 -07:00
Andrew Kane
e1f3caba49 Added OPTFLAGS 2021-05-02 14:49:34 -07:00
Andrew Kane
3f0d2bbd2f Updated readme [skip ci] 2021-04-30 18:45:25 -07:00
Andrew Kane
c989b85f75 Updated readme [skip ci] 2021-04-30 18:40:18 -07:00
Andrew Kane
a9bbee4198 Added section on hosted Postgres [skip ci] 2021-04-30 18:01:07 -07:00
Andrew Kane
fb274f1197 Added Homebrew docs [skip ci] 2021-04-30 16:30:55 -07:00
Andrew Kane
88ba5da6a7 Version bump to 0.1.2 [skip ci] 2021-04-26 19:37:26 -07:00
Andrew Kane
6a550c8b52 Added Mac to CI 2021-04-26 15:36:58 -07:00
Andrew Kane
5748cb6b43 Vectorized distance calculations 2021-04-26 15:33:11 -07:00
Andrew Kane
60814b8f39 Use write location for Postgres 9.6 2021-04-26 03:50:01 -07:00
Andrew Kane
773a63bed1 Use replay location instead of write location for test 2021-04-26 03:42:34 -07:00
Andrew Kane
955a5a6082 Removed completed todo [skip ci] 2021-04-26 01:09:05 -07:00
Andrew Kane
8863920fdc Improved cost estimation 2021-04-26 01:04:01 -07:00
Andrew Kane
6d9653d763 Show diff on failure 2021-04-25 22:24:45 -07:00
Andrew Kane
3a488c9f2f Fixed warning 2021-04-25 20:39:16 -07:00
Andrew Kane
fe133bfe5d Updated readme [skip ci] 2021-04-25 20:00:53 -07:00
Andrew Kane
e279bb3d7e Revert "Use INFINITY instead of DBL_MAX for comparisons"
This reverts commit 0aa39a8c0c.
2021-04-25 19:51:35 -07:00
Andrew Kane
0aa39a8c0c Use INFINITY instead of DBL_MAX for comparisons 2021-04-25 19:16:29 -07:00
46 changed files with 635 additions and 268 deletions

8
.dockerignore Normal file
View File

@@ -0,0 +1,8 @@
/.git/
/dist/
/results/
/tmp_check/
/sql/vector--?.?.?.sql
regression.*
*.o
*.so

View File

@@ -3,20 +3,37 @@ on: [push, pull_request]
jobs:
build:
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
postgres: [13, 12, 11, 10, 9.6]
os: [ubuntu-latest]
postgres: [14, 13, 12, 11, 10, 9.6]
include:
- os: macos-latest
postgres: 13
steps:
- uses: actions/checkout@v2
- uses: ankane/setup-postgres@v1
with:
postgres-version: ${{ matrix.postgres }}
- run: sudo apt-get update && sudo apt-get install postgresql-server-dev-${{ matrix.postgres }} libipc-run-perl
- if: ${{ startsWith(matrix.os, 'ubuntu') }}
run: sudo apt-get update && sudo apt-get install postgresql-server-dev-${{ matrix.postgres }} libipc-run-perl
- run: make
- run: |
- if: ${{ startsWith(matrix.os, 'ubuntu') }}
run: |
export PG_CONFIG=`which pg_config`
sudo --preserve-env=PG_CONFIG make install
- if: ${{ startsWith(matrix.os, 'macos') }}
run: make install
- run: make installcheck
- run: make prove_installcheck
- if: ${{ failure() }}
run: cat regression.diffs
- if: ${{ startsWith(matrix.os, 'ubuntu') }}
run: make prove_installcheck
- if: ${{ startsWith(matrix.os, 'macos') }}
run: |
brew install cpanm && cpanm IPC::Run
wget -q https://github.com/postgres/postgres/archive/refs/tags/REL_13_2.tar.gz
tar xf REL_13_2.tar.gz
make prove_installcheck PROVE=prove PERL5LIB=postgres-REL_13_2/src/test/perl

6
.gitignore vendored
View File

@@ -1,5 +1,7 @@
results
tmp_check
/dist/
/results/
/tmp_check/
/sql/vector--?.?.?.sql
regression.*
*.o
*.so

View File

@@ -1,3 +1,38 @@
## 0.2.0 (2021-10-03)
- Added support for Postgres 14
## 0.1.8 (2021-09-07)
- Added cast for `vector` to `real[]`
## 0.1.7 (2021-06-13)
- Added cast for `numeric[]` to `vector`
## 0.1.6 (2021-06-09)
- Fixed segmentation fault with `COUNT`
## 0.1.5 (2021-05-25)
- Reduced memory usage during index creation
## 0.1.4 (2021-05-09)
- Fixed kmeans for inner product
- Fixed multiple definition error with GCC 10
## 0.1.3 (2021-05-06)
- Added Dockerfile
- Fixed version
## 0.1.2 (2021-04-26)
- Vectorized distance calculations
- Improved cost estimation
## 0.1.1 (2021-04-25)
- Added binary representation for `COPY`

16
Dockerfile Normal file
View File

@@ -0,0 +1,16 @@
FROM postgres:14
COPY . /tmp/pgvector
RUN apt-get update && \
apt-get install -y --no-install-recommends build-essential postgresql-server-dev-14 && \
cd /tmp/pgvector && \
make clean && \
make OPTFLAGS="" && \
make install && \
mkdir /usr/share/doc/pgvector && \
cp LICENSE README.md /usr/share/doc/pgvector && \
rm -r /tmp/pgvector && \
apt-get remove -y build-essential postgresql-server-dev-14 && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*

49
META.json Normal file
View File

@@ -0,0 +1,49 @@
{
"name": "vector",
"abstract": "Open-source vector similarity search for Postgres",
"description": "Supports L2 distance, inner product, and cosine distance",
"version": "0.2.0",
"maintainer": [
"Andrew Kane <andrew@ankane.org>"
],
"license": {
"PostgreSQL": "http://www.postgresql.org/about/licence"
},
"prereqs": {
"runtime": {
"requires": {
"PostgreSQL": "9.6.0"
}
}
},
"provides": {
"vector": {
"file": "sql/vector.sql",
"docfile": "README.md",
"version": "0.2.0",
"abstract": "Open-source vector similarity search for Postgres"
}
},
"resources": {
"homepage": "https://github.com/ankane/pgvector",
"bugtracker": {
"web": "https://github.com/ankane/pgvector/issues"
},
"repository": {
"url": "https://github.com/ankane/pgvector.git",
"web": "https://github.com/ankane/pgvector",
"type": "git"
}
},
"generated_by": "Andrew Kane",
"meta-spec": {
"version": "1.0.0",
"url": "http://pgxn.org/meta/spec.txt"
},
"tags": [
"vectors",
"datatype",
"nearest neighbor search",
"approximate nearest neighbors"
]
}

View File

@@ -1,11 +1,33 @@
EXTENSION = vector
DATA = vector--0.1.1.sql vector--0.1.0--0.1.1.sql
EXTVERSION = 0.2.0
MODULE_big = vector
DATA = $(wildcard sql/*--*.sql)
OBJS = src/ivfbuild.o src/ivfflat.o src/ivfinsert.o src/ivfkmeans.o src/ivfscan.o src/ivfutils.o src/ivfvacuum.o src/vector.o
TESTS = $(wildcard sql/*.sql)
TESTS = $(wildcard test/sql/*.sql)
REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS))
REGRESS_OPTS = --inputdir=test
REGRESS = btree cast copy functions ivfflat_cosine ivfflat_ip ivfflat_l2 ivfflat_unlogged vector
OPTFLAGS = -march=native
# For auto-vectorization:
# - GCC (needs -ftree-vectorize OR -O3) - https://gcc.gnu.org/projects/tree-ssa/vectorization.html
# - Clang (could use pragma instead) - https://llvm.org/docs/Vectorizers.html
PG_CFLAGS = $(OPTFLAGS) -ftree-vectorize -fassociative-math -fno-signed-zeros -fno-trapping-math
# Debug GCC auto-vectorization
# PG_CFLAGS += -fopt-info-vec
# Debug Clang auto-vectorization
# PG_CFLAGS += -Rpass=loop-vectorize -Rpass-analysis=loop-vectorize
all: sql/$(EXTENSION)--$(EXTVERSION).sql
sql/$(EXTENSION)--$(EXTVERSION).sql: sql/$(EXTENSION).sql
cp $< $@
EXTRA_CLEAN = sql/$(EXTENSION)--$(EXTVERSION).sql
PG_CONFIG ?= pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
@@ -13,4 +35,10 @@ include $(PGXS)
prove_installcheck:
rm -rf $(CURDIR)/tmp_check
cd $(srcdir) && TESTDIR='$(CURDIR)' PATH="$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' PG_REGRESS='$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl)
cd $(srcdir) && TESTDIR='$(CURDIR)' PATH="$(bindir):$$PATH" PGPORT='6$(DEF_PGPORT)' PG_REGRESS='$(top_builddir)/src/test/regress/pg_regress' $(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),test/t/*.pl)
.PHONY: dist
dist:
mkdir -p dist
git archive --format zip --prefix=$(EXTENSION)-$(EXTVERSION)/ --output dist/$(EXTENSION)-$(EXTVERSION).zip master

View File

@@ -17,7 +17,7 @@ Supports L2 distance, inner product, and cosine distance
Compile and install the extension (supports Postgres 9.6+)
```sh
git clone --branch v0.1.1 https://github.com/ankane/pgvector.git
git clone --branch v0.2.0 https://github.com/ankane/pgvector.git
cd pgvector
make
make install # may need sudo
@@ -29,6 +29,8 @@ Then load it in databases where you want to use it
CREATE EXTENSION vector;
```
You can also install it with [Docker](#docker), [Homebrew](#homebrew), or [PGXN](#pgxn)
## Getting Started
Create a vector column with 3 dimensions (replace `table` and `column` with non-reserved names)
@@ -104,6 +106,16 @@ SELECT ...
COMMIT;
```
### Partial Indexes
Consider [partial indexes](https://www.postgresql.org/docs/current/indexes-partial.html) for queries with a `WHERE` clause
```sql
CREATE INDEX ON table USING ivfflat (column) WHERE (other_column = 123);
```
To index many different values of `other_column`, consider [partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html) on `other_column`.
## Reference
### Vector Type
@@ -134,16 +146,64 @@ vector_norm(vector) | Euclidean norm
Libraries that use pgvector:
- [pgvector-python](https://github.com/ankane/pgvector-python) (Python)
- [Neighbor](https://github.com/ankane/neighbor) (Ruby)
- [pgvector-node](https://github.com/ankane/pgvector-node) (Node.js)
- [pgvector-go](https://github.com/ankane/pgvector-go) (Go)
- [pgvector-rust](https://github.com/ankane/pgvector-rust) (Rust)
- [pgvector-cpp](https://github.com/ankane/pgvector-cpp) (C++)
## Additional Installation Methods
### Docker
Get the [Docker image](https://hub.docker.com/repository/docker/ankane/pgvector) with:
```sh
docker pull ankane/pgvector
```
This adds pgvector to the [Postgres image](https://hub.docker.com/_/postgres).
You can also build the image manually
```sh
git clone --branch v0.2.0 https://github.com/ankane/pgvector.git
cd pgvector
docker build -t pgvector .
```
### Homebrew
On Mac with Homebrew Postgres, you can use:
```sh
brew install ankane/brew/pgvector
```
### PGXN
Install from the [PostgreSQL Extension Network](https://pgxn.org/dist/vector) with:
```sh
pgxn install vector
```
## Hosted Postgres
Some Postgres providers only support specific extensions. To request a new extension:
- Amazon RDS - follow the instructions on [this page](https://aws.amazon.com/rds/postgresql/faqs/)
- Google Cloud SQL - follow the instructions on [this page](https://cloud.google.com/sql/docs/postgres/extensions#requesting-support-for-a-new-extension)
- DigitalOcean Managed Databases - follow the instructions on [this page](https://docs.digitalocean.com/products/databases/postgresql/resources/supported-extensions/#supported-extensions)
- Azure Database for PostgreSQL - follow the instructions on [this page](https://docs.microsoft.com/en-us/azure/postgresql/concepts-extensions#next-steps)
## Upgrading
### 0.1.1
Follow the [installation instructions](#installation) and run:
Install the latest version and run:
```sql
ALTER EXTENSION vector UPDATE TO '0.1.1';
ALTER EXTENSION vector UPDATE;
```
## Thanks
@@ -188,16 +248,10 @@ make prove_installcheck # TAP tests
To run single tests:
```sh
make installcheck REGRESS=vector # regression test
make prove_installcheck PROVE_TESTS=t/001_wal.pl # TAP test
make installcheck REGRESS=functions # regression test
make prove_installcheck PROVE_TESTS=test/t/001_wal.pl # TAP test
```
Directories
- `expected` - expected output for regression tests
- `sql` - regression tests
- `t` - TAP tests
Resources for contributors
- [Extension Building Infrastructure](https://www.postgresql.org/docs/current/extend-pgxs.html)

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,8 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION vector UPDATE TO '0.1.7'" to load this file. \quit
CREATE FUNCTION array_to_vector(numeric[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE CAST (numeric[] AS vector)
WITH FUNCTION array_to_vector(numeric[], integer, boolean) AS IMPLICIT;

View File

@@ -0,0 +1,8 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION vector UPDATE TO '0.1.8'" to load this file. \quit
CREATE FUNCTION vector_to_float4(vector, integer, boolean) RETURNS real[]
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE CAST (vector AS real[])
WITH FUNCTION vector_to_float4(vector, integer, boolean) AS IMPLICIT;

View File

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

View File

@@ -1,15 +1,230 @@
SET client_min_messages = warning;
CREATE EXTENSION IF NOT EXISTS vector;
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION vector" to load this file. \quit
SELECT '[1,2,3]'::vector;
SELECT '[-1,2,3]'::vector;
SELECT '[hello,1]'::vector;
SELECT '[NaN,1]'::vector;
SELECT '[Infinity,1]'::vector;
SELECT '[-Infinity,1]'::vector;
SELECT '[1,2,3'::vector;
SELECT '[1,2,3]9'::vector;
SELECT '1,2,3'::vector;
SELECT '[]'::vector;
SELECT '[1,]'::vector;
SELECT '[1,2,3]'::vector(2);
-- type
CREATE TYPE vector;
CREATE FUNCTION vector_in(cstring, oid, integer) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_out(vector) RETURNS cstring
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_typmod_in(cstring[]) RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_recv(internal, oid, integer) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_send(vector) RETURNS bytea
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE TYPE vector (
INPUT = vector_in,
OUTPUT = vector_out,
TYPMOD_IN = vector_typmod_in,
RECEIVE = vector_recv,
SEND = vector_send
);
-- functions
CREATE FUNCTION l2_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION inner_product(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION cosine_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_dims(vector) RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_norm(vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_add(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_sub(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- private functions
CREATE FUNCTION vector_lt(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_le(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_eq(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_ne(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_ge(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_gt(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_cmp(vector, vector) RETURNS int4
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_l2_squared_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_negative_inner_product(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_spherical_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- cast functions
CREATE FUNCTION vector(vector, integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(integer[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(real[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(double precision[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(numeric[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_to_float4(vector, integer, boolean) RETURNS real[]
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- casts
CREATE CAST (vector AS vector)
WITH FUNCTION vector(vector, integer, boolean) AS IMPLICIT;
CREATE CAST (integer[] AS vector)
WITH FUNCTION array_to_vector(integer[], integer, boolean) AS IMPLICIT;
CREATE CAST (real[] AS vector)
WITH FUNCTION array_to_vector(real[], integer, boolean) AS IMPLICIT;
CREATE CAST (double precision[] AS vector)
WITH FUNCTION array_to_vector(double precision[], integer, boolean) AS IMPLICIT;
CREATE CAST (numeric[] AS vector)
WITH FUNCTION array_to_vector(numeric[], integer, boolean) AS IMPLICIT;
CREATE CAST (vector AS real[])
WITH FUNCTION vector_to_float4(vector, integer, boolean) AS IMPLICIT;
-- operators
CREATE OPERATOR <-> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = l2_distance,
COMMUTATOR = '<->'
);
CREATE OPERATOR <#> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_negative_inner_product,
COMMUTATOR = '<#>'
);
CREATE OPERATOR <=> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = cosine_distance,
COMMUTATOR = '<=>'
);
CREATE OPERATOR + (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_add,
COMMUTATOR = +
);
CREATE OPERATOR - (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_sub,
COMMUTATOR = -
);
CREATE OPERATOR < (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_lt,
COMMUTATOR = > , NEGATOR = >= ,
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);
-- should use scalarlesel and scalarlejoinsel, but not supported in Postgres < 11
CREATE OPERATOR <= (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_le,
COMMUTATOR = >= , NEGATOR = > ,
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);
CREATE OPERATOR = (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_eq,
COMMUTATOR = = , NEGATOR = <> ,
RESTRICT = eqsel, JOIN = eqjoinsel
);
CREATE OPERATOR <> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_ne,
COMMUTATOR = <> , NEGATOR = = ,
RESTRICT = eqsel, JOIN = eqjoinsel
);
-- should use scalargesel and scalargejoinsel, but not supported in Postgres < 11
CREATE OPERATOR >= (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_ge,
COMMUTATOR = <= , NEGATOR = < ,
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);
CREATE OPERATOR > (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_gt,
COMMUTATOR = < , NEGATOR = <= ,
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);
-- access method
CREATE FUNCTION ivfflathandler(internal) RETURNS index_am_handler
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE ACCESS METHOD ivfflat TYPE INDEX HANDLER ivfflathandler;
COMMENT ON ACCESS METHOD ivfflat IS 'ivfflat index access method';
-- opclasses
CREATE OPERATOR CLASS vector_ops
DEFAULT FOR TYPE vector USING btree AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
OPERATOR 3 = ,
OPERATOR 4 >= ,
OPERATOR 5 > ,
FUNCTION 1 vector_cmp(vector, vector);
CREATE OPERATOR CLASS vector_l2_ops
DEFAULT FOR TYPE vector USING ivfflat AS
OPERATOR 1 <-> (vector, vector) FOR ORDER BY float_ops,
FUNCTION 1 vector_l2_squared_distance(vector, vector),
FUNCTION 3 l2_distance(vector, vector);
CREATE OPERATOR CLASS vector_ip_ops
FOR TYPE vector USING ivfflat AS
OPERATOR 1 <#> (vector, vector) FOR ORDER BY float_ops,
FUNCTION 1 vector_negative_inner_product(vector, vector),
FUNCTION 3 vector_spherical_distance(vector, vector),
FUNCTION 4 vector_norm(vector);
CREATE OPERATOR CLASS vector_cosine_ops
FOR TYPE vector USING ivfflat AS
OPERATOR 1 <=> (vector, vector) FOR ORDER BY float_ops,
FUNCTION 1 vector_negative_inner_product(vector, vector),
FUNCTION 2 vector_norm(vector),
FUNCTION 3 vector_spherical_distance(vector, vector),
FUNCTION 4 vector_norm(vector);

View File

@@ -41,10 +41,13 @@ SampleCallback(Relation index, CALLBACK_ITEM_POINTER, Datum *values,
if (isnull[0])
return;
/* Normalize the value */
if (buildstate->normprocinfo != NULL)
/*
* Normalize with KMEANS_NORM_PROC since spherical distance function
* expects unit vectors
*/
if (buildstate->kmeansnormprocinfo != NULL)
{
if (!IvfflatNormValue(buildstate->normprocinfo, buildstate->collation, &value, buildstate->normvec))
if (!IvfflatNormValue(buildstate->kmeansnormprocinfo, buildstate->collation, &value, buildstate->normvec))
return;
}
@@ -238,6 +241,8 @@ InsertTuples(Relation index, IvfflatBuildState * buildstate, ForkNumber forkNum)
if (PageAddItem(page, (Item) itup, itemsz, InvalidOffsetNumber, false, false) == InvalidOffsetNumber)
elog(ERROR, "failed to add index item to \"%s\"", RelationGetRelationName(index));
pfree(itup);
buildstate->indtuples += 1;
GetNextTuple(buildstate->sortstate, tupdesc, slot, &itup, &list);
@@ -275,6 +280,7 @@ InitBuildState(IvfflatBuildState * buildstate, Relation heap, Relation index, In
/* Get support functions */
buildstate->procinfo = index_getprocinfo(index, 1, IVFFLAT_DISTANCE_PROC);
buildstate->normprocinfo = IvfflatOptionalProcInfo(index, IVFFLAT_NORM_PROC);
buildstate->kmeansnormprocinfo = IvfflatOptionalProcInfo(index, IVFFLAT_KMEANS_NORM_PROC);
buildstate->collation = index->rd_indcollation[0];
/* Create tuple description for sorting */

View File

@@ -1,11 +1,14 @@
#include "postgres.h"
#include <float.h>
#include "access/amapi.h"
#include "commands/vacuum.h"
#include "ivfflat.h"
#include "utils/guc.h"
#include "utils/selfuncs.h"
int ivfflat_probes;
static relopt_kind ivfflat_relopt_kind;
/*
@@ -29,8 +32,6 @@ _PG_init(void)
/*
* Estimate the cost of an index scan
*
* TODO Improve cost estimation
*/
static void
ivfflatcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
@@ -42,22 +43,47 @@ ivfflatcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
)
{
GenericCosts costs;
int lists;
double ratio;
Relation indexRel;
#if PG_VERSION_NUM < 120000
List *qinfos;
qinfos = deconstruct_indexquals(path);
#endif
/* Never use index without order */
if (path->indexorderbys == NULL)
{
*indexStartupCost = DBL_MAX;
*indexTotalCost = DBL_MAX;
*indexSelectivity = 0;
*indexCorrelation = 0;
#if PG_VERSION_NUM >= 100000
*indexPages = 0;
#endif
return;
}
MemSet(&costs, 0, sizeof(costs));
#if PG_VERSION_NUM >= 120000
genericcostestimate(root, path, loop_count, &costs);
#else
qinfos = deconstruct_indexquals(path);
genericcostestimate(root, path, loop_count, qinfos, &costs);
#endif
*indexStartupCost = costs.indexStartupCost;
indexRel = index_open(path->indexinfo->indexoid, NoLock);
lists = IvfflatGetLists(indexRel);
index_close(indexRel, NoLock);
ratio = ((double) ivfflat_probes) / lists;
if (ratio > 1)
ratio = 1;
costs.indexTotalCost *= ratio;
/* Startup cost and total cost are same */
*indexStartupCost = costs.indexTotalCost;
*indexTotalCost = costs.indexTotalCost;
*indexSelectivity = costs.indexSelectivity;
*indexCorrelation = costs.indexCorrelation;

View File

@@ -38,7 +38,7 @@
#endif
/* Variables */
int ivfflat_probes;
extern int ivfflat_probes;
typedef struct VectorArrayData
{
@@ -81,6 +81,7 @@ typedef struct IvfflatBuildState
/* Support functions */
FmgrInfo *procinfo;
FmgrInfo *normprocinfo;
FmgrInfo *kmeansnormprocinfo;
Oid collation;
/* Variables */
@@ -179,6 +180,9 @@ void IvfflatInitPage(Relation index, Buffer *buf, Page *page, GenericXLogState
IndexBuildResult *ivfflatbuild(Relation heap, Relation index, IndexInfo *indexInfo);
void ivfflatbuildempty(Relation index);
bool ivfflatinsert(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid, Relation heap, IndexUniqueCheck checkUnique
#if PG_VERSION_NUM >= 140000
,bool indexUnchanged
#endif
#if PG_VERSION_NUM >= 100000
,IndexInfo *indexInfo
#endif

View File

@@ -128,6 +128,9 @@ InsertTuple(Relation rel, IndexTuple itup, Relation heapRel, Datum *values)
bool
ivfflatinsert(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid,
Relation heap, IndexUniqueCheck checkUnique
#if PG_VERSION_NUM >= 140000
,bool indexUnchanged
#endif
#if PG_VERSION_NUM >= 100000
,IndexInfo *indexInfo
#endif

View File

@@ -251,6 +251,10 @@ ivfflatgettuple(IndexScanDesc scan, ScanDirection dir)
{
Datum value;
/* Safety check */
if (scan->orderByData == NULL)
elog(ERROR, "cannot scan ivfflat index without order");
/* No items will match if null */
if (scan->orderByData->sk_flags & SK_ISNULL)
return false;

View File

@@ -10,11 +10,16 @@
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/numeric.h"
#if PG_VERSION_NUM >= 120000
#include "utils/float.h"
#endif
#if PG_VERSION_NUM < 130000
#define TYPALIGN_INT 'i'
#endif
PG_MODULE_MAGIC;
/*
@@ -253,6 +258,11 @@ vector_recv(PG_FUNCTION_ARGS)
CheckDim(dim);
CheckExpectedDim(typmod, dim);
if (unused != 0)
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("expected unused to be 0, not %d", unused)));
result = InitVector(dim);
for (i = 0; i < dim; i++)
result->x[i] = pq_getmsgfloat4(buf);
@@ -340,6 +350,8 @@ array_to_vector(PG_FUNCTION_ARGS)
result->x[i] = DatumGetFloat8(elemsp[i]);
else if (ARR_ELEMTYPE(array) == FLOAT4OID)
result->x[i] = DatumGetFloat4(elemsp[i]);
else if (ARR_ELEMTYPE(array) == NUMERICOID)
result->x[i] = DatumGetFloat4(DirectFunctionCall1(numeric_float4, NumericGetDatum(elemsp[i])));
else
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
@@ -351,6 +363,29 @@ array_to_vector(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(result);
}
/*
* Convert vector to float4[]
*/
PG_FUNCTION_INFO_V1(vector_to_float4);
Datum
vector_to_float4(PG_FUNCTION_ARGS)
{
Vector *vec = PG_GETARG_VECTOR_P(0);
Datum *d;
ArrayType *result;
int i;
d = (Datum *) palloc(sizeof(Datum) * vec->dim);
for (i = 0; i < vec->dim; i++)
d[i] = Float4GetDatum(vec->x[i]);
/* Use TYPALIGN_INT for float4 */
result = construct_array(d, vec->dim, FLOAT4OID, sizeof(float4), true, TYPALIGN_INT);
PG_RETURN_POINTER(result);
}
/*
* Get the L2 distance between vectors
*/

View File

@@ -6,6 +6,12 @@ SELECT ARRAY[1,2,3]::vector;
[1,2,3]
(1 row)
SELECT ARRAY[1.0,2.0,3.0]::vector;
array
---------
[1,2,3]
(1 row)
SELECT ARRAY[1,2,3]::float4[]::vector;
array
---------
@@ -28,3 +34,11 @@ SELECT '{-Infinity}'::real[]::vector;
ERROR: infinite value not allowed in vector
SELECT '{}'::real[]::vector;
ERROR: vector must have at least 1 dimension
SELECT '[1,2,3]'::vector::real[];
float4
---------
{1,2,3}
(1 row)
SELECT array_agg(n)::vector FROM generate_series(1, 1025) n;
ERROR: vector cannot have more than 1024 dimensions

View File

@@ -19,4 +19,10 @@ SELECT * FROM t ORDER BY val <-> (SELECT NULL::vector);
-----
(0 rows)
SELECT COUNT(*) FROM t;
count
-------
5
(1 row)
DROP TABLE t;

View File

@@ -0,0 +1,17 @@
SET client_min_messages = warning;
CREATE EXTENSION IF NOT EXISTS vector;
SET enable_seqscan = off;
CREATE TABLE t (val vector(3));
CREATE INDEX ON t USING ivfflat (val) WITH (lists = 0);
ERROR: value 0 out of bounds for option "lists"
DETAIL: Valid values are between "1" and "32768".
CREATE INDEX ON t USING ivfflat (val) WITH (lists = 32769);
ERROR: value 32769 out of bounds for option "lists"
DETAIL: Valid values are between "1" and "32768".
SHOW ivfflat.probes;
ivfflat.probes
----------------
1
(1 row)
DROP TABLE t;

View File

@@ -2,6 +2,7 @@ SET client_min_messages = warning;
CREATE EXTENSION IF NOT EXISTS vector;
SELECT ARRAY[1,2,3]::vector;
SELECT ARRAY[1.0,2.0,3.0]::vector;
SELECT ARRAY[1,2,3]::float4[]::vector;
SELECT ARRAY[1,2,3]::float8[]::vector;
SELECT '{NULL}'::real[]::vector;
@@ -9,3 +10,5 @@ SELECT '{NaN}'::real[]::vector;
SELECT '{Infinity}'::real[]::vector;
SELECT '{-Infinity}'::real[]::vector;
SELECT '{}'::real[]::vector;
SELECT '[1,2,3]'::vector::real[];
SELECT array_agg(n)::vector FROM generate_series(1, 1025) n;

15
test/sql/input.sql Normal file
View File

@@ -0,0 +1,15 @@
SET client_min_messages = warning;
CREATE EXTENSION IF NOT EXISTS vector;
SELECT '[1,2,3]'::vector;
SELECT '[-1,2,3]'::vector;
SELECT '[hello,1]'::vector;
SELECT '[NaN,1]'::vector;
SELECT '[Infinity,1]'::vector;
SELECT '[-Infinity,1]'::vector;
SELECT '[1,2,3'::vector;
SELECT '[1,2,3]9'::vector;
SELECT '1,2,3'::vector;
SELECT '[]'::vector;
SELECT '[1,]'::vector;
SELECT '[1,2,3]'::vector(2);

View File

@@ -10,5 +10,6 @@ INSERT INTO t (val) VALUES ('[1,2,4]');
SELECT * FROM t ORDER BY val <-> '[3,3,3]';
SELECT * FROM t ORDER BY val <-> (SELECT NULL::vector);
SELECT COUNT(*) FROM t;
DROP TABLE t;

View File

@@ -21,8 +21,9 @@ sub test_index_replay
my $caughtup_query;
my $server_version_num = $node_primary->safe_psql("postgres", "SHOW server_version_num");
if ($server_version_num >= 100000) {
$caughtup_query = "SELECT pg_current_wal_lsn() <= write_lsn FROM pg_stat_replication WHERE application_name = '$applname';";
$caughtup_query = "SELECT pg_current_wal_lsn() <= replay_lsn FROM pg_stat_replication WHERE application_name = '$applname';";
} else {
# TODO figure out why replay location doesn't work
$caughtup_query = "SELECT pg_current_xlog_location() <= write_location FROM pg_stat_replication WHERE application_name = '$applname';";
}

View File

@@ -1,218 +0,0 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION vector" to load this file. \quit
-- type
CREATE TYPE vector;
CREATE FUNCTION vector_in(cstring, oid, integer) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_out(vector) RETURNS cstring
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_typmod_in(cstring[]) RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_recv(internal, oid, integer) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_send(vector) RETURNS bytea
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE TYPE vector (
INPUT = vector_in,
OUTPUT = vector_out,
TYPMOD_IN = vector_typmod_in,
RECEIVE = vector_recv,
SEND = vector_send
);
-- functions
CREATE FUNCTION l2_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION inner_product(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION cosine_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_dims(vector) RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_norm(vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_add(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_sub(vector, vector) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- private functions
CREATE FUNCTION vector_lt(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_le(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_eq(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_ne(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_ge(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_gt(vector, vector) RETURNS bool
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_cmp(vector, vector) RETURNS int4
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_l2_squared_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_negative_inner_product(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION vector_spherical_distance(vector, vector) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- cast functions
CREATE FUNCTION vector(vector, integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(integer[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(real[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION array_to_vector(double precision[], integer, boolean) RETURNS vector
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
-- casts
CREATE CAST (vector AS vector)
WITH FUNCTION vector(vector, integer, boolean) AS IMPLICIT;
CREATE CAST (integer[] AS vector)
WITH FUNCTION array_to_vector(integer[], integer, boolean) AS IMPLICIT;
CREATE CAST (real[] AS vector)
WITH FUNCTION array_to_vector(real[], integer, boolean) AS IMPLICIT;
CREATE CAST (double precision[] AS vector)
WITH FUNCTION array_to_vector(double precision[], integer, boolean) AS IMPLICIT;
-- operators
CREATE OPERATOR <-> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = l2_distance,
COMMUTATOR = '<->'
);
CREATE OPERATOR <#> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_negative_inner_product,
COMMUTATOR = '<#>'
);
CREATE OPERATOR <=> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = cosine_distance,
COMMUTATOR = '<=>'
);
CREATE OPERATOR + (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_add,
COMMUTATOR = +
);
CREATE OPERATOR - (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_sub,
COMMUTATOR = -
);
CREATE OPERATOR < (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_lt,
COMMUTATOR = > , NEGATOR = >= ,
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);
-- should use scalarlesel and scalarlejoinsel, but not supported in Postgres < 11
CREATE OPERATOR <= (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_le,
COMMUTATOR = >= , NEGATOR = > ,
RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);
CREATE OPERATOR = (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_eq,
COMMUTATOR = = , NEGATOR = <> ,
RESTRICT = eqsel, JOIN = eqjoinsel
);
CREATE OPERATOR <> (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_ne,
COMMUTATOR = <> , NEGATOR = = ,
RESTRICT = eqsel, JOIN = eqjoinsel
);
-- should use scalargesel and scalargejoinsel, but not supported in Postgres < 11
CREATE OPERATOR >= (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_ge,
COMMUTATOR = <= , NEGATOR = < ,
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);
CREATE OPERATOR > (
LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_gt,
COMMUTATOR = < , NEGATOR = <= ,
RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);
-- access method
CREATE FUNCTION ivfflathandler(internal) RETURNS index_am_handler
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE ACCESS METHOD ivfflat TYPE INDEX HANDLER ivfflathandler;
COMMENT ON ACCESS METHOD ivfflat IS 'ivfflat index access method';
-- opclasses
CREATE OPERATOR CLASS vector_ops
DEFAULT FOR TYPE vector USING btree AS
OPERATOR 1 < ,
OPERATOR 2 <= ,
OPERATOR 3 = ,
OPERATOR 4 >= ,
OPERATOR 5 > ,
FUNCTION 1 vector_cmp(vector, vector);
CREATE OPERATOR CLASS vector_l2_ops
DEFAULT FOR TYPE vector USING ivfflat AS
OPERATOR 1 <-> (vector, vector) FOR ORDER BY float_ops,
FUNCTION 1 vector_l2_squared_distance(vector, vector),
FUNCTION 3 l2_distance(vector, vector);
CREATE OPERATOR CLASS vector_ip_ops
FOR TYPE vector USING ivfflat AS
OPERATOR 1 <#> (vector, vector) FOR ORDER BY float_ops,
FUNCTION 1 vector_negative_inner_product(vector, vector),
FUNCTION 3 vector_spherical_distance(vector, vector),
FUNCTION 4 vector_norm(vector);
CREATE OPERATOR CLASS vector_cosine_ops
FOR TYPE vector USING ivfflat AS
OPERATOR 1 <=> (vector, vector) FOR ORDER BY float_ops,
FUNCTION 1 vector_negative_inner_product(vector, vector),
FUNCTION 2 vector_norm(vector),
FUNCTION 3 vector_spherical_distance(vector, vector),
FUNCTION 4 vector_norm(vector);

View File

@@ -1,4 +1,4 @@
comment = 'vector data type and ivfflat access method'
default_version = '0.1.1'
default_version = '0.2.0'
module_pathname = '$libdir/vector'
relocatable = true