mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-12 07:36:55 +08:00
Tried switching column order [skip ci]
This commit is contained in:
@@ -4,3 +4,7 @@
|
|||||||
CREATE OPERATOR CLASS vector_integer_ops
|
CREATE OPERATOR CLASS vector_integer_ops
|
||||||
DEFAULT FOR TYPE integer USING hnsw AS
|
DEFAULT FOR TYPE integer USING hnsw AS
|
||||||
OPERATOR 2 = (integer, integer);
|
OPERATOR 2 = (integer, integer);
|
||||||
|
|
||||||
|
CREATE OPERATOR CLASS vector_bigint_ops
|
||||||
|
DEFAULT FOR TYPE bigint USING hnsw AS
|
||||||
|
OPERATOR 2 = (bigint, bigint);
|
||||||
|
|||||||
@@ -296,3 +296,7 @@ CREATE OPERATOR CLASS vector_cosine_ops
|
|||||||
CREATE OPERATOR CLASS vector_integer_ops
|
CREATE OPERATOR CLASS vector_integer_ops
|
||||||
DEFAULT FOR TYPE integer USING hnsw AS
|
DEFAULT FOR TYPE integer USING hnsw AS
|
||||||
OPERATOR 2 = (integer, integer);
|
OPERATOR 2 = (integer, integer);
|
||||||
|
|
||||||
|
CREATE OPERATOR CLASS vector_bigint_ops
|
||||||
|
DEFAULT FOR TYPE bigint USING hnsw AS
|
||||||
|
OPERATOR 2 = (bigint, bigint);
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heaptid, Hn
|
|||||||
bool unused;
|
bool unused;
|
||||||
|
|
||||||
/* Detoast once for all calls */
|
/* Detoast once for all calls */
|
||||||
Datum value = PointerGetDatum(PG_DETOAST_DATUM(values[0]));
|
Datum value = PointerGetDatum(PG_DETOAST_DATUM(values[IndexRelationGetNumberOfKeyAttributes(index) - 1]));
|
||||||
|
|
||||||
/* Normalize if needed */
|
/* Normalize if needed */
|
||||||
if (buildstate->normprocinfo != NULL)
|
if (buildstate->normprocinfo != NULL)
|
||||||
@@ -551,7 +551,7 @@ InsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heaptid, Hn
|
|||||||
/* Copy the index tuple */
|
/* Copy the index tuple */
|
||||||
memcpy(itupPtr, itup, itupSize);
|
memcpy(itupPtr, itup, itupSize);
|
||||||
HnswPtrStore(base, element->itup, itupPtr);
|
HnswPtrStore(base, element->itup, itupPtr);
|
||||||
valuePtr = DatumGetPointer(index_getattr(itupPtr, 1, tupdesc, &unused));
|
valuePtr = DatumGetPointer(index_getattr(itupPtr, IndexRelationGetNumberOfKeyAttributes(index), tupdesc, &unused));
|
||||||
HnswPtrStore(base, element->value, valuePtr);
|
HnswPtrStore(base, element->value, valuePtr);
|
||||||
|
|
||||||
/* Create a lock for the element */
|
/* Create a lock for the element */
|
||||||
@@ -582,7 +582,7 @@ BuildCallback(Relation index, CALLBACK_ITEM_POINTER, Datum *values,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Skip nulls */
|
/* Skip nulls */
|
||||||
if (isnull[0])
|
if (isnull[IndexRelationGetNumberOfKeyAttributes(index) - 1])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Use memory context */
|
/* Use memory context */
|
||||||
@@ -674,16 +674,16 @@ InitBuildState(HnswBuildState * buildstate, Relation heap, Relation index, Index
|
|||||||
|
|
||||||
buildstate->m = HnswGetM(index);
|
buildstate->m = HnswGetM(index);
|
||||||
buildstate->efConstruction = HnswGetEfConstruction(index);
|
buildstate->efConstruction = HnswGetEfConstruction(index);
|
||||||
buildstate->dimensions = TupleDescAttr(index->rd_att, 0)->atttypmod;
|
buildstate->dimensions = TupleDescAttr(index->rd_att, IndexRelationGetNumberOfKeyAttributes(index) - 1)->atttypmod;
|
||||||
|
|
||||||
/* For now */
|
/* For now */
|
||||||
if (IndexRelationGetNumberOfKeyAttributes(index) > 2)
|
if (IndexRelationGetNumberOfKeyAttributes(index) > 2)
|
||||||
elog(ERROR, "index cannot have more than two columns");
|
elog(ERROR, "index cannot have more than two columns");
|
||||||
|
|
||||||
if (!OidIsValid(index_getprocid(index, 1, HNSW_DISTANCE_PROC)))
|
if (!OidIsValid(index_getprocid(index, IndexRelationGetNumberOfKeyAttributes(index), HNSW_DISTANCE_PROC)))
|
||||||
elog(ERROR, "first column must be a vector");
|
elog(ERROR, "last column must be a vector");
|
||||||
|
|
||||||
for (int i = 1; i < IndexRelationGetNumberOfKeyAttributes(index); i++)
|
for (int i = 0; i < IndexRelationGetNumberOfKeyAttributes(index) - 1; i++)
|
||||||
{
|
{
|
||||||
if (OidIsValid(index_getprocid(index, i + 1, HNSW_DISTANCE_PROC)))
|
if (OidIsValid(index_getprocid(index, i + 1, HNSW_DISTANCE_PROC)))
|
||||||
elog(ERROR, "column %d cannot be a vector", i + 1);
|
elog(ERROR, "column %d cannot be a vector", i + 1);
|
||||||
@@ -703,9 +703,9 @@ InitBuildState(HnswBuildState * buildstate, Relation heap, Relation index, Index
|
|||||||
buildstate->indtuples = 0;
|
buildstate->indtuples = 0;
|
||||||
|
|
||||||
/* Get support functions */
|
/* Get support functions */
|
||||||
buildstate->procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC);
|
buildstate->procinfo = index_getprocinfo(index, IndexRelationGetNumberOfKeyAttributes(index), HNSW_DISTANCE_PROC);
|
||||||
buildstate->normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC);
|
buildstate->normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC);
|
||||||
buildstate->collation = index->rd_indcollation[0];
|
buildstate->collation = index->rd_indcollation[IndexRelationGetNumberOfKeyAttributes(index) - 1];
|
||||||
|
|
||||||
InitGraph(&buildstate->graphData, NULL, maintenance_work_mem * 1024L);
|
InitGraph(&buildstate->graphData, NULL, maintenance_work_mem * 1024L);
|
||||||
buildstate->graph = &buildstate->graphData;
|
buildstate->graph = &buildstate->graphData;
|
||||||
|
|||||||
@@ -561,8 +561,8 @@ HnswInsertTupleOnDisk(Relation index, Datum value, Datum *values, bool *isnull,
|
|||||||
HnswElement element;
|
HnswElement element;
|
||||||
int m;
|
int m;
|
||||||
int efConstruction = HnswGetEfConstruction(index);
|
int efConstruction = HnswGetEfConstruction(index);
|
||||||
FmgrInfo *procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC);
|
FmgrInfo *procinfo = index_getprocinfo(index, IndexRelationGetNumberOfKeyAttributes(index), HNSW_DISTANCE_PROC);
|
||||||
Oid collation = index->rd_indcollation[0];
|
Oid collation = index->rd_indcollation[IndexRelationGetNumberOfKeyAttributes(index) - 1];
|
||||||
LOCKMODE lockmode = ShareLock;
|
LOCKMODE lockmode = ShareLock;
|
||||||
char *base = NULL;
|
char *base = NULL;
|
||||||
TupleDesc tupdesc = HnswTupleDesc(index);
|
TupleDesc tupdesc = HnswTupleDesc(index);
|
||||||
@@ -584,7 +584,7 @@ HnswInsertTupleOnDisk(Relation index, Datum value, Datum *values, bool *isnull,
|
|||||||
element = HnswInitElement(base, heap_tid, m, HnswGetMl(m), HnswGetMaxLevel(m), NULL);
|
element = HnswInitElement(base, heap_tid, m, HnswGetMl(m), HnswGetMaxLevel(m), NULL);
|
||||||
itup = HnswFormIndexTuple(index, tupdesc, value, values, isnull);
|
itup = HnswFormIndexTuple(index, tupdesc, value, values, isnull);
|
||||||
HnswPtrStore(base, element->itup, itup);
|
HnswPtrStore(base, element->itup, itup);
|
||||||
valuePtr = DatumGetPointer(index_getattr(itup, 1, tupdesc, &unused));
|
valuePtr = DatumGetPointer(index_getattr(itup, IndexRelationGetNumberOfKeyAttributes(index), tupdesc, &unused));
|
||||||
HnswPtrStore(base, element->value, valuePtr);
|
HnswPtrStore(base, element->value, valuePtr);
|
||||||
|
|
||||||
/* Prevent concurrent inserts when likely updating entry point */
|
/* Prevent concurrent inserts when likely updating entry point */
|
||||||
@@ -621,10 +621,10 @@ HnswInsertTuple(Relation index, Datum *values, bool *isnull, ItemPointer heap_ti
|
|||||||
{
|
{
|
||||||
Datum value;
|
Datum value;
|
||||||
FmgrInfo *normprocinfo;
|
FmgrInfo *normprocinfo;
|
||||||
Oid collation = index->rd_indcollation[0];
|
Oid collation = index->rd_indcollation[IndexRelationGetNumberOfKeyAttributes(index) - 1];
|
||||||
|
|
||||||
/* Detoast once for all calls */
|
/* Detoast once for all calls */
|
||||||
value = PointerGetDatum(PG_DETOAST_DATUM(values[0]));
|
value = PointerGetDatum(PG_DETOAST_DATUM(values[IndexRelationGetNumberOfKeyAttributes(index) - 1]));
|
||||||
|
|
||||||
/* Normalize if needed */
|
/* Normalize if needed */
|
||||||
normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC);
|
normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC);
|
||||||
@@ -653,7 +653,7 @@ hnswinsert(Relation index, Datum *values, bool *isnull, ItemPointer heap_tid,
|
|||||||
MemoryContext insertCtx;
|
MemoryContext insertCtx;
|
||||||
|
|
||||||
/* Skip nulls */
|
/* Skip nulls */
|
||||||
if (isnull[0])
|
if (isnull[IndexRelationGetNumberOfKeyAttributes(index) - 1])
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Create memory context */
|
/* Create memory context */
|
||||||
|
|||||||
@@ -109,9 +109,9 @@ hnswbeginscan(Relation index, int nkeys, int norderbys)
|
|||||||
ALLOCSET_DEFAULT_SIZES);
|
ALLOCSET_DEFAULT_SIZES);
|
||||||
|
|
||||||
/* Set support functions */
|
/* Set support functions */
|
||||||
so->procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC);
|
so->procinfo = index_getprocinfo(index, IndexRelationGetNumberOfKeyAttributes(index), HNSW_DISTANCE_PROC);
|
||||||
so->normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC);
|
so->normprocinfo = HnswOptionalProcInfo(index, HNSW_NORM_PROC);
|
||||||
so->collation = index->rd_indcollation[0];
|
so->collation = index->rd_indcollation[IndexRelationGetNumberOfKeyAttributes(index) - 1];
|
||||||
|
|
||||||
scan->opaque = so;
|
scan->opaque = so;
|
||||||
|
|
||||||
|
|||||||
@@ -148,10 +148,10 @@ HnswGetEfConstruction(Relation index)
|
|||||||
FmgrInfo *
|
FmgrInfo *
|
||||||
HnswOptionalProcInfo(Relation index, uint16 procnum)
|
HnswOptionalProcInfo(Relation index, uint16 procnum)
|
||||||
{
|
{
|
||||||
if (!OidIsValid(index_getprocid(index, 1, procnum)))
|
if (!OidIsValid(index_getprocid(index, IndexRelationGetNumberOfKeyAttributes(index), procnum)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return index_getprocinfo(index, 1, procnum);
|
return index_getprocinfo(index, IndexRelationGetNumberOfKeyAttributes(index), procnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -324,7 +324,7 @@ HnswFormIndexTuple(Relation index, TupleDesc tupdesc, Datum value, Datum *values
|
|||||||
Datum *newValues = palloc(size);
|
Datum *newValues = palloc(size);
|
||||||
|
|
||||||
memcpy(newValues, values, size);
|
memcpy(newValues, values, size);
|
||||||
newValues[0] = value;
|
newValues[IndexRelationGetNumberOfKeyAttributes(index) - 1] = value;
|
||||||
|
|
||||||
return index_form_tuple(tupdesc, newValues, isnull);
|
return index_form_tuple(tupdesc, newValues, isnull);
|
||||||
}
|
}
|
||||||
@@ -642,7 +642,7 @@ HnswLoadElementFromTuple(HnswElement element, HnswElementTuple etup, bool loadHe
|
|||||||
TupleDesc tupdesc = RelationGetDescr(index);
|
TupleDesc tupdesc = RelationGetDescr(index);
|
||||||
bool unused;
|
bool unused;
|
||||||
IndexTuple itup = CopyIndexTuple((IndexTuple) &etup->data);
|
IndexTuple itup = CopyIndexTuple((IndexTuple) &etup->data);
|
||||||
Datum value = index_getattr(itup, 1, tupdesc, &unused);
|
Datum value = index_getattr(itup, IndexRelationGetNumberOfKeyAttributes(index), tupdesc, &unused);
|
||||||
|
|
||||||
HnswPtrStore(base, element->itup, itup);
|
HnswPtrStore(base, element->itup, itup);
|
||||||
HnswPtrStore(base, element->value, DatumGetPointer(value));
|
HnswPtrStore(base, element->value, DatumGetPointer(value));
|
||||||
@@ -722,7 +722,7 @@ HnswLoadElement(HnswElement element, float *distance, Datum *q, Relation index,
|
|||||||
TupleDesc tupdesc = RelationGetDescr(index);
|
TupleDesc tupdesc = RelationGetDescr(index);
|
||||||
bool unused;
|
bool unused;
|
||||||
|
|
||||||
value = index_getattr(itup, 1, tupdesc, &unused);
|
value = index_getattr(itup, IndexRelationGetNumberOfKeyAttributes(index), tupdesc, &unused);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
value = PointerGetDatum(&etup->data);
|
value = PointerGetDatum(&etup->data);
|
||||||
|
|||||||
@@ -585,8 +585,8 @@ InitVacuumState(HnswVacuumState * vacuumstate, IndexVacuumInfo *info, IndexBulkD
|
|||||||
vacuumstate->callback_state = callback_state;
|
vacuumstate->callback_state = callback_state;
|
||||||
vacuumstate->efConstruction = HnswGetEfConstruction(index);
|
vacuumstate->efConstruction = HnswGetEfConstruction(index);
|
||||||
vacuumstate->bas = GetAccessStrategy(BAS_BULKREAD);
|
vacuumstate->bas = GetAccessStrategy(BAS_BULKREAD);
|
||||||
vacuumstate->procinfo = index_getprocinfo(index, 1, HNSW_DISTANCE_PROC);
|
vacuumstate->procinfo = index_getprocinfo(index, IndexRelationGetNumberOfKeyAttributes(index), HNSW_DISTANCE_PROC);
|
||||||
vacuumstate->collation = index->rd_indcollation[0];
|
vacuumstate->collation = index->rd_indcollation[IndexRelationGetNumberOfKeyAttributes(index) - 1];
|
||||||
vacuumstate->ntup = palloc0(HNSW_TUPLE_ALLOC_SIZE);
|
vacuumstate->ntup = palloc0(HNSW_TUPLE_ALLOC_SIZE);
|
||||||
vacuumstate->tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
|
vacuumstate->tmpCtx = AllocSetContextCreate(CurrentMemoryContext,
|
||||||
"Hnsw vacuum temporary context",
|
"Hnsw vacuum temporary context",
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ $node->start;
|
|||||||
|
|
||||||
# Create table
|
# Create table
|
||||||
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
|
||||||
$node->safe_psql("postgres", "CREATE TABLE tst (i int4, v vector($dim), c int4);");
|
$node->safe_psql("postgres", "CREATE TABLE tst (i int4, v vector($dim), c int8);");
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT i, ARRAY[$array_sql], i % $nc FROM generate_series(1, 10000) i;"
|
"INSERT INTO tst SELECT i, ARRAY[$array_sql], i % $nc FROM generate_series(1, 10000) i;"
|
||||||
);
|
);
|
||||||
$node->safe_psql("postgres", "CREATE INDEX ON tst USING hnsw (v vector_l2_ops, c);");
|
$node->safe_psql("postgres", "CREATE INDEX ON tst USING hnsw (c, v vector_l2_ops);");
|
||||||
$node->safe_psql("postgres",
|
$node->safe_psql("postgres",
|
||||||
"INSERT INTO tst SELECT i, ARRAY[$array_sql], i % $nc FROM generate_series(1, 10000) i;"
|
"INSERT INTO tst SELECT i, ARRAY[$array_sql], i % $nc FROM generate_series(1, 10000) i;"
|
||||||
);
|
);
|
||||||
@@ -99,15 +99,15 @@ $node->safe_psql("postgres", "VACUUM tst;");
|
|||||||
|
|
||||||
# Test columns
|
# Test columns
|
||||||
my ($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (c);");
|
my ($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (c);");
|
||||||
like($stderr, qr/first column must be a vector/);
|
like($stderr, qr/last column must be a vector/);
|
||||||
|
|
||||||
($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (c, v vector_l2_ops);");
|
($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (c, c);");
|
||||||
like($stderr, qr/first column must be a vector/);
|
like($stderr, qr/last column must be a vector/);
|
||||||
|
|
||||||
($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (v vector_l2_ops, c, c);");
|
($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (c, c, v vector_l2_ops);");
|
||||||
like($stderr, qr/index cannot have more than two columns/);
|
like($stderr, qr/index cannot have more than two columns/);
|
||||||
|
|
||||||
($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (v vector_l2_ops, v vector_l2_ops);");
|
($ret, $stdout, $stderr) = $node->psql("postgres", "CREATE INDEX ON tst USING hnsw (v vector_l2_ops, v vector_l2_ops);");
|
||||||
like($stderr, qr/column 2 cannot be a vector/);
|
like($stderr, qr/column 1 cannot be a vector/);
|
||||||
|
|
||||||
done_testing();
|
done_testing();
|
||||||
|
|||||||
Reference in New Issue
Block a user