1
0
mirror of https://github.com/pgvector/pgvector.git synced 2026-10-23 10:48:54 +03:00

Added check for required support functions to amvalidate functions [skip ci]

This commit is contained in:
Andrew Kane
2026-10-22 14:14:23 -07:00
parent cbcf35510d
commit 6a0bcc3526
4 changed files with 66 additions and 4 deletions

View File

@@ -266,6 +266,7 @@ hnswvalidate(Oid opclassoid)
HeapTuple classtup;
Form_pg_opclass classform;
Oid opcintype;
char *opclassname;
Oid opfamilyoid;
#if PG_VERSION_NUM < 180000
HeapTuple familytup;
@@ -274,6 +275,9 @@ hnswvalidate(Oid opclassoid)
char *opfamilyname;
CatCList *proclist;
CatCList *oprlist;
List *grouplist;
OpFamilyOpFuncGroup *opclassgroup;
ListCell *lc;
/* Fetch opclass information */
classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
@@ -281,6 +285,7 @@ hnswvalidate(Oid opclassoid)
elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
classform = (Form_pg_opclass) GETSTRUCT(classtup);
opcintype = classform->opcintype;
opclassname = NameStr(classform->opcname);
/* Fetch opfamily information */
opfamilyoid = classform->opcfamily;
@@ -392,6 +397,31 @@ hnswvalidate(Oid opclassoid)
}
}
grouplist = identify_opfamily_groups(oprlist, proclist);
opclassgroup = NULL;
foreach(lc, grouplist)
{
OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);
if (thisgroup->lefttype == opcintype &&
thisgroup->righttype == opcintype)
opclassgroup = thisgroup;
}
/* Check required support functions */
for (int i = 1; i <= HNSW_NPROCS; i++)
{
if (opclassgroup && (opclassgroup->functionset & (((int64) 1) << i)) != 0)
continue;
if (i == HNSW_NORM_PROC || i == HNSW_TYPE_INFO_PROC)
continue;
ereport(INFO,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("operator class \"%s\" of access method %s is missing support function %d",
opclassname, "hnsw", i)));
result = false;
}
ReleaseCatCacheList(proclist);
ReleaseCatCacheList(oprlist);
#if PG_VERSION_NUM < 180000
@@ -415,7 +445,7 @@ hnswhandler(PG_FUNCTION_ARGS)
static const IndexAmRoutine amroutine = {
.type = T_IndexAmRoutine,
.amstrategies = 0,
.amsupport = 3,
.amsupport = HNSW_NPROCS,
.amoptsprocnum = 0,
.amcanorder = false,
.amcanorderbyop = true,
@@ -472,7 +502,7 @@ hnswhandler(PG_FUNCTION_ARGS)
IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
amroutine->amstrategies = 0;
amroutine->amsupport = 3;
amroutine->amsupport = HNSW_NPROCS;
amroutine->amoptsprocnum = 0;
amroutine->amcanorder = false;
amroutine->amcanorderbyop = true;

View File

@@ -37,6 +37,7 @@ typedef Pointer Item;
#define HNSW_DISTANCE_PROC 1
#define HNSW_NORM_PROC 2
#define HNSW_TYPE_INFO_PROC 3
#define HNSW_NPROCS 3
#define HNSW_VERSION 1
#define HNSW_MAGIC_NUMBER 0xA953A953

View File

@@ -183,6 +183,7 @@ ivfflatvalidate(Oid opclassoid)
HeapTuple classtup;
Form_pg_opclass classform;
Oid opcintype;
char *opclassname;
Oid opfamilyoid;
#if PG_VERSION_NUM < 180000
HeapTuple familytup;
@@ -191,6 +192,9 @@ ivfflatvalidate(Oid opclassoid)
char *opfamilyname;
CatCList *proclist;
CatCList *oprlist;
List *grouplist;
OpFamilyOpFuncGroup *opclassgroup;
ListCell *lc;
/* Fetch opclass information */
classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassoid));
@@ -198,6 +202,7 @@ ivfflatvalidate(Oid opclassoid)
elog(ERROR, "cache lookup failed for operator class %u", opclassoid);
classform = (Form_pg_opclass) GETSTRUCT(classtup);
opcintype = classform->opcintype;
opclassname = NameStr(classform->opcname);
/* Fetch opfamily information */
opfamilyoid = classform->opcfamily;
@@ -315,6 +320,31 @@ ivfflatvalidate(Oid opclassoid)
}
}
grouplist = identify_opfamily_groups(oprlist, proclist);
opclassgroup = NULL;
foreach(lc, grouplist)
{
OpFamilyOpFuncGroup *thisgroup = (OpFamilyOpFuncGroup *) lfirst(lc);
if (thisgroup->lefttype == opcintype &&
thisgroup->righttype == opcintype)
opclassgroup = thisgroup;
}
/* Check required support functions */
for (int i = 1; i <= IVFFLAT_NPROCS; i++)
{
if (opclassgroup && (opclassgroup->functionset & (((int64) 1) << i)) != 0)
continue;
if (i == IVFFLAT_NORM_PROC || i == IVFFLAT_KMEANS_NORM_PROC || i == IVFFLAT_TYPE_INFO_PROC)
continue;
ereport(INFO,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("operator class \"%s\" of access method %s is missing support function %d",
opclassname, "hnsw", i)));
result = false;
}
ReleaseCatCacheList(proclist);
ReleaseCatCacheList(oprlist);
#if PG_VERSION_NUM < 180000
@@ -338,7 +368,7 @@ ivfflathandler(PG_FUNCTION_ARGS)
static const IndexAmRoutine amroutine = {
.type = T_IndexAmRoutine,
.amstrategies = 0,
.amsupport = 5,
.amsupport = IVFFLAT_NPROCS,
.amoptsprocnum = 0,
.amcanorder = false,
.amcanorderbyop = true,
@@ -395,7 +425,7 @@ ivfflathandler(PG_FUNCTION_ARGS)
IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);
amroutine->amstrategies = 0;
amroutine->amsupport = 5;
amroutine->amsupport = IVFFLAT_NPROCS;
amroutine->amoptsprocnum = 0;
amroutine->amcanorder = false;
amroutine->amcanorderbyop = true;

View File

@@ -39,6 +39,7 @@ typedef Pointer Item;
#define IVFFLAT_KMEANS_DISTANCE_PROC 3
#define IVFFLAT_KMEANS_NORM_PROC 4
#define IVFFLAT_TYPE_INFO_PROC 5
#define IVFFLAT_NPROCS 5
#define IVFFLAT_VERSION 1
#define IVFFLAT_MAGIC_NUMBER 0x14FF1A7