Updated sparsevec input to support indices in any order [skip ci]

This commit is contained in:
Andrew Kane
2024-04-19 16:54:19 -07:00
parent 4e093f95be
commit fd4fbd238c
3 changed files with 43 additions and 10 deletions

View File

@@ -18,6 +18,12 @@
#include "utils/builtins.h" #include "utils/builtins.h"
#endif #endif
typedef struct SparseInputElement
{
int32 index;
float value;
} SparseInputElement;
/* /*
* Ensure same dimensions * Ensure same dimensions
*/ */
@@ -164,6 +170,21 @@ sparsevec_isspace(char ch)
return false; return false;
} }
/*
* Compare indices
*/
static int
CompareIndices(const void *a, const void *b)
{
if (((SparseInputElement *) a)->index < ((SparseInputElement *) b)->index)
return -1;
if (((SparseInputElement *) a)->index > ((SparseInputElement *) b)->index)
return 1;
return 0;
}
/* /*
* Convert textual representation to internal representation * Convert textual representation to internal representation
*/ */
@@ -178,8 +199,7 @@ sparsevec_in(PG_FUNCTION_ARGS)
char *stringEnd; char *stringEnd;
SparseVector *result; SparseVector *result;
float *rvalues; float *rvalues;
int32 *indices; SparseInputElement *elements;
float *values;
int maxNnz; int maxNnz;
int nnz = 0; int nnz = 0;
@@ -197,8 +217,7 @@ sparsevec_in(PG_FUNCTION_ARGS)
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("sparsevec cannot have more than %d non-zero elements", SPARSEVEC_MAX_NNZ))); errmsg("sparsevec cannot have more than %d non-zero elements", SPARSEVEC_MAX_NNZ)));
indices = palloc(maxNnz * sizeof(int32)); elements = palloc(maxNnz * sizeof(SparseInputElement));
values = palloc(maxNnz * sizeof(float));
pt = lit; pt = lit;
@@ -291,8 +310,8 @@ sparsevec_in(PG_FUNCTION_ARGS)
/* Do not store zero values */ /* Do not store zero values */
if (value != 0) if (value != 0)
{ {
indices[nnz] = index; elements[nnz].index = index;
values[nnz] = value; elements[nnz].value = value;
nnz++; nnz++;
} }
@@ -353,12 +372,14 @@ sparsevec_in(PG_FUNCTION_ARGS)
CheckDim(dim); CheckDim(dim);
CheckExpectedDim(typmod, dim); CheckExpectedDim(typmod, dim);
qsort(elements, nnz, sizeof(SparseInputElement), CompareIndices);
result = InitSparseVector(dim, nnz); 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] = elements[i].index;
rvalues[i] = values[i]; rvalues[i] = elements[i].value;
CheckIndex(result->indices, i, dim); CheckIndex(result->indices, i, dim);
} }

View File

@@ -164,8 +164,18 @@ SELECT '{1:0,2:1,3:0}/3'::sparsevec;
(1 row) (1 row)
SELECT '{2:1,1:1}/2'::sparsevec; SELECT '{2:1,1:1}/2'::sparsevec;
ERROR: indexes must be in ascending order sparsevec
LINE 1: SELECT '{2:1,1:1}/2'::sparsevec; -------------
{1:1,2:1}/2
(1 row)
SELECT '{1:1,1:1}/2'::sparsevec;
ERROR: indexes must not contain duplicates
LINE 1: SELECT '{1:1,1:1}/2'::sparsevec;
^
SELECT '{1:1,2:1,1:1}/2'::sparsevec;
ERROR: indexes must not contain duplicates
LINE 1: SELECT '{1:1,2:1,1:1}/2'::sparsevec;
^ ^
SELECT '{}/5'::sparsevec; SELECT '{}/5'::sparsevec;
sparsevec sparsevec

View File

@@ -34,6 +34,8 @@ SELECT '{1:1a}/1'::sparsevec;
SELECT '{1:1,}/1'::sparsevec; SELECT '{1:1,}/1'::sparsevec;
SELECT '{1:0,2:1,3:0}/3'::sparsevec; SELECT '{1:0,2:1,3:0}/3'::sparsevec;
SELECT '{2:1,1:1}/2'::sparsevec; SELECT '{2:1,1:1}/2'::sparsevec;
SELECT '{1:1,1:1}/2'::sparsevec;
SELECT '{1:1,2:1,1:1}/2'::sparsevec;
SELECT '{}/5'::sparsevec; SELECT '{}/5'::sparsevec;
SELECT '{}/-1'::sparsevec; SELECT '{}/-1'::sparsevec;
SELECT '{}/100001'::sparsevec; SELECT '{}/100001'::sparsevec;