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

Reply via email to