mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-22 12:07:34 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1982121694 | ||
|
|
9c8c4483db | ||
|
|
426ae1f16e | ||
|
|
06c3e68bef | ||
|
|
e5a620e02c | ||
|
|
092bb80f58 | ||
|
|
b690cd4d5d | ||
|
|
4e0d11acfe | ||
|
|
aa63f80b69 | ||
|
|
b8a7355731 | ||
|
|
3332669489 | ||
|
|
08c70bb57f | ||
|
|
eff0de6a64 | ||
|
|
3cf7ce6543 | ||
|
|
3cb6440744 | ||
|
|
b6a0d2b12b | ||
|
|
78632e3301 | ||
|
|
f8c85905c3 | ||
|
|
0a98a953cd | ||
|
|
a577c2df80 | ||
|
|
7ee9e86b10 | ||
|
|
5fdf5573a0 | ||
|
|
2b939edfee | ||
|
|
987026a559 | ||
|
|
d158eefa60 |
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -60,6 +60,7 @@ jobs:
|
|||||||
wget -q https://github.com/postgres/postgres/archive/refs/tags/REL_14_5.tar.gz
|
wget -q https://github.com/postgres/postgres/archive/refs/tags/REL_14_5.tar.gz
|
||||||
tar xf REL_14_5.tar.gz
|
tar xf REL_14_5.tar.gz
|
||||||
- run: make prove_installcheck PROVE_FLAGS="-I ./postgres-REL_14_5/src/test/perl" PERL5LIB="/Users/runner/perl5/lib/perl5"
|
- run: make prove_installcheck PROVE_FLAGS="-I ./postgres-REL_14_5/src/test/perl" PERL5LIB="/Users/runner/perl5/lib/perl5"
|
||||||
|
- run: make clean && /usr/local/opt/llvm@15/bin/scan-build --status-bugs make
|
||||||
windows:
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
if: ${{ !startsWith(github.ref_name, 'mac') }}
|
if: ${{ !startsWith(github.ref_name, 'mac') }}
|
||||||
|
|||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,8 +1,14 @@
|
|||||||
|
## 0.4.4 (2023-06-12)
|
||||||
|
|
||||||
|
- Improved error message for malformed vector literal
|
||||||
|
- Fixed segmentation fault with text input
|
||||||
|
- Fixed consecutive delimiters with text input
|
||||||
|
|
||||||
## 0.4.3 (2023-06-10)
|
## 0.4.3 (2023-06-10)
|
||||||
|
|
||||||
- Improved cost estimation
|
- Improved cost estimation
|
||||||
- Improved support for spaces with text representation
|
- Improved support for spaces with text input
|
||||||
- Fixed infinite and NaN values with binary representation
|
- Fixed infinite and NaN values with binary input
|
||||||
- Fixed infinite values with vector addition and subtraction
|
- Fixed infinite values with vector addition and subtraction
|
||||||
- Fixed infinite values with list centers
|
- Fixed infinite values with list centers
|
||||||
- Fixed compilation error when `float8` is pass by reference
|
- Fixed compilation error when `float8` is pass by reference
|
||||||
|
|||||||
@@ -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.4.3",
|
"version": "0.4.4",
|
||||||
"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.4.3",
|
"version": "0.4.4",
|
||||||
"abstract": "Open-source vector similarity search for Postgres"
|
"abstract": "Open-source vector similarity search for Postgres"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
EXTENSION = vector
|
EXTENSION = vector
|
||||||
EXTVERSION = 0.4.3
|
EXTVERSION = 0.4.4
|
||||||
|
|
||||||
MODULE_big = vector
|
MODULE_big = vector
|
||||||
DATA = $(wildcard sql/*--*.sql)
|
DATA = $(wildcard sql/*--*.sql)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
EXTENSION = vector
|
EXTENSION = vector
|
||||||
EXTVERSION = 0.4.3
|
EXTVERSION = 0.4.4
|
||||||
|
|
||||||
OBJS = src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\vector.obj
|
OBJS = src\ivfbuild.obj src\ivfflat.obj src\ivfinsert.obj src\ivfkmeans.obj src\ivfscan.obj src\ivfutils.obj src\ivfvacuum.obj src\vector.obj
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Compile and install the extension (supports Postgres 11+)
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd /tmp
|
cd /tmp
|
||||||
git clone --branch v0.4.3 https://github.com/pgvector/pgvector.git
|
git clone --branch v0.4.4 https://github.com/pgvector/pgvector.git
|
||||||
cd pgvector
|
cd pgvector
|
||||||
make
|
make
|
||||||
make install # may need sudo
|
make install # may need sudo
|
||||||
@@ -163,7 +163,7 @@ Three keys to achieving good recall are:
|
|||||||
|
|
||||||
1. Create the index *after* the table has some data
|
1. Create the index *after* the table has some data
|
||||||
2. Choose an appropriate number of lists - a good place to start is `rows / 1000` for up to 1M rows and `sqrt(rows)` for over 1M rows
|
2. Choose an appropriate number of lists - a good place to start is `rows / 1000` for up to 1M rows and `sqrt(rows)` for over 1M rows
|
||||||
3. When querying, specify an appropriate number of [probes](#query-options) (higher is better for recall, lower is better for speed) - a good place to start is `lists / 10` for up to 1M rows and `sqrt(lists)` for over 1M rows
|
3. When querying, specify an appropriate number of [probes](#query-options) (higher is better for recall, lower is better for speed) - a good place to start is `sqrt(lists)`
|
||||||
|
|
||||||
Add an index for each distance function you want to use.
|
Add an index for each distance function you want to use.
|
||||||
|
|
||||||
@@ -397,7 +397,7 @@ Support for Windows is currently experimental. Use `nmake` to build:
|
|||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
set "PGROOT=C:\Program Files\PostgreSQL\15"
|
set "PGROOT=C:\Program Files\PostgreSQL\15"
|
||||||
git clone --branch v0.4.3 https://github.com/pgvector/pgvector.git
|
git clone --branch v0.4.4 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
|
||||||
@@ -418,7 +418,7 @@ 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.4.3 https://github.com/pgvector/pgvector.git
|
git clone --branch v0.4.4 https://github.com/pgvector/pgvector.git
|
||||||
cd pgvector
|
cd pgvector
|
||||||
docker build --build-arg PG_MAJOR=15 -t myuser/pgvector .
|
docker build --build-arg PG_MAJOR=15 -t myuser/pgvector .
|
||||||
```
|
```
|
||||||
|
|||||||
2
sql/vector--0.4.3--0.4.4.sql
Normal file
2
sql/vector--0.4.3--0.4.4.sql
Normal 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.4.4'" to load this file. \quit
|
||||||
@@ -568,6 +568,21 @@ PrintKmeansMetrics(IvfflatBuildState * buildstate)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan table for tuples to index
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ScanTable(IvfflatBuildState * buildstate)
|
||||||
|
{
|
||||||
|
#if PG_VERSION_NUM >= 120000
|
||||||
|
buildstate->reltuples = table_index_build_scan(buildstate->heap, buildstate->index, buildstate->indexInfo,
|
||||||
|
true, true, BuildCallback, (void *) buildstate, NULL);
|
||||||
|
#else
|
||||||
|
buildstate->reltuples = IndexBuildHeapScan(buildstate->heap, buildstate->index, buildstate->indexInfo,
|
||||||
|
true, BuildCallback, (void *) buildstate, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create entry pages
|
* Create entry pages
|
||||||
*/
|
*/
|
||||||
@@ -585,25 +600,17 @@ CreateEntryPages(IvfflatBuildState * buildstate, ForkNumber forkNum)
|
|||||||
|
|
||||||
/* Add tuples to sort */
|
/* Add tuples to sort */
|
||||||
if (buildstate->heap != NULL)
|
if (buildstate->heap != NULL)
|
||||||
{
|
IvfflatBench("assign tuples", ScanTable(buildstate));
|
||||||
#if PG_VERSION_NUM >= 120000
|
|
||||||
buildstate->reltuples = table_index_build_scan(buildstate->heap, buildstate->index, buildstate->indexInfo,
|
|
||||||
true, true, BuildCallback, (void *) buildstate, NULL);
|
|
||||||
#else
|
|
||||||
buildstate->reltuples = IndexBuildHeapScan(buildstate->heap, buildstate->index, buildstate->indexInfo,
|
|
||||||
true, BuildCallback, (void *) buildstate, NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sort */
|
/* Sort */
|
||||||
tuplesort_performsort(buildstate->sortstate);
|
IvfflatBench("sort tuples", tuplesort_performsort(buildstate->sortstate));
|
||||||
|
|
||||||
#ifdef IVFFLAT_KMEANS_DEBUG
|
#ifdef IVFFLAT_KMEANS_DEBUG
|
||||||
PrintKmeansMetrics(buildstate);
|
PrintKmeansMetrics(buildstate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Insert */
|
/* Insert */
|
||||||
InsertTuples(buildstate->index, buildstate, forkNum);
|
IvfflatBench("load tuples", InsertTuples(buildstate->index, buildstate, forkNum));
|
||||||
tuplesort_end(buildstate->sortstate);
|
tuplesort_end(buildstate->sortstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,7 +628,7 @@ BuildIndex(Relation heap, Relation index, IndexInfo *indexInfo,
|
|||||||
/* Create pages */
|
/* Create pages */
|
||||||
CreateMetaPage(index, buildstate->dimensions, buildstate->lists, forkNum);
|
CreateMetaPage(index, buildstate->dimensions, buildstate->lists, forkNum);
|
||||||
CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo);
|
CreateListPages(index, buildstate->centers, buildstate->dimensions, buildstate->lists, forkNum, &buildstate->listInfo);
|
||||||
IvfflatBench("CreateEntryPages", CreateEntryPages(buildstate, forkNum));
|
CreateEntryPages(buildstate, forkNum);
|
||||||
|
|
||||||
FreeBuildState(buildstate);
|
FreeBuildState(buildstate);
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/vector.c
107
src/vector.c
@@ -42,7 +42,7 @@ CheckDims(Vector * a, Vector * b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure expected dimension
|
* Ensure expected dimensions
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
CheckExpectedDim(int32 typmod, int dim)
|
CheckExpectedDim(int32 typmod, int dim)
|
||||||
@@ -53,7 +53,9 @@ CheckExpectedDim(int32 typmod, int dim)
|
|||||||
errmsg("expected %d dimensions, not %d", typmod, dim)));
|
errmsg("expected %d dimensions, not %d", typmod, dim)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure valid dimensions
|
||||||
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
CheckDim(int dim)
|
CheckDim(int dim)
|
||||||
{
|
{
|
||||||
@@ -72,27 +74,17 @@ CheckDim(int dim)
|
|||||||
* Ensure finite elements
|
* Ensure finite elements
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
CheckElementOrFree(float value, Vector * vec)
|
CheckElement(float value)
|
||||||
{
|
{
|
||||||
if (isnan(value))
|
if (isnan(value))
|
||||||
{
|
|
||||||
if (vec != NULL)
|
|
||||||
pfree(vec);
|
|
||||||
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("NaN not allowed in vector")));
|
errmsg("NaN not allowed in vector")));
|
||||||
}
|
|
||||||
|
|
||||||
if (isinf(value))
|
if (isinf(value))
|
||||||
{
|
|
||||||
if (vec != NULL)
|
|
||||||
pfree(vec);
|
|
||||||
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("infinite value not allowed in vector")));
|
errmsg("infinite value not allowed in vector")));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -135,30 +127,6 @@ float_overflow_error(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Print vector - useful for debugging
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
PrintVector(char *msg, Vector * vector)
|
|
||||||
{
|
|
||||||
StringInfoData buf;
|
|
||||||
int dim = vector->dim;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
initStringInfo(&buf);
|
|
||||||
|
|
||||||
appendStringInfoChar(&buf, '[');
|
|
||||||
for (i = 0; i < dim; i++)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
appendStringInfoString(&buf, ",");
|
|
||||||
appendStringInfoString(&buf, float8out_internal(vector->x[i]));
|
|
||||||
}
|
|
||||||
appendStringInfoChar(&buf, ']');
|
|
||||||
|
|
||||||
elog(INFO, "%s = %s", msg, buf.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert textual representation to internal representation
|
* Convert textual representation to internal representation
|
||||||
*/
|
*/
|
||||||
@@ -174,6 +142,7 @@ vector_in(PG_FUNCTION_ARGS)
|
|||||||
char *pt;
|
char *pt;
|
||||||
char *stringEnd;
|
char *stringEnd;
|
||||||
Vector *result;
|
Vector *result;
|
||||||
|
char *lit = pstrdup(str);
|
||||||
|
|
||||||
while (vector_isspace(*str))
|
while (vector_isspace(*str))
|
||||||
str++;
|
str++;
|
||||||
@@ -181,7 +150,7 @@ vector_in(PG_FUNCTION_ARGS)
|
|||||||
if (*str != '[')
|
if (*str != '[')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed vector literal: \"%s\"", str),
|
errmsg("malformed vector literal: \"%s\"", lit),
|
||||||
errdetail("Vector contents must start with \"[\".")));
|
errdetail("Vector contents must start with \"[\".")));
|
||||||
|
|
||||||
str++;
|
str++;
|
||||||
@@ -195,15 +164,24 @@ vector_in(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("vector cannot have more than %d dimensions", VECTOR_MAX_DIM)));
|
errmsg("vector cannot have more than %d dimensions", VECTOR_MAX_DIM)));
|
||||||
|
|
||||||
|
while (vector_isspace(*pt))
|
||||||
|
pt++;
|
||||||
|
|
||||||
|
/* Check for empty string like float4in */
|
||||||
|
if (*pt == '\0')
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("invalid input syntax for type vector: \"%s\"", lit)));
|
||||||
|
|
||||||
/* Use strtof like float4in to avoid a double-rounding problem */
|
/* Use strtof like float4in to avoid a double-rounding problem */
|
||||||
x[dim] = strtof(pt, &stringEnd);
|
x[dim] = strtof(pt, &stringEnd);
|
||||||
CheckElementOrFree(x[dim], NULL);
|
CheckElement(x[dim]);
|
||||||
dim++;
|
dim++;
|
||||||
|
|
||||||
if (stringEnd == pt)
|
if (stringEnd == pt)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type vector: \"%s\"", pt)));
|
errmsg("invalid input syntax for type vector: \"%s\"", lit)));
|
||||||
|
|
||||||
while (vector_isspace(*stringEnd))
|
while (vector_isspace(*stringEnd))
|
||||||
stringEnd++;
|
stringEnd++;
|
||||||
@@ -211,15 +189,15 @@ vector_in(PG_FUNCTION_ARGS)
|
|||||||
if (*stringEnd != '\0' && *stringEnd != ']')
|
if (*stringEnd != '\0' && *stringEnd != ']')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("invalid input syntax for type vector: \"%s\"", pt)));
|
errmsg("invalid input syntax for type vector: \"%s\"", lit)));
|
||||||
|
|
||||||
pt = strtok(NULL, ",");
|
pt = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*stringEnd != ']')
|
if (stringEnd == NULL || *stringEnd != ']')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed vector literal"),
|
errmsg("malformed vector literal: \"%s\"", lit),
|
||||||
errdetail("Unexpected end of input.")));
|
errdetail("Unexpected end of input.")));
|
||||||
|
|
||||||
stringEnd++;
|
stringEnd++;
|
||||||
@@ -231,14 +209,25 @@ vector_in(PG_FUNCTION_ARGS)
|
|||||||
if (*stringEnd != '\0')
|
if (*stringEnd != '\0')
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed vector literal"),
|
errmsg("malformed vector literal: \"%s\"", lit),
|
||||||
errdetail("Junk after closing right brace.")));
|
errdetail("Junk after closing right brace.")));
|
||||||
|
|
||||||
|
/* Ensure no consecutive delimiters since strtok skips */
|
||||||
|
for (pt = lit + 1; *pt != '\0'; pt++)
|
||||||
|
{
|
||||||
|
if (pt[-1] == ',' && *pt == ',')
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
|
errmsg("malformed vector literal: \"%s\"", lit)));
|
||||||
|
}
|
||||||
|
|
||||||
if (dim < 1)
|
if (dim < 1)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("vector must have at least 1 dimension")));
|
errmsg("vector must have at least 1 dimension")));
|
||||||
|
|
||||||
|
pfree(lit);
|
||||||
|
|
||||||
CheckExpectedDim(typmod, dim);
|
CheckExpectedDim(typmod, dim);
|
||||||
|
|
||||||
result = InitVector(dim);
|
result = InitVector(dim);
|
||||||
@@ -309,6 +298,18 @@ vector_out(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_CSTRING(buf);
|
PG_RETURN_CSTRING(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print vector - useful for debugging
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PrintVector(char *msg, Vector * vector)
|
||||||
|
{
|
||||||
|
char *out = DatumGetPointer(DirectFunctionCall1(vector_out, PointerGetDatum(vector)));
|
||||||
|
|
||||||
|
elog(INFO, "%s = %s", msg, out);
|
||||||
|
pfree(out);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert type modifier
|
* Convert type modifier
|
||||||
*/
|
*/
|
||||||
@@ -369,7 +370,7 @@ vector_recv(PG_FUNCTION_ARGS)
|
|||||||
for (i = 0; i < dim; i++)
|
for (i = 0; i < dim; i++)
|
||||||
{
|
{
|
||||||
result->x[i] = pq_getmsgfloat4(buf);
|
result->x[i] = pq_getmsgfloat4(buf);
|
||||||
CheckElementOrFree(result->x[i], result);
|
CheckElement(result->x[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
@@ -461,7 +462,7 @@ array_to_vector(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("unsupported array type")));
|
errmsg("unsupported array type")));
|
||||||
|
|
||||||
CheckElementOrFree(result->x[i], result);
|
CheckElement(result->x[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
@@ -703,10 +704,7 @@ vector_add(PG_FUNCTION_ARGS)
|
|||||||
for (int i = 0, imax = a->dim; i < imax; i++)
|
for (int i = 0, imax = a->dim; i < imax; i++)
|
||||||
{
|
{
|
||||||
if (isinf(rx[i]))
|
if (isinf(rx[i]))
|
||||||
{
|
|
||||||
pfree(result);
|
|
||||||
float_overflow_error();
|
float_overflow_error();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
@@ -739,10 +737,7 @@ vector_sub(PG_FUNCTION_ARGS)
|
|||||||
for (int i = 0, imax = a->dim; i < imax; i++)
|
for (int i = 0, imax = a->dim; i < imax; i++)
|
||||||
{
|
{
|
||||||
if (isinf(rx[i]))
|
if (isinf(rx[i]))
|
||||||
{
|
|
||||||
pfree(result);
|
|
||||||
float_overflow_error();
|
float_overflow_error();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
@@ -905,10 +900,7 @@ vector_accum(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Check for overflow */
|
/* Check for overflow */
|
||||||
if (isinf(v))
|
if (isinf(v))
|
||||||
{
|
|
||||||
pfree(statedatums);
|
|
||||||
float_overflow_error();
|
float_overflow_error();
|
||||||
}
|
|
||||||
|
|
||||||
statedatums[i + 1] = Float8GetDatum(v);
|
statedatums[i + 1] = Float8GetDatum(v);
|
||||||
}
|
}
|
||||||
@@ -977,10 +969,7 @@ vector_combine(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* Check for overflow */
|
/* Check for overflow */
|
||||||
if (isinf(v))
|
if (isinf(v))
|
||||||
{
|
|
||||||
pfree(statedatums);
|
|
||||||
float_overflow_error();
|
float_overflow_error();
|
||||||
}
|
|
||||||
|
|
||||||
statedatums[i] = Float8GetDatum(v);
|
statedatums[i] = Float8GetDatum(v);
|
||||||
}
|
}
|
||||||
@@ -1025,7 +1014,7 @@ vector_avg(PG_FUNCTION_ARGS)
|
|||||||
for (int i = 0; i < dim; i++)
|
for (int i = 0; i < dim; i++)
|
||||||
{
|
{
|
||||||
result->x[i] = statevalues[i + 1] / n;
|
result->x[i] = statevalues[i + 1] / n;
|
||||||
CheckElementOrFree(result->x[i], result);
|
CheckElement(result->x[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
PG_RETURN_POINTER(result);
|
||||||
|
|||||||
@@ -4,13 +4,19 @@ SELECT '[1,2,3]'::vector;
|
|||||||
[1,2,3]
|
[1,2,3]
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '[-1,2,3]'::vector;
|
SELECT '[-1,-2,-3]'::vector;
|
||||||
vector
|
vector
|
||||||
----------
|
------------
|
||||||
[-1,2,3]
|
[-1,-2,-3]
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT ' [ 1, 2 , 3 ] '::vector(3);
|
SELECT '[1.,2.,3.]'::vector;
|
||||||
|
vector
|
||||||
|
---------
|
||||||
|
[1,2,3]
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT ' [ 1, 2 , 3 ] '::vector;
|
||||||
vector
|
vector
|
||||||
---------
|
---------
|
||||||
[1,2,3]
|
[1,2,3]
|
||||||
@@ -23,7 +29,7 @@ SELECT '[1.23456]'::vector;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '[hello,1]'::vector;
|
SELECT '[hello,1]'::vector;
|
||||||
ERROR: invalid input syntax for type vector: "hello"
|
ERROR: invalid input syntax for type vector: "[hello,1]"
|
||||||
LINE 1: SELECT '[hello,1]'::vector;
|
LINE 1: SELECT '[hello,1]'::vector;
|
||||||
^
|
^
|
||||||
SELECT '[NaN,1]'::vector;
|
SELECT '[NaN,1]'::vector;
|
||||||
@@ -38,17 +44,35 @@ SELECT '[-Infinity,1]'::vector;
|
|||||||
ERROR: infinite value not allowed in vector
|
ERROR: infinite value not allowed in vector
|
||||||
LINE 1: SELECT '[-Infinity,1]'::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;
|
SELECT '[4e38,1]'::vector;
|
||||||
ERROR: infinite value not allowed in vector
|
ERROR: infinite value not allowed in vector
|
||||||
LINE 1: SELECT '[4e38,1]'::vector;
|
LINE 1: SELECT '[4e38,1]'::vector;
|
||||||
^
|
^
|
||||||
SELECT '[1,2,3'::vector;
|
SELECT '[1,2,3'::vector;
|
||||||
ERROR: malformed vector literal
|
ERROR: malformed vector literal: "[1,2,3"
|
||||||
LINE 1: SELECT '[1,2,3'::vector;
|
LINE 1: SELECT '[1,2,3'::vector;
|
||||||
^
|
^
|
||||||
DETAIL: Unexpected end of input.
|
DETAIL: Unexpected end of input.
|
||||||
SELECT '[1,2,3]9'::vector;
|
SELECT '[1,2,3]9'::vector;
|
||||||
ERROR: malformed vector literal
|
ERROR: malformed vector literal: "[1,2,3]9"
|
||||||
LINE 1: SELECT '[1,2,3]9'::vector;
|
LINE 1: SELECT '[1,2,3]9'::vector;
|
||||||
^
|
^
|
||||||
DETAIL: Junk after closing right brace.
|
DETAIL: Junk after closing right brace.
|
||||||
@@ -57,14 +81,36 @@ ERROR: malformed vector literal: "1,2,3"
|
|||||||
LINE 1: SELECT '1,2,3'::vector;
|
LINE 1: SELECT '1,2,3'::vector;
|
||||||
^
|
^
|
||||||
DETAIL: Vector contents must start with "[".
|
DETAIL: Vector contents must start with "[".
|
||||||
|
SELECT '['::vector;
|
||||||
|
ERROR: malformed vector literal: "["
|
||||||
|
LINE 1: SELECT '['::vector;
|
||||||
|
^
|
||||||
|
DETAIL: Unexpected end of input.
|
||||||
|
SELECT '[,'::vector;
|
||||||
|
ERROR: malformed vector literal: "[,"
|
||||||
|
LINE 1: SELECT '[,'::vector;
|
||||||
|
^
|
||||||
|
DETAIL: Unexpected end of input.
|
||||||
SELECT '[]'::vector;
|
SELECT '[]'::vector;
|
||||||
ERROR: vector must have at least 1 dimension
|
ERROR: vector must have at least 1 dimension
|
||||||
LINE 1: SELECT '[]'::vector;
|
LINE 1: SELECT '[]'::vector;
|
||||||
^
|
^
|
||||||
SELECT '[1,]'::vector;
|
SELECT '[1,]'::vector;
|
||||||
ERROR: invalid input syntax for type vector: "]"
|
ERROR: invalid input syntax for type vector: "[1,]"
|
||||||
LINE 1: SELECT '[1,]'::vector;
|
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: malformed vector literal: "[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(2);
|
SELECT '[1,2,3]'::vector(2);
|
||||||
ERROR: expected 2 dimensions, not 3
|
ERROR: expected 2 dimensions, not 3
|
||||||
SELECT unnest('{"[1,2,3]", "[4,5,6]"}'::vector[]);
|
SELECT unnest('{"[1,2,3]", "[4,5,6]"}'::vector[]);
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
SELECT '[1,2,3]'::vector;
|
SELECT '[1,2,3]'::vector;
|
||||||
SELECT '[-1,2,3]'::vector;
|
SELECT '[-1,-2,-3]'::vector;
|
||||||
SELECT ' [ 1, 2 , 3 ] '::vector(3);
|
SELECT '[1.,2.,3.]'::vector;
|
||||||
|
SELECT ' [ 1, 2 , 3 ] '::vector;
|
||||||
SELECT '[1.23456]'::vector;
|
SELECT '[1.23456]'::vector;
|
||||||
SELECT '[hello,1]'::vector;
|
SELECT '[hello,1]'::vector;
|
||||||
SELECT '[NaN,1]'::vector;
|
SELECT '[NaN,1]'::vector;
|
||||||
SELECT '[Infinity,1]'::vector;
|
SELECT '[Infinity,1]'::vector;
|
||||||
SELECT '[-Infinity,1]'::vector;
|
SELECT '[-Infinity,1]'::vector;
|
||||||
|
SELECT '[1.5e38,-1.5e38]'::vector;
|
||||||
|
SELECT '[1.5e+38,-1.5e+38]'::vector;
|
||||||
|
SELECT '[1.5e-38,-1.5e-38]'::vector;
|
||||||
SELECT '[4e38,1]'::vector;
|
SELECT '[4e38,1]'::vector;
|
||||||
SELECT '[1,2,3'::vector;
|
SELECT '[1,2,3'::vector;
|
||||||
SELECT '[1,2,3]9'::vector;
|
SELECT '[1,2,3]9'::vector;
|
||||||
SELECT '1,2,3'::vector;
|
SELECT '1,2,3'::vector;
|
||||||
|
SELECT '['::vector;
|
||||||
|
SELECT '[,'::vector;
|
||||||
SELECT '[]'::vector;
|
SELECT '[]'::vector;
|
||||||
SELECT '[1,]'::vector;
|
SELECT '[1,]'::vector;
|
||||||
|
SELECT '[1a]'::vector;
|
||||||
|
SELECT '[1,,3]'::vector;
|
||||||
|
SELECT '[1, ,3]'::vector;
|
||||||
SELECT '[1,2,3]'::vector(2);
|
SELECT '[1,2,3]'::vector(2);
|
||||||
|
|
||||||
SELECT unnest('{"[1,2,3]", "[4,5,6]"}'::vector[]);
|
SELECT unnest('{"[1,2,3]", "[4,5,6]"}'::vector[]);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
comment = 'vector data type and ivfflat access method'
|
comment = 'vector data type and ivfflat access method'
|
||||||
default_version = '0.4.3'
|
default_version = '0.4.4'
|
||||||
module_pathname = '$libdir/vector'
|
module_pathname = '$libdir/vector'
|
||||||
relocatable = true
|
relocatable = true
|
||||||
|
|||||||
Reference in New Issue
Block a user