mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-10 06:40:57 +08:00
Removed dimensions from sparsevec
This commit is contained in:
@@ -173,9 +173,6 @@ CREATE FUNCTION sparsevec_in(cstring, oid, integer) RETURNS sparsevec
|
|||||||
CREATE FUNCTION sparsevec_out(sparsevec) RETURNS cstring
|
CREATE FUNCTION sparsevec_out(sparsevec) RETURNS cstring
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
CREATE FUNCTION sparsevec_typmod_in(cstring[]) RETURNS integer
|
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
||||||
|
|
||||||
CREATE FUNCTION sparsevec_recv(internal, oid, integer) RETURNS sparsevec
|
CREATE FUNCTION sparsevec_recv(internal, oid, integer) RETURNS sparsevec
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
@@ -185,7 +182,6 @@ CREATE FUNCTION sparsevec_send(sparsevec) RETURNS bytea
|
|||||||
CREATE TYPE sparsevec (
|
CREATE TYPE sparsevec (
|
||||||
INPUT = sparsevec_in,
|
INPUT = sparsevec_in,
|
||||||
OUTPUT = sparsevec_out,
|
OUTPUT = sparsevec_out,
|
||||||
TYPMOD_IN = sparsevec_typmod_in,
|
|
||||||
RECEIVE = sparsevec_recv,
|
RECEIVE = sparsevec_recv,
|
||||||
SEND = sparsevec_send,
|
SEND = sparsevec_send,
|
||||||
STORAGE = external
|
STORAGE = external
|
||||||
|
|||||||
@@ -480,9 +480,6 @@ CREATE FUNCTION sparsevec_in(cstring, oid, integer) RETURNS sparsevec
|
|||||||
CREATE FUNCTION sparsevec_out(sparsevec) RETURNS cstring
|
CREATE FUNCTION sparsevec_out(sparsevec) RETURNS cstring
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
CREATE FUNCTION sparsevec_typmod_in(cstring[]) RETURNS integer
|
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
|
||||||
|
|
||||||
CREATE FUNCTION sparsevec_recv(internal, oid, integer) RETURNS sparsevec
|
CREATE FUNCTION sparsevec_recv(internal, oid, integer) RETURNS sparsevec
|
||||||
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
|
||||||
|
|
||||||
@@ -492,7 +489,6 @@ CREATE FUNCTION sparsevec_send(sparsevec) RETURNS bytea
|
|||||||
CREATE TYPE sparsevec (
|
CREATE TYPE sparsevec (
|
||||||
INPUT = sparsevec_in,
|
INPUT = sparsevec_in,
|
||||||
OUTPUT = sparsevec_out,
|
OUTPUT = sparsevec_out,
|
||||||
TYPMOD_IN = sparsevec_typmod_in,
|
|
||||||
RECEIVE = sparsevec_recv,
|
RECEIVE = sparsevec_recv,
|
||||||
SEND = sparsevec_send,
|
SEND = sparsevec_send,
|
||||||
STORAGE = external
|
STORAGE = external
|
||||||
|
|||||||
@@ -681,8 +681,6 @@ GetMaxDimensions(HnswType type)
|
|||||||
maxDimensions *= 2;
|
maxDimensions *= 2;
|
||||||
else if (type == HNSW_TYPE_BIT)
|
else if (type == HNSW_TYPE_BIT)
|
||||||
maxDimensions *= 32;
|
maxDimensions *= 32;
|
||||||
else if (type == HNSW_TYPE_SPARSEVEC)
|
|
||||||
maxDimensions = INT_MAX;
|
|
||||||
|
|
||||||
return maxDimensions;
|
return maxDimensions;
|
||||||
}
|
}
|
||||||
@@ -693,8 +691,6 @@ GetMaxDimensions(HnswType type)
|
|||||||
static void
|
static void
|
||||||
InitBuildState(HnswBuildState * buildstate, Relation heap, Relation index, IndexInfo *indexInfo, ForkNumber forkNum)
|
InitBuildState(HnswBuildState * buildstate, Relation heap, Relation index, IndexInfo *indexInfo, ForkNumber forkNum)
|
||||||
{
|
{
|
||||||
int maxDimensions;
|
|
||||||
|
|
||||||
buildstate->heap = heap;
|
buildstate->heap = heap;
|
||||||
buildstate->index = index;
|
buildstate->index = index;
|
||||||
buildstate->indexInfo = indexInfo;
|
buildstate->indexInfo = indexInfo;
|
||||||
@@ -705,14 +701,17 @@ InitBuildState(HnswBuildState * buildstate, Relation heap, Relation index, Index
|
|||||||
buildstate->efConstruction = HnswGetEfConstruction(index);
|
buildstate->efConstruction = HnswGetEfConstruction(index);
|
||||||
buildstate->dimensions = TupleDescAttr(index->rd_att, 0)->atttypmod;
|
buildstate->dimensions = TupleDescAttr(index->rd_att, 0)->atttypmod;
|
||||||
|
|
||||||
maxDimensions = GetMaxDimensions(buildstate->type);
|
|
||||||
|
|
||||||
/* Require column to have dimensions to be indexed */
|
if (buildstate->type != HNSW_TYPE_SPARSEVEC)
|
||||||
if (buildstate->dimensions < 0)
|
{
|
||||||
elog(ERROR, "column does not have dimensions");
|
int maxDimensions = GetMaxDimensions(buildstate->type);
|
||||||
|
|
||||||
if (buildstate->dimensions > maxDimensions)
|
if (buildstate->dimensions < 0)
|
||||||
elog(ERROR, "column cannot have more than %d dimensions for hnsw index", maxDimensions);
|
elog(ERROR, "column does not have dimensions");
|
||||||
|
|
||||||
|
if (buildstate->dimensions > maxDimensions)
|
||||||
|
elog(ERROR, "column cannot have more than %d dimensions for hnsw index", maxDimensions);
|
||||||
|
}
|
||||||
|
|
||||||
if (buildstate->efConstruction < 2 * buildstate->m)
|
if (buildstate->efConstruction < 2 * buildstate->m)
|
||||||
elog(ERROR, "ef_construction must be greater than or equal to 2 * m");
|
elog(ERROR, "ef_construction must be greater than or equal to 2 * m");
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ HnswNormValue(FmgrInfo *procinfo, Oid collation, Datum *value, HnswType type)
|
|||||||
else if (type == HNSW_TYPE_SPARSEVEC)
|
else if (type == HNSW_TYPE_SPARSEVEC)
|
||||||
{
|
{
|
||||||
SparseVector *v = DatumGetSparseVector(*value);
|
SparseVector *v = DatumGetSparseVector(*value);
|
||||||
SparseVector *result = InitSparseVector(v->dim, v->nnz);
|
SparseVector *result = InitSparseVector(v->nnz);
|
||||||
float *vx = SPARSEVEC_VALUES(v);
|
float *vx = SPARSEVEC_VALUES(v);
|
||||||
float *rx = SPARSEVEC_VALUES(result);
|
float *rx = SPARSEVEC_VALUES(result);
|
||||||
|
|
||||||
|
|||||||
168
src/sparsevec.c
168
src/sparsevec.c
@@ -18,69 +18,28 @@
|
|||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure same dimensions
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
CheckDims(SparseVector * a, SparseVector * b)
|
|
||||||
{
|
|
||||||
if (a->dim != b->dim)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
|
||||||
errmsg("different sparsevec dimensions %d and %d", a->dim, b->dim)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure expected dimensions
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
CheckExpectedDim(int32 typmod, int dim)
|
|
||||||
{
|
|
||||||
if (typmod != -1 && typmod != dim)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
|
||||||
errmsg("expected %d dimensions, not %d", typmod, dim)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure valid dimensions
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
CheckDim(int dim)
|
|
||||||
{
|
|
||||||
if (dim < 1)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
|
||||||
errmsg("sparsevec must have at least 1 dimension")));
|
|
||||||
|
|
||||||
if (dim > SPARSEVEC_MAX_DIM)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
|
||||||
errmsg("sparsevec cannot have more than %d dimensions", SPARSEVEC_MAX_DIM)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure valid nnz
|
* Ensure valid nnz
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
CheckNnz(int nnz, int dim)
|
CheckNnz(int nnz)
|
||||||
{
|
{
|
||||||
if (nnz < 0)
|
if (nnz < 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("sparsevec must have at least one element")));
|
errmsg("sparsevec must have at least one element")));
|
||||||
|
|
||||||
if (nnz > dim)
|
if (nnz > SPARSEVEC_MAX_NNZ)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
errmsg("sparsevec cannot have more elements than dimensions")));
|
errmsg("sparsevec cannot have more elements than non-zero elements")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure valid index
|
* Ensure valid index
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
CheckIndex(int32 *indices, int i, int dim)
|
CheckIndex(int32 *indices, int i)
|
||||||
{
|
{
|
||||||
int32 index = indices[i];
|
int32 index = indices[i];
|
||||||
|
|
||||||
@@ -89,11 +48,6 @@ CheckIndex(int32 *indices, int i, int dim)
|
|||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("index must not be negative")));
|
errmsg("index must not be negative")));
|
||||||
|
|
||||||
if (index >= dim)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
|
||||||
errmsg("index must be less than dimensions")));
|
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
if (index < indices[i - 1])
|
if (index < indices[i - 1])
|
||||||
@@ -129,7 +83,7 @@ CheckElement(float value)
|
|||||||
* Allocate and initialize a new sparse vector
|
* Allocate and initialize a new sparse vector
|
||||||
*/
|
*/
|
||||||
SparseVector *
|
SparseVector *
|
||||||
InitSparseVector(int dim, int nnz)
|
InitSparseVector(int nnz)
|
||||||
{
|
{
|
||||||
SparseVector *result;
|
SparseVector *result;
|
||||||
int size;
|
int size;
|
||||||
@@ -137,7 +91,6 @@ InitSparseVector(int dim, int nnz)
|
|||||||
size = SPARSEVEC_SIZE(nnz);
|
size = SPARSEVEC_SIZE(nnz);
|
||||||
result = (SparseVector *) palloc0(size);
|
result = (SparseVector *) palloc0(size);
|
||||||
SET_VARSIZE(result, size);
|
SET_VARSIZE(result, size);
|
||||||
result->dim = dim;
|
|
||||||
result->nnz = nnz;
|
result->nnz = nnz;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -167,8 +120,6 @@ Datum
|
|||||||
sparsevec_in(PG_FUNCTION_ARGS)
|
sparsevec_in(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
char *lit = PG_GETARG_CSTRING(0);
|
char *lit = PG_GETARG_CSTRING(0);
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
|
||||||
int dim;
|
|
||||||
char *pt;
|
char *pt;
|
||||||
char *stringEnd;
|
char *stringEnd;
|
||||||
SparseVector *result;
|
SparseVector *result;
|
||||||
@@ -190,6 +141,11 @@ sparsevec_in(PG_FUNCTION_ARGS)
|
|||||||
pt++;
|
pt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (maxNnz > SPARSEVEC_MAX_NNZ)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
|
||||||
|
errmsg("sparsevec cannot have more than %d non-zero elements", SPARSEVEC_MAX_NNZ)));
|
||||||
|
|
||||||
indices = palloc(maxNnz * sizeof(int32));
|
indices = palloc(maxNnz * sizeof(int32));
|
||||||
values = palloc(maxNnz * sizeof(float));
|
values = palloc(maxNnz * sizeof(float));
|
||||||
|
|
||||||
@@ -297,24 +253,6 @@ sparsevec_in(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
stringEnd++;
|
stringEnd++;
|
||||||
|
|
||||||
if (*stringEnd != '/')
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("malformed sparsevec literal: \"%s\"", lit),
|
|
||||||
errdetail("Unexpected end of input.")));
|
|
||||||
|
|
||||||
stringEnd++;
|
|
||||||
|
|
||||||
/* Use similar logic as int2vectorin */
|
|
||||||
errno = 0;
|
|
||||||
pt = stringEnd;
|
|
||||||
dim = strtol(pt, &stringEnd, 10);
|
|
||||||
|
|
||||||
if (stringEnd == pt)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
||||||
errmsg("invalid input syntax for type sparsevec: \"%s\"", lit)));
|
|
||||||
|
|
||||||
/* Only whitespace is allowed after the closing brace */
|
/* Only whitespace is allowed after the closing brace */
|
||||||
while (sparsevec_isspace(*stringEnd))
|
while (sparsevec_isspace(*stringEnd))
|
||||||
stringEnd++;
|
stringEnd++;
|
||||||
@@ -323,21 +261,18 @@ sparsevec_in(PG_FUNCTION_ARGS)
|
|||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
||||||
errmsg("malformed sparsevec literal: \"%s\"", lit),
|
errmsg("malformed sparsevec literal: \"%s\"", lit),
|
||||||
errdetail("Junk after closing.")));
|
errdetail("Junk after closing right brace.")));
|
||||||
|
|
||||||
pfree(litcopy);
|
pfree(litcopy);
|
||||||
|
|
||||||
CheckDim(dim);
|
result = InitSparseVector(nnz);
|
||||||
CheckExpectedDim(typmod, dim);
|
|
||||||
|
|
||||||
result = InitSparseVector(dim, nnz);
|
|
||||||
rvalues = SPARSEVEC_VALUES(result);
|
rvalues = SPARSEVEC_VALUES(result);
|
||||||
for (int i = 0; i < nnz; i++)
|
for (int i = 0; i < nnz; i++)
|
||||||
{
|
{
|
||||||
result->indices[i] = indices[i];
|
result->indices[i] = indices[i];
|
||||||
rvalues[i] = values[i];
|
rvalues[i] = values[i];
|
||||||
|
|
||||||
CheckIndex(result->indices, i, dim);
|
CheckIndex(result->indices, i);
|
||||||
CheckElement(rvalues[i]);
|
CheckElement(rvalues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,11 +317,9 @@ sparsevec_out(PG_FUNCTION_ARGS)
|
|||||||
*
|
*
|
||||||
* nnz - 1 bytes for ,
|
* nnz - 1 bytes for ,
|
||||||
*
|
*
|
||||||
* 10 bytes for dimensions
|
* 3 bytes for {, }, and \0
|
||||||
*
|
|
||||||
* 4 bytes for {, }, /, and \0
|
|
||||||
*/
|
*/
|
||||||
buf = (char *) palloc((11 + FLOAT_SHORTEST_DECIMAL_LEN) * sparsevec->nnz + 13);
|
buf = (char *) palloc((11 + FLOAT_SHORTEST_DECIMAL_LEN) * sparsevec->nnz + 2);
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|
||||||
AppendChar(ptr, '{');
|
AppendChar(ptr, '{');
|
||||||
@@ -402,45 +335,12 @@ sparsevec_out(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AppendChar(ptr, '}');
|
AppendChar(ptr, '}');
|
||||||
AppendChar(ptr, '/');
|
|
||||||
AppendInt(ptr, sparsevec->dim);
|
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
|
|
||||||
PG_FREE_IF_COPY(sparsevec, 0);
|
PG_FREE_IF_COPY(sparsevec, 0);
|
||||||
PG_RETURN_CSTRING(buf);
|
PG_RETURN_CSTRING(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert type modifier
|
|
||||||
*/
|
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec_typmod_in);
|
|
||||||
Datum
|
|
||||||
sparsevec_typmod_in(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
|
|
||||||
int32 *tl;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
tl = ArrayGetIntegerTypmods(ta, &n);
|
|
||||||
|
|
||||||
if (n != 1)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("invalid type modifier")));
|
|
||||||
|
|
||||||
if (*tl < 1)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("dimensions for type sparsevec must be at least 1")));
|
|
||||||
|
|
||||||
if (*tl > SPARSEVEC_MAX_DIM)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("dimensions for type sparsevec cannot exceed %d", SPARSEVEC_MAX_DIM)));
|
|
||||||
|
|
||||||
PG_RETURN_INT32(*tl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert external binary representation to internal representation
|
* Convert external binary representation to internal representation
|
||||||
*/
|
*/
|
||||||
@@ -449,33 +349,30 @@ Datum
|
|||||||
sparsevec_recv(PG_FUNCTION_ARGS)
|
sparsevec_recv(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||||
int32 typmod = PG_GETARG_INT32(2);
|
|
||||||
SparseVector *result;
|
SparseVector *result;
|
||||||
int32 dim;
|
|
||||||
int32 nnz;
|
int32 nnz;
|
||||||
int32 unused;
|
int32 unused;
|
||||||
|
int32 unused2;
|
||||||
float *values;
|
float *values;
|
||||||
|
|
||||||
dim = pq_getmsgint(buf, sizeof(int32));
|
|
||||||
nnz = pq_getmsgint(buf, sizeof(int32));
|
nnz = pq_getmsgint(buf, sizeof(int32));
|
||||||
unused = pq_getmsgint(buf, sizeof(int32));
|
unused = pq_getmsgint(buf, sizeof(int32));
|
||||||
|
unused2 = pq_getmsgint(buf, sizeof(int32));
|
||||||
|
|
||||||
CheckDim(dim);
|
CheckNnz(nnz);
|
||||||
CheckNnz(nnz, dim);
|
|
||||||
CheckExpectedDim(typmod, dim);
|
|
||||||
|
|
||||||
if (unused != 0)
|
if (unused != 0 || unused2 != 0)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("expected unused to be 0, not %d", unused)));
|
errmsg("expected unused to be 0, not %d", unused)));
|
||||||
|
|
||||||
result = InitSparseVector(dim, nnz);
|
result = InitSparseVector(nnz);
|
||||||
values = SPARSEVEC_VALUES(result);
|
values = SPARSEVEC_VALUES(result);
|
||||||
|
|
||||||
for (int i = 0; i < nnz; i++)
|
for (int i = 0; i < nnz; i++)
|
||||||
{
|
{
|
||||||
result->indices[i] = pq_getmsgint(buf, sizeof(int32));
|
result->indices[i] = pq_getmsgint(buf, sizeof(int32));
|
||||||
CheckIndex(result->indices, i, dim);
|
CheckIndex(result->indices, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nnz; i++)
|
for (int i = 0; i < nnz; i++)
|
||||||
@@ -499,9 +396,9 @@ sparsevec_send(PG_FUNCTION_ARGS)
|
|||||||
StringInfoData buf;
|
StringInfoData buf;
|
||||||
|
|
||||||
pq_begintypsend(&buf);
|
pq_begintypsend(&buf);
|
||||||
pq_sendint(&buf, svec->dim, sizeof(int32));
|
|
||||||
pq_sendint(&buf, svec->nnz, sizeof(int32));
|
pq_sendint(&buf, svec->nnz, sizeof(int32));
|
||||||
pq_sendint(&buf, svec->unused, sizeof(int32));
|
pq_sendint(&buf, svec->unused, sizeof(int32));
|
||||||
|
pq_sendint(&buf, svec->unused2, sizeof(int32));
|
||||||
for (int i = 0; i < svec->nnz; i++)
|
for (int i = 0; i < svec->nnz; i++)
|
||||||
pq_sendint(&buf, svec->indices[i], sizeof(int32));
|
pq_sendint(&buf, svec->indices[i], sizeof(int32));
|
||||||
for (int i = 0; i < svec->nnz; i++)
|
for (int i = 0; i < svec->nnz; i++)
|
||||||
@@ -512,16 +409,12 @@ 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
|
|
||||||
*/
|
*/
|
||||||
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec);
|
PGDLLEXPORT PG_FUNCTION_INFO_V1(sparsevec);
|
||||||
Datum
|
Datum
|
||||||
sparsevec(PG_FUNCTION_ARGS)
|
sparsevec(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
SparseVector *svec = PG_GETARG_SPARSEVEC_P(0);
|
SparseVector *svec = PG_GETARG_SPARSEVEC_P(0);
|
||||||
int32 typmod = PG_GETARG_INT32(1);
|
|
||||||
|
|
||||||
CheckExpectedDim(typmod, svec->dim);
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(svec);
|
PG_RETURN_POINTER(svec);
|
||||||
}
|
}
|
||||||
@@ -534,23 +427,20 @@ Datum
|
|||||||
vector_to_sparsevec(PG_FUNCTION_ARGS)
|
vector_to_sparsevec(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Vector *vec = PG_GETARG_VECTOR_P(0);
|
Vector *vec = PG_GETARG_VECTOR_P(0);
|
||||||
int32 typmod = PG_GETARG_INT32(1);
|
|
||||||
SparseVector *result;
|
SparseVector *result;
|
||||||
int dim = vec->dim;
|
int dim = vec->dim;
|
||||||
int nnz = 0;
|
int nnz = 0;
|
||||||
float *values;
|
float *values;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
CheckDim(dim);
|
|
||||||
CheckExpectedDim(typmod, dim);
|
|
||||||
|
|
||||||
for (int i = 0; i < dim; i++)
|
for (int i = 0; i < dim; i++)
|
||||||
{
|
{
|
||||||
if (vec->x[i] != 0)
|
if (vec->x[i] != 0)
|
||||||
nnz++;
|
nnz++;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = InitSparseVector(dim, nnz);
|
CheckNnz(nnz);
|
||||||
|
result = InitSparseVector(nnz);
|
||||||
values = SPARSEVEC_VALUES(result);
|
values = SPARSEVEC_VALUES(result);
|
||||||
for (int i = 0; i < dim; i++)
|
for (int i = 0; i < dim; i++)
|
||||||
{
|
{
|
||||||
@@ -627,8 +517,6 @@ sparsevec_l2_distance(PG_FUNCTION_ARGS)
|
|||||||
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
||||||
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
||||||
|
|
||||||
CheckDims(a, b);
|
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(sqrt(l2_distance_squared_internal(a, b)));
|
PG_RETURN_FLOAT8(sqrt(l2_distance_squared_internal(a, b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,8 +531,6 @@ sparsevec_l2_squared_distance(PG_FUNCTION_ARGS)
|
|||||||
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
||||||
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
||||||
|
|
||||||
CheckDims(a, b);
|
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(l2_distance_squared_internal(a, b));
|
PG_RETURN_FLOAT8(l2_distance_squared_internal(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,8 +580,6 @@ sparsevec_inner_product(PG_FUNCTION_ARGS)
|
|||||||
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
||||||
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
||||||
|
|
||||||
CheckDims(a, b);
|
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(inner_product_internal(a, b));
|
PG_RETURN_FLOAT8(inner_product_internal(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,8 +593,6 @@ sparsevec_negative_inner_product(PG_FUNCTION_ARGS)
|
|||||||
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
SparseVector *a = PG_GETARG_SPARSEVEC_P(0);
|
||||||
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
SparseVector *b = PG_GETARG_SPARSEVEC_P(1);
|
||||||
|
|
||||||
CheckDims(a, b);
|
|
||||||
|
|
||||||
PG_RETURN_FLOAT8(-inner_product_internal(a, b));
|
PG_RETURN_FLOAT8(-inner_product_internal(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,8 +611,6 @@ sparsevec_cosine_distance(PG_FUNCTION_ARGS)
|
|||||||
float normb = 0.0;
|
float normb = 0.0;
|
||||||
double similarity;
|
double similarity;
|
||||||
|
|
||||||
CheckDims(a, b);
|
|
||||||
|
|
||||||
similarity = inner_product_internal(a, b);
|
similarity = inner_product_internal(a, b);
|
||||||
|
|
||||||
/* Auto-vectorized */
|
/* Auto-vectorized */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef SPARSEVEC_H
|
#ifndef SPARSEVEC_H
|
||||||
#define SPARSEVEC_H
|
#define SPARSEVEC_H
|
||||||
|
|
||||||
#define SPARSEVEC_MAX_DIM 100000
|
#define SPARSEVEC_MAX_NNZ 100000
|
||||||
|
|
||||||
/* Ensure values are aligned */
|
/* Ensure values are aligned */
|
||||||
#define SPARSEVEC_SIZE(_nnz) (offsetof(SparseVector, indices) + MAXALIGN((_nnz) * sizeof(int32)) + (_nnz * sizeof(float)))
|
#define SPARSEVEC_SIZE(_nnz) (offsetof(SparseVector, indices) + MAXALIGN((_nnz) * sizeof(int32)) + (_nnz * sizeof(float)))
|
||||||
@@ -13,12 +13,12 @@
|
|||||||
typedef struct SparseVector
|
typedef struct SparseVector
|
||||||
{
|
{
|
||||||
int32 vl_len_; /* varlena header (do not touch directly!) */
|
int32 vl_len_; /* varlena header (do not touch directly!) */
|
||||||
int32 dim; /* number of dimensions */
|
|
||||||
int32 nnz;
|
int32 nnz;
|
||||||
int32 unused;
|
int32 unused;
|
||||||
|
int32 unused2;
|
||||||
int32 indices[FLEXIBLE_ARRAY_MEMBER];
|
int32 indices[FLEXIBLE_ARRAY_MEMBER];
|
||||||
} SparseVector;
|
} SparseVector;
|
||||||
|
|
||||||
SparseVector *InitSparseVector(int dim, int nnz);
|
SparseVector *InitSparseVector(int nnz);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
12
src/vector.c
12
src/vector.c
@@ -1236,11 +1236,19 @@ sparsevec_to_vector(PG_FUNCTION_ARGS)
|
|||||||
SparseVector *svec = PG_GETARG_SPARSEVEC_P(0);
|
SparseVector *svec = PG_GETARG_SPARSEVEC_P(0);
|
||||||
int32 typmod = PG_GETARG_INT32(1);
|
int32 typmod = PG_GETARG_INT32(1);
|
||||||
Vector *result;
|
Vector *result;
|
||||||
int dim = svec->dim;
|
int dim;
|
||||||
float *values = SPARSEVEC_VALUES(svec);
|
float *values = SPARSEVEC_VALUES(svec);
|
||||||
|
int maxIndex = svec->nnz == 0 ? -1 : svec->indices[svec->nnz - 1];
|
||||||
|
|
||||||
|
if (typmod == -1)
|
||||||
|
dim = maxIndex + 1;
|
||||||
|
else
|
||||||
|
dim = typmod;
|
||||||
|
|
||||||
CheckDim(dim);
|
CheckDim(dim);
|
||||||
CheckExpectedDim(typmod, dim);
|
|
||||||
|
if (dim < maxIndex + 1)
|
||||||
|
elog(ERROR, "Vector must have at least %d dimensions", maxIndex + 1);
|
||||||
|
|
||||||
result = InitVector(dim);
|
result = InitVector(dim);
|
||||||
for (int i = 0; i < svec->nnz; i++)
|
for (int i = 0; i < svec->nnz; i++)
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
CREATE TABLE t (val sparsevec(3));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES ('{}/3'), ('{0:1,1:2,2:3}/3'), ('{0:1,1:1,2:1}/3'), (NULL);
|
INSERT INTO t (val) VALUES ('{}'), ('{0:1,1:2,2:3}'), ('{0:1,1:1,2:1}'), (NULL);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_cosine_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_cosine_ops);
|
||||||
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}/3');
|
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}');
|
||||||
SELECT * FROM t ORDER BY val <=> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <=> '{0:3,1:3,2:3}';
|
||||||
val
|
val
|
||||||
-----------------
|
---------------
|
||||||
{0:1,1:1,2:1}/3
|
{0:1,1:1,2:1}
|
||||||
{0:1,1:2,2:3}/3
|
{0:1,1:2,2:3}
|
||||||
{0:1,1:2,2:4}/3
|
{0:1,1:2,2:4}
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <=> '{}/3') t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <=> '{}') t2;
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
3
|
3
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
CREATE TABLE t (val sparsevec(3));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES ('{}/3'), ('{0:1,1:2,2:3}/3'), ('{0:1,1:1,2:1}/3'), (NULL);
|
INSERT INTO t (val) VALUES ('{}'), ('{0:1,1:2,2:3}'), ('{0:1,1:1,2:1}'), (NULL);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_ip_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_ip_ops);
|
||||||
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}/3');
|
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}');
|
||||||
SELECT * FROM t ORDER BY val <#> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <#> '{0:3,1:3,2:3}';
|
||||||
val
|
val
|
||||||
-----------------
|
---------------
|
||||||
{0:1,1:2,2:4}/3
|
{0:1,1:2,2:4}
|
||||||
{0:1,1:2,2:3}/3
|
{0:1,1:2,2:3}
|
||||||
{0:1,1:1,2:1}/3
|
{0:1,1:1,2:1}
|
||||||
{}/3
|
{}
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <#> (SELECT NULL::sparsevec)) t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <#> (SELECT NULL::sparsevec)) t2;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
CREATE TABLE t (val sparsevec(3));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES ('{}/3'), ('{0:1,1:2,2:3}/3'), ('{0:1,1:1,2:1}/3'), (NULL);
|
INSERT INTO t (val) VALUES ('{}'), ('{0:1,1:2,2:3}'), ('{0:1,1:1,2:1}'), (NULL);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
||||||
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}/3');
|
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}');
|
||||||
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}';
|
||||||
val
|
val
|
||||||
-----------------
|
---------------
|
||||||
{0:1,1:2,2:3}/3
|
{0:1,1:2,2:3}
|
||||||
{0:1,1:2,2:4}/3
|
{0:1,1:2,2:4}
|
||||||
{0:1,1:1,2:1}/3
|
{0:1,1:1,2:1}
|
||||||
{}/3
|
{}
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <-> (SELECT NULL::sparsevec)) t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <-> (SELECT NULL::sparsevec)) t2;
|
||||||
@@ -25,14 +25,14 @@ SELECT COUNT(*) FROM t;
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
TRUNCATE t;
|
TRUNCATE t;
|
||||||
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}';
|
||||||
val
|
val
|
||||||
-----
|
-----
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
-- TODO move
|
-- TODO move
|
||||||
CREATE TABLE t (val sparsevec(1001));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES (array_fill(1, ARRAY[1001])::vector::sparsevec);
|
INSERT INTO t (val) VALUES (array_fill(1, ARRAY[1001])::vector::sparsevec);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
||||||
ERROR: sparsevec cannot have more than 1000 non-zero elements for hnsw index
|
ERROR: sparsevec cannot have more than 1000 non-zero elements for hnsw index
|
||||||
|
|||||||
@@ -1,62 +1,60 @@
|
|||||||
SELECT l2_distance('{}/2'::sparsevec, '{0:3,1:4}/2');
|
SELECT l2_distance('{}'::sparsevec, '{0:3,1:4}');
|
||||||
l2_distance
|
l2_distance
|
||||||
-------------
|
-------------
|
||||||
5
|
5
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT l2_distance('{}/2'::sparsevec, '{1:1}/2');
|
SELECT l2_distance('{}'::sparsevec, '{1:1}');
|
||||||
l2_distance
|
l2_distance
|
||||||
-------------
|
-------------
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{}/2'::sparsevec <-> '{0:3,1:4}/2';
|
SELECT '{}'::sparsevec <-> '{0:3,1:4}';
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
5
|
5
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT inner_product('{0:1,1:2}/2'::sparsevec, '{0:2,1:4}/2');
|
SELECT inner_product('{0:1,1:2}'::sparsevec, '{0:2,1:4}');
|
||||||
inner_product
|
inner_product
|
||||||
---------------
|
---------------
|
||||||
10
|
10
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT sparsevec_negative_inner_product('{0:1,1:2}/2', '{0:2,1:4}/2');
|
SELECT sparsevec_negative_inner_product('{0:1,1:2}', '{0:2,1:4}');
|
||||||
sparsevec_negative_inner_product
|
sparsevec_negative_inner_product
|
||||||
----------------------------------
|
----------------------------------
|
||||||
-10
|
-10
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT cosine_distance('{0:1,1:2}/2'::sparsevec, '{0:2,1:4}/2');
|
SELECT cosine_distance('{0:1,1:2}'::sparsevec, '{0:2,1:4}');
|
||||||
cosine_distance
|
cosine_distance
|
||||||
-----------------
|
-----------------
|
||||||
0
|
0
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT cosine_distance('{0:1,1:2}/2'::sparsevec, '{}/2');
|
SELECT cosine_distance('{0:1,1:2}'::sparsevec, '{}');
|
||||||
cosine_distance
|
cosine_distance
|
||||||
-----------------
|
-----------------
|
||||||
NaN
|
NaN
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT cosine_distance('{0:1,1:1}/2'::sparsevec, '{0:-1,1:-1}/2');
|
SELECT cosine_distance('{0:1,1:1}'::sparsevec, '{0:-1,1:-1}');
|
||||||
cosine_distance
|
cosine_distance
|
||||||
-----------------
|
-----------------
|
||||||
2
|
2
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT cosine_distance('{0:1}/2'::sparsevec, '{1:2}/2');
|
SELECT cosine_distance('{0:1}'::sparsevec, '{1:2}');
|
||||||
cosine_distance
|
cosine_distance
|
||||||
-----------------
|
-----------------
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT cosine_distance('{}/1'::sparsevec, '{}/1');
|
SELECT cosine_distance('{}'::sparsevec, '{}');
|
||||||
cosine_distance
|
cosine_distance
|
||||||
-----------------
|
-----------------
|
||||||
NaN
|
NaN
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT cosine_distance('{0:1}/2'::sparsevec, '{0:1}/3');
|
|
||||||
ERROR: different sparsevec dimensions 2 and 3
|
|
||||||
|
|||||||
@@ -1,62 +1,64 @@
|
|||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec;
|
SELECT '{0:1.5,2:3.5}'::sparsevec;
|
||||||
sparsevec
|
sparsevec
|
||||||
-----------------
|
---------------
|
||||||
{0:1.5,2:3.5}/5
|
{0:1.5,2:3.5}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec::vector;
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector;
|
||||||
|
vector
|
||||||
|
-------------
|
||||||
|
[1.5,0,3.5]
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector(5);
|
||||||
vector
|
vector
|
||||||
-----------------
|
-----------------
|
||||||
[1.5,0,3.5,0,0]
|
[1.5,0,3.5,0,0]
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec::vector(5);
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector(4);
|
||||||
vector
|
vector
|
||||||
-----------------
|
---------------
|
||||||
[1.5,0,3.5,0,0]
|
[1.5,0,3.5,0]
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec::vector(4);
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector(2);
|
||||||
ERROR: expected 4 dimensions, not 5
|
ERROR: Vector must have at least 3 dimensions
|
||||||
SELECT '[0,1.5,0,3.5,0]'::vector::sparsevec;
|
SELECT '[0,1.5,0,3.5,0]'::vector::sparsevec;
|
||||||
sparsevec
|
sparsevec
|
||||||
-----------------
|
---------------
|
||||||
{1:1.5,3:3.5}/5
|
{1:1.5,3:3.5}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{0:0,1:1,2:0}/3'::sparsevec;
|
SELECT '{0:0,1:1,2:0}'::sparsevec;
|
||||||
sparsevec
|
sparsevec
|
||||||
-----------
|
-----------
|
||||||
{1:1}/3
|
{1:1}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{1:1,0:1}/2'::sparsevec;
|
SELECT '{1:1,0:1}'::sparsevec;
|
||||||
ERROR: indexes must be in ascending order
|
ERROR: indexes must be in ascending order
|
||||||
LINE 1: SELECT '{1:1,0:1}/2'::sparsevec;
|
LINE 1: SELECT '{1:1,0:1}'::sparsevec;
|
||||||
^
|
^
|
||||||
SELECT '{}/5'::sparsevec;
|
SELECT '{}'::sparsevec;
|
||||||
sparsevec
|
sparsevec
|
||||||
-----------
|
-----------
|
||||||
{}/5
|
{}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT '{}/-1'::sparsevec;
|
SELECT '{}'::sparsevec::vector;
|
||||||
ERROR: sparsevec must have at least 1 dimension
|
ERROR: vector must have at least 1 dimension
|
||||||
LINE 1: SELECT '{}/-1'::sparsevec;
|
SELECT '{-1:1}'::sparsevec;
|
||||||
^
|
|
||||||
SELECT '{}/100001'::sparsevec;
|
|
||||||
ERROR: sparsevec cannot have more than 100000 dimensions
|
|
||||||
LINE 1: SELECT '{}/100001'::sparsevec;
|
|
||||||
^
|
|
||||||
SELECT '{}/16001'::sparsevec::vector;
|
|
||||||
ERROR: vector cannot have more than 16000 dimensions
|
|
||||||
SELECT '{-1:1}/1'::sparsevec;
|
|
||||||
ERROR: index "-1" is out of range for type sparsevec
|
ERROR: index "-1" is out of range for type sparsevec
|
||||||
LINE 1: SELECT '{-1:1}/1'::sparsevec;
|
LINE 1: SELECT '{-1:1}'::sparsevec;
|
||||||
^
|
^
|
||||||
SELECT '{1:1}/1'::sparsevec;
|
SELECT '{1:1}'::sparsevec;
|
||||||
ERROR: index must be less than dimensions
|
sparsevec
|
||||||
LINE 1: SELECT '{1:1}/1'::sparsevec;
|
-----------
|
||||||
^
|
{1:1}
|
||||||
SELECT '{}/1'::sparsevec(2);
|
(1 row)
|
||||||
ERROR: expected 2 dimensions, not 1
|
|
||||||
|
SELECT '{}'::sparsevec(2);
|
||||||
|
ERROR: type modifier is not allowed for type "sparsevec"
|
||||||
|
LINE 1: SELECT '{}'::sparsevec(2);
|
||||||
|
^
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
|
|
||||||
CREATE TABLE t (val sparsevec(3));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES ('{}/3'), ('{0:1,1:2,2:3}/3'), ('{0:1,1:1,2:1}/3'), (NULL);
|
INSERT INTO t (val) VALUES ('{}'), ('{0:1,1:2,2:3}'), ('{0:1,1:1,2:1}'), (NULL);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_cosine_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_cosine_ops);
|
||||||
|
|
||||||
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}/3');
|
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}');
|
||||||
|
|
||||||
SELECT * FROM t ORDER BY val <=> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <=> '{0:3,1:3,2:3}';
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <=> '{}/3') t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <=> '{}') t2;
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <=> (SELECT NULL::sparsevec)) t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <=> (SELECT NULL::sparsevec)) t2;
|
||||||
|
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
|
|
||||||
CREATE TABLE t (val sparsevec(3));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES ('{}/3'), ('{0:1,1:2,2:3}/3'), ('{0:1,1:1,2:1}/3'), (NULL);
|
INSERT INTO t (val) VALUES ('{}'), ('{0:1,1:2,2:3}'), ('{0:1,1:1,2:1}'), (NULL);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_ip_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_ip_ops);
|
||||||
|
|
||||||
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}/3');
|
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}');
|
||||||
|
|
||||||
SELECT * FROM t ORDER BY val <#> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <#> '{0:3,1:3,2:3}';
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <#> (SELECT NULL::sparsevec)) t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <#> (SELECT NULL::sparsevec)) t2;
|
||||||
|
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
SET enable_seqscan = off;
|
SET enable_seqscan = off;
|
||||||
|
|
||||||
CREATE TABLE t (val sparsevec(3));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES ('{}/3'), ('{0:1,1:2,2:3}/3'), ('{0:1,1:1,2:1}/3'), (NULL);
|
INSERT INTO t (val) VALUES ('{}'), ('{0:1,1:2,2:3}'), ('{0:1,1:1,2:1}'), (NULL);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
||||||
|
|
||||||
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}/3');
|
INSERT INTO t (val) VALUES ('{0:1,1:2,2:4}');
|
||||||
|
|
||||||
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}';
|
||||||
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <-> (SELECT NULL::sparsevec)) t2;
|
SELECT COUNT(*) FROM (SELECT * FROM t ORDER BY val <-> (SELECT NULL::sparsevec)) t2;
|
||||||
SELECT COUNT(*) FROM t;
|
SELECT COUNT(*) FROM t;
|
||||||
|
|
||||||
TRUNCATE t;
|
TRUNCATE t;
|
||||||
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}/3';
|
SELECT * FROM t ORDER BY val <-> '{0:3,1:3,2:3}';
|
||||||
|
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
|
|
||||||
-- TODO move
|
-- TODO move
|
||||||
CREATE TABLE t (val sparsevec(1001));
|
CREATE TABLE t (val sparsevec);
|
||||||
INSERT INTO t (val) VALUES (array_fill(1, ARRAY[1001])::vector::sparsevec);
|
INSERT INTO t (val) VALUES (array_fill(1, ARRAY[1001])::vector::sparsevec);
|
||||||
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
CREATE INDEX ON t USING hnsw (val sparsevec_l2_ops);
|
||||||
TRUNCATE t;
|
TRUNCATE t;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
SELECT l2_distance('{}/2'::sparsevec, '{0:3,1:4}/2');
|
SELECT l2_distance('{}'::sparsevec, '{0:3,1:4}');
|
||||||
SELECT l2_distance('{}/2'::sparsevec, '{1:1}/2');
|
SELECT l2_distance('{}'::sparsevec, '{1:1}');
|
||||||
SELECT '{}/2'::sparsevec <-> '{0:3,1:4}/2';
|
SELECT '{}'::sparsevec <-> '{0:3,1:4}';
|
||||||
|
|
||||||
SELECT inner_product('{0:1,1:2}/2'::sparsevec, '{0:2,1:4}/2');
|
SELECT inner_product('{0:1,1:2}'::sparsevec, '{0:2,1:4}');
|
||||||
SELECT sparsevec_negative_inner_product('{0:1,1:2}/2', '{0:2,1:4}/2');
|
SELECT sparsevec_negative_inner_product('{0:1,1:2}', '{0:2,1:4}');
|
||||||
|
|
||||||
SELECT cosine_distance('{0:1,1:2}/2'::sparsevec, '{0:2,1:4}/2');
|
SELECT cosine_distance('{0:1,1:2}'::sparsevec, '{0:2,1:4}');
|
||||||
SELECT cosine_distance('{0:1,1:2}/2'::sparsevec, '{}/2');
|
SELECT cosine_distance('{0:1,1:2}'::sparsevec, '{}');
|
||||||
SELECT cosine_distance('{0:1,1:1}/2'::sparsevec, '{0:-1,1:-1}/2');
|
SELECT cosine_distance('{0:1,1:1}'::sparsevec, '{0:-1,1:-1}');
|
||||||
SELECT cosine_distance('{0:1}/2'::sparsevec, '{1:2}/2');
|
SELECT cosine_distance('{0:1}'::sparsevec, '{1:2}');
|
||||||
SELECT cosine_distance('{}/1'::sparsevec, '{}/1');
|
SELECT cosine_distance('{}'::sparsevec, '{}');
|
||||||
SELECT cosine_distance('{0:1}/2'::sparsevec, '{0:1}/3');
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec;
|
SELECT '{0:1.5,2:3.5}'::sparsevec;
|
||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec::vector;
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector;
|
||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec::vector(5);
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector(5);
|
||||||
SELECT '{0:1.5,2:3.5}/5'::sparsevec::vector(4);
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector(4);
|
||||||
|
SELECT '{0:1.5,2:3.5}'::sparsevec::vector(2);
|
||||||
SELECT '[0,1.5,0,3.5,0]'::vector::sparsevec;
|
SELECT '[0,1.5,0,3.5,0]'::vector::sparsevec;
|
||||||
|
|
||||||
SELECT '{0:0,1:1,2:0}/3'::sparsevec;
|
SELECT '{0:0,1:1,2:0}'::sparsevec;
|
||||||
|
|
||||||
SELECT '{1:1,0:1}/2'::sparsevec;
|
SELECT '{1:1,0:1}'::sparsevec;
|
||||||
|
|
||||||
SELECT '{}/5'::sparsevec;
|
SELECT '{}'::sparsevec;
|
||||||
SELECT '{}/-1'::sparsevec;
|
SELECT '{}'::sparsevec::vector;
|
||||||
SELECT '{}/100001'::sparsevec;
|
|
||||||
SELECT '{}/16001'::sparsevec::vector;
|
|
||||||
|
|
||||||
SELECT '{-1:1}/1'::sparsevec;
|
SELECT '{-1:1}'::sparsevec;
|
||||||
SELECT '{1:1}/1'::sparsevec;
|
SELECT '{1:1}'::sparsevec;
|
||||||
|
|
||||||
SELECT '{}/1'::sparsevec(2);
|
SELECT '{}'::sparsevec(2);
|
||||||
|
|||||||
Reference in New Issue
Block a user