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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers