5

There is a lot of information, that can be retrieved from information_schema and pg_catalog in postgresql. I would like to retrieve information about columns indexed by a certain index, similar to what I would achieve with pragma index_info(<index_name>) in sqlite3. How can this be achieved without parsing create index statement?

1
  • @OMG Ponies: Because the answer is not as simple as it sounds. Commented Mar 20, 2011 at 21:43

2 Answers 2

7

Those things are pretty easy to find out.

Simply run psql with the -E option and it will show you the SQL statements that are used. So when running \d index_name the following statement (among others) is used to retrieve the index columns:

SELECT a.attname,
       pg_catalog.format_type (a.atttypid,a.atttypmod),
       (SELECT SUBSTRING (pg_catalog.pg_get_expr (d.adbin,d.adrelid) FOR 128)
        FROM pg_catalog.pg_attrdef d
        WHERE d.adrelid = a.attrelid
        AND   d.adnum = a.attnum
        AND   a.atthasdef),
       a.attnotnull,
       a.attnum,
       pg_catalog.pg_get_indexdef (a.attrelid,a.attnum,TRUE) AS indexdef
FROM pg_catalog.pg_attribute a
WHERE a.attrelid = (SELECT oid FROM pg_class WHERE relname = 'index_name')
AND   a.attnum > 0
AND   NOT a.attisdropped
ORDER BY a.attnum;
Sign up to request clarification or add additional context in comments.

1 Comment

I had no idea, that you can display an index information with \d. That's very helpful, as well as '-E' option. Thanks a lot.
1

Accepted answer didn't work for me (error occured on execution).

Anyway, you can list all columns in the database and mark all indexed in some way columns (abilities to limit result rowset are mentioned as comments):

    WITH 
    table_select as (
        select row_number() over(ORDER BY relname) as rownum, 
        c.relname, c.oid, c.reltuples
        FROM pg_class c
        JOIN pg_namespace n ON (n.oid = c.relnamespace)
        WHERE  c.relkind = 'r'::"char" 
               --AND n.nspname = '%MyNameSpaceHere%'
        ORDER BY c.relname      
    ),
    indxs as (
    select distinct t.relname as table_name, a.attname as column_name
    from pg_class t,  pg_class i, pg_index ix, pg_attribute a
    where
        t.oid = ix.indrelid
        and i.oid = ix.indexrelid
        and a.attrelid = t.oid
        and a.attnum = ANY(ix.indkey)
        and t.relkind = 'r'
        --and t.relname like 'mytable here'
        and cast (i.oid::regclass as text) like '%MyNameSpaceHere%'
    order by
        t.relname --, i.relname
    ),
    cols as (
    select a.attname, a.attrelid, c.oid, col.TABLE_NAME, col.COLUMN_NAME 
       FROM table_select c
        JOIN pg_attribute a ON (a.attrelid = c.oid) AND  (a.attname <> 'tableoid')
        LEFT JOIN information_schema.columns col ON 
(col.TABLE_NAME = c.relname AND col.COLUMN_NAME = a.attname )
      WHERE    
          ( a.attnum >= 0 ) --attnum > 0 for real columns
    )

    --select * from table_select t
    select c.TABLE_NAME, c.COLUMN_NAME, 
        case when i.column_name is not null then 'Y' else '' end as is_indexed 
    from cols c
    left join indxs i on (i.table_name = c.table_name and i.column_name = c.column_name)

The example result:

    table_name column_name is_indexed
   'events        id          "Y"
    events       type         "Y"
    events       descr         ""   '

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.