Here is my proposed code (first cut; obviously it needs docs too). Opinions?
-- Andrew (irc:RhodiumToad)
diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c index d347ebc..3e7e084 100644 --- a/src/backend/access/index/amapi.c +++ b/src/backend/access/index/amapi.c @@ -16,7 +16,9 @@ #include "access/amapi.h" #include "access/htup_details.h" #include "catalog/pg_am.h" +#include "catalog/pg_class.h" #include "catalog/pg_opclass.h" +#include "utils/elog.h" #include "utils/syscache.h" @@ -119,3 +121,95 @@ amvalidate(PG_FUNCTION_ARGS) PG_RETURN_BOOL(result); } + + +/* + * Test capabilities of an index or index AM. + */ +static Datum +indexam_capability(FunctionCallInfo fcinfo, + Oid amoid, char *nameptr, int namelen) +{ + IndexAmRoutine *routine = NULL; + bool ret; + + if (namelen < 1 || namelen > 14) + PG_RETURN_NULL(); + + routine = GetIndexAmRoutineByAmId(amoid); + + if (namelen == 10 && memcmp(nameptr, "amcanorder", 10) == 0) + ret = (routine->amcanorder) ? true : false; + else if (namelen == 14 && memcmp(nameptr, "amcanorderbyop", 14) == 0) + ret = (routine->amcanorderbyop) ? true : false; + else if (namelen == 13 && memcmp(nameptr, "amcanbackward", 13) == 0) + ret = (routine->amcanbackward) ? true : false; + else if (namelen == 11 && memcmp(nameptr, "amcanunique", 11) == 0) + ret = (routine->amcanunique) ? true : false; + else if (namelen == 13 && memcmp(nameptr, "amcanmulticol", 13) == 0) + ret = (routine->amcanmulticol) ? true : false; + else if (namelen == 13 && memcmp(nameptr, "amoptionalkey", 13) == 0) + ret = (routine->amoptionalkey) ? true : false; + else if (namelen == 13 && memcmp(nameptr, "amsearcharray", 13) == 0) + ret = (routine->amsearcharray) ? true : false; + else if (namelen == 13 && memcmp(nameptr, "amsearchnulls", 13) == 0) + ret = (routine->amsearchnulls) ? true : false; + else if (namelen == 9 && memcmp(nameptr, "amstorage", 9) == 0) + ret = (routine->amstorage) ? true : false; + else if (namelen == 13 && memcmp(nameptr, "amclusterable", 13) == 0) + ret = (routine->amclusterable) ? true : false; + else if (namelen == 11 && memcmp(nameptr, "ampredlocks", 11) == 0) + ret = (routine->ampredlocks) ? true : false; + else if (namelen == 11 && memcmp(nameptr, "amcanreturn", 11) == 0) + ret = (routine->amcanreturn) ? true : false; + else if (namelen == 10 && memcmp(nameptr, "amgettuple", 10) == 0) + ret = (routine->amgettuple) ? true : false; + else if (namelen == 11 && memcmp(nameptr, "amgetbitmap", 11) == 0) + ret = (routine->amgetbitmap) ? true : false; + else + PG_RETURN_NULL(); + + PG_RETURN_BOOL(ret); +} + +/* + * Test capability of an AM specified by the AM Oid. + */ +Datum +pg_indexam_has_capability(PG_FUNCTION_ARGS) +{ + Oid amoid = PG_GETARG_OID(0); + text *name = PG_GETARG_TEXT_PP(1); + char *nameptr = VARDATA_ANY(name); + int namelen = VARSIZE_ANY_EXHDR(name); + + return indexam_capability(fcinfo, amoid, nameptr, namelen); +} + +/* + * Test capability of the AM for an index specified by relation Oid. + */ +Datum +pg_index_has_capability(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + text *name = PG_GETARG_TEXT_PP(1); + char *nameptr = VARDATA_ANY(name); + int namelen = VARSIZE_ANY_EXHDR(name); + Oid amoid; + HeapTuple tuple; + Form_pg_class rd_rel; + + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "could not find tuple for relation %u", relid); + rd_rel = (Form_pg_class) GETSTRUCT(tuple); + if (rd_rel->relkind != RELKIND_INDEX) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation %u is not an index", relid))); + amoid = rd_rel->relam; + ReleaseSysCache(tuple); + + return indexam_capability(fcinfo, amoid, nameptr, namelen); +} diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index 35f1061..0e2f9d7 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -171,4 +171,7 @@ extern IndexAmRoutine *GetIndexAmRoutineByAmId(Oid amoid); extern Datum amvalidate(PG_FUNCTION_ARGS); +extern Datum pg_indexam_has_capability(PG_FUNCTION_ARGS); +extern Datum pg_index_has_capability(PG_FUNCTION_ARGS); + #endif /* AMAPI_H */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 5d233e3..4e696fa 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -564,6 +564,11 @@ DESCR("spgist index access method handler"); DATA(insert OID = 335 ( brinhandler PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 325 "2281" _null_ _null_ _null_ _null_ _null_ brinhandler _null_ _null_ _null_ )); DESCR("brin index access method handler"); +DATA(insert OID = 336 ( pg_indexam_has_capability PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ pg_indexam_has_capability _null_ _null_ _null_ )); +DESCR("test capability of an index access method"); +DATA(insert OID = 337 ( pg_index_has_capability PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 16 "26 25" _null_ _null_ _null_ _null_ _null_ pg_index_has_capability _null_ _null_ _null_ )); +DESCR("test capability of an index"); + DATA(insert OID = 338 ( amvalidate PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ amvalidate _null_ _null_ _null_ )); DESCR("validate an operator class"); DATA(insert OID = 3952 ( brin_summarize_new_values PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 23 "2205" _null_ _null_ _null_ _null_ _null_ brin_summarize_new_values _null_ _null_ _null_ ));
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers