Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to introspect materialized views

I have a utility that introspects columns of tables using:

select column_name, data_type from information_schema.columns
        where table_name=%s

How can I extend this to introspect columns of materialized views?

like image 760
shaunc Avatar asked Oct 01 '13 23:10

shaunc


2 Answers

Your query carries a few shortcomings / room for improvement:

  • A table name is not unique inside a database, you would have to narrow down to a specific schema, or could get surprising / misleading / totally incorrect results.
    It's much more effective / convenient to cast the (optionally) schema-qualified table name to regclass ... see below.

  • A cast to regtype gives you generic type names instead of internal ones. But that's still only the base type.
    Use the system catalog information functions format_type() instead to get an exact type name including modifiers.

  • With the above improvements you don't need to join to additional tables. Just pg_attribute.

  • Dropped columns reside in the catalog until the table is vacuumed (fully). You need to exclude those.

SELECT attname, atttypid::regtype AS base_type
              , format_type(atttypid, atttypmod) AS full_type
FROM   pg_attribute
WHERE  attrelid = 'myschema.mytable'::regclass
AND    attnum > 0
AND    NOT attisdropped;  -- no dead columns

As an aside: the views in the information schema are only good for standard compliance and portability (rarely works anyway). If you don't plan to switch your RDBMS, stick with the catalog tables, which are much faster - and more complete, apparently.

like image 53
Erwin Brandstetter Avatar answered Oct 07 '22 05:10

Erwin Brandstetter


It would seem that postgres 9.3 has left materialized views out of the information_schema. (See http://postgresql.1045698.n5.nabble.com/Re-Materialized-views-WIP-patch-td5740513i40.html for a discussion.)

The following will work for introspection:

select attname, typname 
from pg_attribute a 
join pg_class c on a.attrelid = c.oid 
join pg_type t on a.atttypid = t.oid
where relname = %s and attnum >= 1;

The clause attnum >= 1 suppresses system columns. The type names are pg_specific this way, I guess, but good enough for my purposes.

like image 23
shaunc Avatar answered Oct 07 '22 04:10

shaunc