diff --git a/CHANGELOG.md b/CHANGELOG.md index bf81eb0..90e5018 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.7.0 (unreleased) + +- Added concatenate operator for vectors + ## 0.6.2 (unreleased) - Reduced lock contention with parallel HNSW index builds diff --git a/README.md b/README.md index 3a8ee86..310a5a4 100644 --- a/README.md +++ b/README.md @@ -682,6 +682,7 @@ Operator | Description | Added \+ | element-wise addition | \- | element-wise subtraction | \* | element-wise multiplication | 0.5.0 +\|\| | concatenate | 0.7.0 <-> | Euclidean distance | <#> | negative inner product | <=> | cosine distance | diff --git a/sql/vector--0.6.2--0.7.0.sql b/sql/vector--0.6.2--0.7.0.sql new file mode 100644 index 0000000..981a5af --- /dev/null +++ b/sql/vector--0.6.2--0.7.0.sql @@ -0,0 +1,9 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION vector UPDATE TO '0.7.0'" to load this file. \quit + +CREATE FUNCTION vector_concat(vector, vector) RETURNS vector + AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + +CREATE OPERATOR || ( + LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_concat +); diff --git a/sql/vector.sql b/sql/vector.sql index 141e83c..215fe54 100644 --- a/sql/vector.sql +++ b/sql/vector.sql @@ -99,6 +99,9 @@ CREATE FUNCTION vector_avg(double precision[]) RETURNS vector CREATE FUNCTION vector_combine(double precision[], double precision[]) RETURNS double precision[] AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; +CREATE FUNCTION vector_concat(vector, vector) RETURNS vector + AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE; + -- aggregates CREATE AGGREGATE avg(vector) ( @@ -224,6 +227,10 @@ CREATE OPERATOR > ( RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR || ( + LEFTARG = vector, RIGHTARG = vector, PROCEDURE = vector_concat +); + -- access methods CREATE FUNCTION ivfflathandler(internal) RETURNS index_am_handler diff --git a/src/vector.c b/src/vector.c index 5f3cbbb..bf1f33e 100644 --- a/src/vector.c +++ b/src/vector.c @@ -1160,3 +1160,28 @@ vector_avg(PG_FUNCTION_ARGS) PG_RETURN_POINTER(result); } + +/* + * Concat vectors + */ +PGDLLEXPORT PG_FUNCTION_INFO_V1(vector_concat); +Datum +vector_concat(PG_FUNCTION_ARGS) +{ + Vector *a = PG_GETARG_VECTOR_P(0); + Vector *b = PG_GETARG_VECTOR_P(1); + Vector *result; + int dim = a->dim + b->dim; + + CheckDim(dim); + + result = InitVector(dim); + + for (int i = 0; i < a->dim; i++) + result->x[i] = a->x[i]; + + for (int i = 0; i < b->dim; i++) + result->x[i + a->dim] = b->x[i]; + + PG_RETURN_POINTER(result); +} diff --git a/test/expected/functions.out b/test/expected/functions.out index 85d1a2f..e0da3b5 100644 --- a/test/expected/functions.out +++ b/test/expected/functions.out @@ -24,6 +24,14 @@ 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,3]'::vector || '[4,5]'::vector; + ?column? +------------- + [1,2,3,4,5] +(1 row) + +SELECT array_fill(0, ARRAY[16000])::vector || '[1]'::vector; +ERROR: vector cannot have more than 16000 dimensions SELECT '[1,2,3]'::vector = '[1,2,3]'; ?column? ---------- diff --git a/test/sql/functions.sql b/test/sql/functions.sql index 6235684..e87562d 100644 --- a/test/sql/functions.sql +++ b/test/sql/functions.sql @@ -6,6 +6,9 @@ SELECT '[1,2,3]'::vector * '[4,5,6]'; SELECT '[1e37]'::vector * '[1e37]'; SELECT '[1e-37]'::vector * '[1e-37]'; +SELECT '[1,2,3]'::vector || '[4,5]'::vector; +SELECT array_fill(0, ARRAY[16000])::vector || '[1]'::vector; + SELECT '[1,2,3]'::vector = '[1,2,3]'; SELECT '[1,2,3]'::vector = '[1,2]';