I have come up with the following query to get the table name, index_type, operator_classes, and uniqueness of indexes based on the answers mostly from @Erwin Brandstetter: ```sql SELECT i.indrelid::regclass::text AS table , c.relname AS index_name , a.amname AS index_type , opc.operator_classes , i.indisunique AS is_unique , array_agg(att.attname) as column_names FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON c.relnamespace = n.oid JOIN pg_catalog.pg_attribute att ON att.attrelid = c.oid JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid JOIN pg_catalog.pg_am a ON a.oid = c.relam CROSS JOIN LATERAL ( SELECT ARRAY (SELECT opc.opcname FROM unnest(i.indclass::oid[]) WITH ORDINALITY o(oid, ord) JOIN pg_opclass opc ON opc.oid = o.oid ORDER BY o.ord) ) opc(operator_classes) WHERE n.nspname !~ '^pg_' AND c.relkind = ANY (ARRAY['r', 't', 'i']) group by i.indrelid, c.relname, a.amname, opc.operator_classes, i.indisunique ORDER BY 1, 2, 3, 4; ``` This works great, except it returns the wrong column names when the index is created by transforming data from another column. For example, with the following index: ```sql CREATE INDEX _ixtr_luxury_inventory_images ON public.luxury_inventory USING gin (f_textarr2text(images) gin_trgm_ops) ``` returns: ``` table | luxury_inventory index_name | _ixtr_luxury_inventory_images index_type | gin operator_classes | ['gin_trgm_ops'] is_unique | False column_names | ['f_textarr2text'] ``` We get `f_textarr2text` as the column name instead of `images`. How can we get the correct column_names? I'm on Postgres 16.2 if that matters.