diff --git a/src/hnsw.c b/src/hnsw.c index e6558f7..3054d01 100644 --- a/src/hnsw.c +++ b/src/hnsw.c @@ -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; diff --git a/src/hnsw.h b/src/hnsw.h index 31b9a11..c416f0f 100644 --- a/src/hnsw.h +++ b/src/hnsw.h @@ -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 diff --git a/src/ivfflat.c b/src/ivfflat.c index 131b091..b78a1e8 100644 --- a/src/ivfflat.c +++ b/src/ivfflat.c @@ -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; diff --git a/src/ivfflat.h b/src/ivfflat.h index 462017b..19ae541 100644 --- a/src/ivfflat.h +++ b/src/ivfflat.h @@ -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