Updated patch. Changes:
- returns NULL rather than "cache lookup failed"
- added pg_index_column_has_property (incl. docs)
- added regression tests
Not changed / need consideration:
- this still has everything in amapi.c rather than creating any new
files. Also, the regression tests are in create_index.sql for lack
of any obviously better place.
The list of column properties is:
ordered - (same as "amcanorder" AM capability)
ordered_asc
ordered_desc
ordered_nulls_first
ordered_nulls_last
If "ordered" is true then exactly one of _asc/_desc and exactly one of
_nulls_first/_last will be true; if "ordered" is false then all the
others will be false too. The intended usage is something like
CASE WHEN pg_index_column_has_property(idx, attno, 'ordered_asc')
THEN 'ASC'
WHEN pg_index_column_has_property(idx, attno, 'ordered_desc')
THEN 'DESC'
ELSE '' -- or NULL
END
Comments?
--
Andrew (irc:RhodiumToad)
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index ccb9b97..684f7b3 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -577,6 +577,89 @@
</tgroup>
</table>
+ <para>
+ Capability information formerly stored in <structname>pg_am</structname>
+ is now available via the functions
+ <function>pg_indexam_has_capability</function> and
+ <function>pg_index_has_capability</function>
+ (see <xref linkend="functions-info-catalog-table">). The following
+ boolean-valued capability names are currently supported:
+ </para>
+
+ <table>
+ <title>Capabilities</title>
+
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>amcanorder</literal></entry>
+ <entry>Does the access method support ordered scans sorted by the
+ indexed column's value?</entry>
+ </row>
+ <row>
+ <entry><literal>amcanorderbyop</literal></entry>
+ <entry>Does the access method support ordered scans sorted by the result
+ of an operator on the indexed column?</entry>
+ </row>
+ <row>
+ <entry><literal>amcanbackward</literal></entry>
+ <entry>Does the access method support backward scanning?</entry>
+ </row>
+ <row>
+ <entry><literal>amcanunique</literal></entry>
+ <entry>Does the access method support unique indexes?</entry>
+ </row>
+ <row>
+ <entry><literal>amcanmulticol</literal></entry>
+ <entry>Does the access method support multicolumn indexes?</entry>
+ </row>
+ <row>
+ <entry><literal>amoptionalkey</literal></entry>
+ <entry>Does the access method support a scan without any constraint
+ for the first index column?</entry>
+ </row>
+ <row>
+ <entry><literal>amsearcharray</literal></entry>
+ <entry>Does the access method support <literal>ScalarArrayOpExpr</> searches?</entry>
+ </row>
+ <row>
+ <entry><literal>amsearchnulls</literal></entry>
+ <entry>Does the access method support <literal>IS NULL</>/<literal>NOT NULL</> searches?</entry>
+ </row>
+ <row>
+ <entry><literal>amstorage</literal></entry>
+ <entry>Can index storage data type differ from column data type?</entry>
+ </row>
+ <row>
+ <entry><literal>amclusterable</literal></entry>
+ <entry>Can an index of this type be clustered on?</entry>
+ </row>
+ <row>
+ <entry><literal>ampredlocks</literal></entry>
+ <entry>Does an index of this type manage fine-grained predicate locks?</entry>
+ </row>
+ <row>
+ <entry><literal>amgettuple</literal></entry>
+ <entry>Does the access method provide an <function>amgettuple</function> function?</entry>
+ </row>
+ <row>
+ <entry><literal>amgetbitmap</literal></entry>
+ <entry>Does the access method provide an <function>amgetbitmap</function> function?</entry>
+ </row>
+ <row>
+ <entry><literal>amcanreturn</literal></entry>
+ <entry>Does the access method support index-only scans?</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
</sect1>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7830334..d2fe506 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16290,6 +16290,18 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
</indexterm>
<indexterm>
+ <primary>pg_indexam_has_capability</primary>
+ </indexterm>
+
+ <indexterm>
+ <primary>pg_index_column_has_property</primary>
+ </indexterm>
+
+ <indexterm>
+ <primary>pg_index_has_capability</primary>
+ </indexterm>
+
+ <indexterm>
<primary>pg_options_to_table</primary>
</indexterm>
@@ -16477,6 +16489,21 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
number of columns, pretty-printing is implied</entry>
</row>
<row>
+ <entry><literal><function>pg_indexam_has_capability(<parameter>am_oid</parameter>, <parameter>cap_name</>)</function></literal></entry>
+ <entry><type>boolean</type></entry>
+ <entry>Test whether an index access method has a specified capability</entry>
+ </row>
+ <row>
+ <entry><literal><function>pg_index_column_has_property(<parameter>index_oid</parameter>, <parameter>column_no</>, <parameter>prop_name</>)</function></literal></entry>
+ <entry><type>boolean</type></entry>
+ <entry>Test whether an index column has a specified property</entry>
+ </row>
+ <row>
+ <entry><literal><function>pg_index_has_capability(<parameter>index_oid</parameter>, <parameter>cap_name</>)</function></literal></entry>
+ <entry><type>boolean</type></entry>
+ <entry>Test whether the access method for the specified index has a specified capability</entry>
+ </row>
+ <row>
<entry><literal><function>pg_options_to_table(<parameter>reloptions</parameter>)</function></literal></entry>
<entry><type>setof record</type></entry>
<entry>get the set of storage option name/value pairs</entry>
@@ -16620,6 +16647,73 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
</para>
<para>
+ <function>pg_indexam_has_capability</function> and
+ <function>pg_index_has_capability</function> return whether the specified
+ access method, or the access method for the specified index, advertises the
+ named capability. <literal>NULL</literal> is returned if the capability
+ name is not known; <literal>true</literal> if the capability is advertised,
+ <literal>false</literal> if it is not. Refer
+ to <xref linkend="catalog-pg-am"> for capability names and their meanings.
+ </para>
+
+ <para>
+ <function>pg_index_column_has_property</function> returns whether the
+ specified index column possesses the named property.
+ <literal>NULL</literal> is returned if the property name is not
+ known; <literal>true</literal> if the property is present,
+ <literal>false</literal> if it is not. Index column property names and the
+ matching clauses of <literal>CREATE INDEX</> are given in
+ <xref linkend="functions-info-index-column-props">.
+ </para>
+
+ <table id="functions-info-index-column-props">
+ <title>Index Column Properties</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Clause</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>ordered</literal></entry>
+ <entry></entry>
+ <entry>Does the access method support ordered scans sorted by the
+ column's value?</entry>
+ </row>
+ <row>
+ <entry><literal>ordered_asc</literal></entry>
+ <entry><literal>ASC</></entry>
+ <entry>Does the column sort in ascending order on a forward scan?
+ </entry>
+ </row>
+ <row>
+ <entry><literal>ordered_desc</literal></entry>
+ <entry><literal>DESC</></entry>
+ <entry>Does the column sort in descending order on a forward scan?
+ </entry>
+ </row>
+ <row>
+ <entry><literal>ordered_nulls_first</literal></entry>
+ <entry><literal>NULLS FIRST</></entry>
+ <entry>Does the column sort with nulls first on a forward scan?
+ </entry>
+ </row>
+ <row>
+ <entry><literal>ordered_nulls_last</literal></entry>
+ <entry><literal>NULLS LAST</></entry>
+ <entry>Does the column sort with nulls last on a forward scan?
+ </entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
<function>pg_options_to_table</function> returns the set of storage
option name/value pairs
(<literal>option_name</>/<literal>option_value</>) when passed
diff --git a/src/backend/access/index/amapi.c b/src/backend/access/index/amapi.c
index d347ebc..8f9eb6b 100644
--- a/src/backend/access/index/amapi.c
+++ b/src/backend/access/index/amapi.c
@@ -16,7 +16,10 @@
#include "access/amapi.h"
#include "access/htup_details.h"
#include "catalog/pg_am.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
+#include "utils/elog.h"
#include "utils/syscache.h"
@@ -119,3 +122,180 @@ 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))
+ PG_RETURN_NULL();
+ 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);
+}
+
+/*
+ * Test for index column properties
+ */
+Datum
+pg_index_column_has_property(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ int32 attno = PG_GETARG_INT32(1);
+ text *propname = PG_GETARG_TEXT_PP(2);
+ char *nameptr = VARDATA_ANY(propname);
+ int namelen = VARSIZE_ANY_EXHDR(propname);
+ Oid amoid;
+ HeapTuple tuple;
+ Form_pg_class rd_rel;
+ Form_pg_index rd_index;
+ int16 natts;
+ Datum indoptionDatum;
+ bool isnull = false;
+ int2vector *indoption;
+ int16 indoption_val;
+ int16 iopt_test = 0;
+ int16 iopt_expect = 0;
+ IndexAmRoutine *routine = NULL;
+
+ tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ PG_RETURN_NULL();
+ 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;
+ natts = rd_rel->relnatts;
+ ReleaseSysCache(tuple);
+
+ if (attno < 1 || attno > natts)
+ PG_RETURN_NULL();
+
+ routine = GetIndexAmRoutineByAmId(amoid);
+
+ /*
+ * Currently, the only properties of interest are known in the core code,
+ * but in future it might be appropriate to punt unknown property names to
+ * a function in the amhandler.
+ */
+
+ if (namelen == 7 && memcmp(nameptr, "ordered", 7) == 0)
+ PG_RETURN_BOOL(routine->amcanorder);
+ else if (namelen == 11 && memcmp(nameptr, "ordered_asc", 11) == 0)
+ iopt_test = INDOPTION_DESC, iopt_expect = 0;
+ else if (namelen == 12 && memcmp(nameptr, "ordered_desc", 12) == 0)
+ iopt_test = INDOPTION_DESC, iopt_expect = INDOPTION_DESC;
+ else if (namelen == 19 && memcmp(nameptr, "ordered_nulls_first", 19) == 0)
+ iopt_test = INDOPTION_NULLS_FIRST, iopt_expect = INDOPTION_NULLS_FIRST;
+ else if (namelen == 18 && memcmp(nameptr, "ordered_nulls_last", 18) == 0)
+ iopt_test = INDOPTION_NULLS_FIRST, iopt_expect = 0;
+ else
+ PG_RETURN_NULL();
+
+ if (!routine->amcanorder)
+ PG_RETURN_BOOL(false);
+
+ tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ PG_RETURN_NULL();
+ rd_index = (Form_pg_index) GETSTRUCT(tuple);
+
+ Assert(relid == rd_index->indexrelid);
+ Assert(natts == rd_index->indnatts);
+
+ indoptionDatum = SysCacheGetAttr(INDEXRELID, tuple,
+ Anum_pg_index_indoption, &isnull);
+ Assert(!isnull);
+
+ indoption = ((int2vector *) DatumGetPointer(indoptionDatum));
+ indoption_val = indoption->values[attno - 1];
+ ReleaseSysCache(tuple);
+
+ if ((indoption_val & iopt_test) == iopt_expect)
+ PG_RETURN_BOOL(true);
+ else
+ PG_RETURN_BOOL(false);
+}
diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h
index 35f1061..af4e195 100644
--- a/src/include/access/amapi.h
+++ b/src/include/access/amapi.h
@@ -171,4 +171,8 @@ 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);
+extern Datum pg_index_column_has_property(PG_FUNCTION_ARGS);
+
#endif /* AMAPI_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 270dd21..0cbaab8 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_ ));
@@ -1988,6 +1993,9 @@ DESCR("result type of a function");
DATA(insert OID = 3808 ( pg_get_function_arg_default PGNSP PGUID 12 1 0 0 0 f f f f t f s s 2 0 25 "26 23" _null_ _null_ _null_ _null_ _null_ pg_get_function_arg_default _null_ _null_ _null_ ));
DESCR("function argument default");
+DATA(insert OID = 4032 ( pg_index_column_has_property PGNSP PGUID 12 1 0 0 0 f f f f t f s s 3 0 16 "26 23 25" _null_ _null_ _null_ _null_ _null_ pg_index_column_has_property _null_ _null_ _null_ ));
+DESCR("test boolean property of index column");
+
DATA(insert OID = 1686 ( pg_get_keywords PGNSP PGUID 12 10 400 0 0 f f f f t t s s 0 0 2249 "" "{25,18,25}" "{o,o,o}" "{word,catcode,catdesc}" _null_ _null_ pg_get_keywords _null_ _null_ _null_ ));
DESCR("list of SQL keywords");
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 76593e1..d27a5f8 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2953,6 +2953,89 @@ explain (costs off)
(2 rows)
--
+-- pg_index_column_has_property
+--
+CREATE INDEX onek_props1 ON onek (unique1 desc, unique2 asc, ten nulls first, hundred nulls last);
+select i, prop, pg_index_column_has_property(o, i, prop)
+ from (values ('onek_props1'::regclass)) v1(o),
+ (values (1,'ordered'),(2,'ordered_asc'),(3,'ordered_desc'),
+ (4,'ordered_nulls_first'),(5,'ordered_nulls_last')) v2(idx,prop),
+ generate_series(1,4) i
+ order by i, idx;
+ i | prop | pg_index_column_has_property
+---+---------------------+------------------------------
+ 1 | ordered | t
+ 1 | ordered_asc | f
+ 1 | ordered_desc | t
+ 1 | ordered_nulls_first | t
+ 1 | ordered_nulls_last | f
+ 2 | ordered | t
+ 2 | ordered_asc | t
+ 2 | ordered_desc | f
+ 2 | ordered_nulls_first | f
+ 2 | ordered_nulls_last | t
+ 3 | ordered | t
+ 3 | ordered_asc | t
+ 3 | ordered_desc | f
+ 3 | ordered_nulls_first | t
+ 3 | ordered_nulls_last | f
+ 4 | ordered | t
+ 4 | ordered_asc | t
+ 4 | ordered_desc | f
+ 4 | ordered_nulls_first | f
+ 4 | ordered_nulls_last | t
+(20 rows)
+
+select prop, pg_index_column_has_property(o, 1, prop)
+ from (values ('gcircleind'::regclass)) v1(o),
+ (values (1,'ordered'),(2,'ordered_asc'),(3,'ordered_desc'),
+ (4,'ordered_nulls_first'),(5,'ordered_nulls_last')) v2(idx,prop)
+ order by idx;
+ prop | pg_index_column_has_property
+---------------------+------------------------------
+ ordered | f
+ ordered_asc | f
+ ordered_desc | f
+ ordered_nulls_first | f
+ ordered_nulls_last | f
+(5 rows)
+
+DROP INDEX onek_props1;
+--
+-- index AM capabilites
+--
+select cap,
+ pg_index_has_capability('onek_hundred'::regclass, cap) as btree,
+ pg_index_has_capability('hash_i4_index'::regclass, cap) as hash,
+ pg_index_has_capability('gcircleind'::regclass, cap) as gist,
+ pg_index_has_capability('sp_radix_ind'::regclass, cap) as spgist,
+ pg_index_has_capability('botharrayidx'::regclass, cap) as gin
+ from unnest(array['amcanorder','amcanorderbyop','amcanbackward',
+ 'amcanunique','amcanmulticol','amoptionalkey',
+ 'amsearcharray','amsearchnulls','amstorage',
+ 'amclusterable','ampredlocks','amcanreturn',
+ 'amgettuple','amgetbitmap'
+ ]) with ordinality as u(cap,ord)
+ order by ord;
+ cap | btree | hash | gist | spgist | gin
+----------------+-------+------+------+--------+-----
+ amcanorder | t | f | f | f | f
+ amcanorderbyop | f | f | t | f | f
+ amcanbackward | t | t | f | f | f
+ amcanunique | t | f | f | f | f
+ amcanmulticol | t | f | t | f | t
+ amoptionalkey | t | f | t | t | t
+ amsearcharray | t | f | f | f | f
+ amsearchnulls | t | f | t | t | f
+ amstorage | f | f | t | f | t
+ amclusterable | t | f | t | f | f
+ ampredlocks | t | f | f | f | f
+ amcanreturn | t | f | t | t | f
+ amgettuple | t | t | t | t | f
+ amgetbitmap | t | t | t | t | t
+(14 rows)
+
+--
-- REINDEX (VERBOSE)
--
CREATE TABLE reindex_verbose(id integer primary key);
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index 71f4f54..62c76e5 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -1011,6 +1011,43 @@ explain (costs off)
select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
--
+-- pg_index_column_has_property
+--
+CREATE INDEX onek_props1 ON onek (unique1 desc, unique2 asc, ten nulls first, hundred nulls last);
+
+select i, prop, pg_index_column_has_property(o, i, prop)
+ from (values ('onek_props1'::regclass)) v1(o),
+ (values (1,'ordered'),(2,'ordered_asc'),(3,'ordered_desc'),
+ (4,'ordered_nulls_first'),(5,'ordered_nulls_last')) v2(idx,prop),
+ generate_series(1,4) i
+ order by i, idx;
+
+select prop, pg_index_column_has_property(o, 1, prop)
+ from (values ('gcircleind'::regclass)) v1(o),
+ (values (1,'ordered'),(2,'ordered_asc'),(3,'ordered_desc'),
+ (4,'ordered_nulls_first'),(5,'ordered_nulls_last')) v2(idx,prop)
+ order by idx;
+
+DROP INDEX onek_props1;
+
+--
+-- index AM capabilites
+--
+select cap,
+ pg_index_has_capability('onek_hundred'::regclass, cap) as btree,
+ pg_index_has_capability('hash_i4_index'::regclass, cap) as hash,
+ pg_index_has_capability('gcircleind'::regclass, cap) as gist,
+ pg_index_has_capability('sp_radix_ind'::regclass, cap) as spgist,
+ pg_index_has_capability('botharrayidx'::regclass, cap) as gin
+ from unnest(array['amcanorder','amcanorderbyop','amcanbackward',
+ 'amcanunique','amcanmulticol','amoptionalkey',
+ 'amsearcharray','amsearchnulls','amstorage',
+ 'amclusterable','ampredlocks','amcanreturn',
+ 'amgettuple','amgetbitmap'
+ ]) with ordinality as u(cap,ord)
+ order by ord;
+
+--
-- REINDEX (VERBOSE)
--
CREATE TABLE reindex_verbose(id integer primary key);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers