Eu criei a seguinte consulta para obter o nome da tabela, index_type, operator_classes e exclusividade dos índices com base nas respostas principalmente de @Erwin Brandstetter:
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;
Isso funciona muito bem, exceto que retorna nomes de colunas errados quando o índice é criado pela transformação de dados de outra coluna. Por exemplo, com o seguinte índice:
CREATE INDEX _ixtr_luxury_inventory_images ON public.luxury_inventory
USING gin (f_textarr2text(images) gin_trgm_ops)
retorna:
table | luxury_inventory
index_name | _ixtr_luxury_inventory_images
index_type | gin
operator_classes | ['gin_trgm_ops']
is_unique | False
column_names | ['f_textarr2text']
Obtemos f_textarr2text
o nome da coluna em vez de images
.
Como podemos obter os column_names corretos? Estou no Postgres 16.2, se isso importa.
Atualização: Aqui está o SQL de criação da tabela:
create table "luxury_inventory" (
id bigserial primary key,
images text[])
CREATE OR REPLACE FUNCTION "public".f_textarr2text(text[])
RETURNS text LANGUAGE sql IMMUTABLE AS $$SELECT array_to_string($1, ',')$$;
Pensando nisso por um momento, talvez seja melhor do que
pg_get_indexdef
extrair ordinais da colunaindexprs
anotada na primeira resposta e, especificamente, dovarattno
campo.regexp_matches
sobre os 'indexprs' (convertendopg_tree_node
paratext
) paravarattno
)Juntei o seguinte, voltando à definição na
columns
tabela deinformation_schema
:e isso produz:
Sinto que isso está muito mais de acordo com o que ambos desejaríamos.
Observe que:
attname
mesa, porque isso é tudo que precisoJSON_AGG(columns.column_name)
pode ser substituído porJSON_AGG(columns.*)
ou algo semelhante para selecionar a linha inteira para as colunas.ANY (ARRAY['r', 't', 'i']
foi atualizado paraIN ANY ('r', 't', 'i')
EDITAR:
Para trazer isso para uma única coluna, vamos
COALESCE
, e sempre que a nova função retornarNULL
, inseriremos um array contendo o resultado depg_get_indexdef
, eARRAY_AGG
preferimosJSON_AGG
. Todos juntos:Isso produz:
Tente
pg_get_indexdef
, assim:Deve-se lembrar que um índice pode referir-se a múltiplas colunas, e assim uma função pode exigir múltiplas colunas como argumentos.
Dito isto, recuperando
pg_get_indexdef
e aplicando um pouco de regexp, podemos obter nossos argumentosOnde apenas índices definidos com chamadas de função retornam linhas aqui:
Em última análise, você está recuperando o nome da função porque essa chamada de função está sendo usada para construir o índice, e não simplesmente a coluna subjacente.
Observe a
pg_catalog.pg_index.indexprs
coluna na sua consulta e você verá algo parecido com o seguinte, que expõe como a função é indexada: