How to retrieve Index-Fillfactor from Postgresql Catalog tables? - postgresql

Am trying to load Postgres attributes from its catalog tables.
I have created a Postgres table and few set of indexes(unique index, clustered index).
With the below query I could the Name of the index, type of the index as well as its comments.
SELECT c.relname as indexname, i.indisunique as isUniqueIndex, i.indisclustered as isClustered, pg_catalog.obj_description(c.oid, 'pg_class') as COMMENT
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
JOIN pg_catalog.pg_class t ON i.indrelid = t.oid
WHERE c.relkind = 'i' and n.nspname = 'schema1' AND t.relname='table_with_index'
Is there a way to retrieve the fillfactor value of the index?
I'm using Postgresql 8.4 and I see the syntax for creating Index with fill factor, so hope there could be a way to get the value from the catalog tables.

A decent method is to run psql with the "-E" option to echo the catalog queries, then extract what you need from that.
Eg. psql -d your_db -E then issue \d+ <your index name>
An alternative query if you are looking for the index defintion is to use the pg_get_indexdef() function.
Eg.
select pg_get_indexdef('aaa_idx'::regclass::oid);
pg_get_indexdef
------------------------------------------------------------------
CREATE INDEX aaa_idx ON aaa USING btree (x) WITH (fillfactor=60)
I went ahead and extracted a catalog query from 9.2 which may or may not work in 8.4. It has been a while since I worked with the 8.4 catalogs and I can't recall if the tables referenced here have changed.
SELECT c.relchecks,
c.relkind,
c.relhasindex,
c.relhasrules,
c.relhastriggers,
c.relhasoids,
pg_catalog.array_to_string(c.reloptions || array(SELECT 'toast.' || x FROM pg_catalog.unnest(tc.reloptions) x), ', ') as storage_options,
c.reltablespace,
CASE
WHEN c.reloftype = 0 THEN ''
ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text
END,
c.relpersistence
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)
LEFT JOIN pg_namespace nsp ON nsp.oid = c.relnamespace
WHERE nsp.nspname = 'schema1'
AND c.relname = 'YOUR INDEX'

Related

Connecting Microstrategy Cube to a Postgres Materialized View

I have created a Materialized View in a Postgres Database. When I am creating my microstrategy cube connection to this Postgres Database, I am unable to see this Materialized View.
Can anyone help me to understand why I am unable to see this?
Thanks
You need to edit the read settings for your Warehouse Catalog.
Location: Schema->Warehouse Catalog Options->Catalog->Read Settings
Query for tables:
SELECT n.nspname as NAME_SPACE,
c.relname as TAB_NAME
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind in ('v', 'm', 'r', 'p', '')
AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
ORDER BY 1,2
Column Query:
hanged to LEFT JOIN in on table INFORMATION_SCHEMA.COLUMNS (no issues for me so far)
SELECT DISTINCT
nspname AS NAME_SPACE,
relname AS TAB_NAME,
attname AS COL_NAME,
typname AS DATA_TYPE,
COALESCE(B.CHARACTER_MAXIMUM_LENGTH, attlen) AS DATA_LEN,
NUMERIC_PRECISION AS DATA_PREC,
NUMERIC_SCALE AS DATA_SCALE
FROM
pg_attribute A
JOIN
pg_class C
ON
A.attrelid = C.oid
JOIN
pg_namespace N
ON
C.relnamespace = N.oid
JOIN
pg_type T
ON
A.atttypid = T.oid
LEFT OUTER JOIN
INFORMATION_SCHEMA.COLUMNS B
ON
A.attname = B.COLUMN_NAME
AND C.relname = B.TABLE_NAME
AND N.nspname = B.TABLE_SCHEMA
WHERE
relname IN (#TABLE_LIST#)
AND attnum > 0
ORDER BY
1,
2,
3
Especially the columns query could be improved but until now I haven't looked back at this as it works fine.
Reason for all of this can be found in the following discussion: Materialized views don't show up in information_schema.
Found a workaround for this...
You can create the view as a standard view, connect this to Microstrategy, and then delete the view and created as a Materialized View. This will then pick up the newly created Materialized view as long as you keep the same name.

How to get list of sequence names in Postgres?

I want to get the list of sequence names in Postgres.
In Oracle, I can use:
select sequence_name
from user_sequences
But in Postgres when I use that statement it always throws the error: not found user_sequences.
How can I do this in Postgres?
You can use:
select sequence_schema, sequence_name
from information_schema.sequences;
That will return a list of sequences accessible to the current user, not the ones owned by him.
If you want to list sequences owned by the current user you need to join pg_class, pg_namespace and pg_user:
select n.nspname as sequence_schema,
c.relname as sequence_name,
u.usename as owner
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
join pg_user u on u.usesysid = c.relowner
where c.relkind = 'S'
and u.usename = current_user;
In Postgres a user can own objects (e.g. sequences) in multiple schemas, not just "his own", so you also need to check in which schema the sequence is created.
More details in the manual:
https://www.postgresql.org/docs/current/static/infoschema-sequences.html
https://www.postgresql.org/docs/current/static/catalog-pg-class.html
SELECT c.relname FROM pg_class c WHERE c.relkind = 'S';
Or trying running psql as psql -U username -E followed by \ds. This will show you the query that was been used to generate the result as well.

List columns with indexes in Amazon Redshift

I need to query Redshift metadata to get a list of table columns that includes information whether the column is part of primary key or not.
There is a post already List columns with indexes in PostgreSQL that has an answer for PostgreSQL, however unfortunately, it fails on Redshift with "ERROR: 42809: op ANY/ALL (array) requires array on right side"
I figured out how to do it with the help of this https://bitbucket.org/zzzeek/sqlalchemy/pull-request/6/sqlalchemy-to-support-postgresql-80/diff
SELECT attname column_name, attnotnull,
format_type(atttypid, atttypmod) as column_type, atttypmod,
i.indisprimary as primary_key,
col_description(attrelid, attnum) as description
FROM pg_attribute c
LEFT OUTER JOIN pg_index i
ON c.attrelid = i.indrelid AND i.indisprimary AND
c.attnum = ANY(string_to_array(textin(int2vectorout(i.indkey)), ' '))
where c.attnum > 0 AND NOT c.attisdropped AND c.attrelid = :tableOid
order by attnum
The following worked for me:
SELECT n.nspname as schema_name,
t.relname as table_name,
i.relname as index_name,
c.contype as index_type,
a.attname as column_name,
a.attnum AS column_position
FROM pg_class t
INNER JOIN pg_index AS ix ON t.oid = ix.indrelid
INNER JOIN pg_constraint AS c ON ix.indrelid = c.conrelid
INNER JOIN pg_class AS i ON i.oid = ix.indexrelid
INNER JOIN pg_attribute AS a ON a.attrelid = t.oid
AND a.attnum= ANY(string_to_array(textin(int2vectorout(ix.indkey)),' ')::int[])
INNER JOIN pg_namespace AS n ON n.oid = t.relnamespace;
You can leverage the table DDL view AWS published a few months ago (https://github.com/awslabs/amazon-redshift-utils/blob/master/src/AdminViews/v_generate_tbl_ddl.sql) by picking out the constraint component and parsing out the key columns:
select schemaname,tablename, substring(ddl,charindex('(',ddl)+1, charindex(')',ddl)-1-charindex('(',ddl))
from
(
SELECT
n.nspname AS schemaname
,c.relname AS tablename
,200000000 + CAST(con.oid AS INT) AS seq
,'\t,' + pg_get_constraintdef(con.oid) AS ddl
FROM
pg_constraint AS con
INNER JOIN pg_class AS c
ON c.relnamespace = con.connamespace
AND c.relfilenode = con.conrelid
INNER JOIN pg_namespace AS n
ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
ORDER BY seq
)
Note that this query also gives you foreign key columns. It's easy enough to filter those out by appending the query with
where ddl like '%PRIMARY KEY%'
Use below query:
select * from pg_table_def where tablename = 'mytablename'
This will give you all columns for table along with their data type , encoding and if it has sort key or dist key.

Postgres: variable saying from which schema I select

I have created a SQL SELECT to get all enums and their values in a schema:
SELECT
t.typname, array_agg(e.enumlabel)
FROM pg_type t
JOIN pg_enum e ON t.oid = e.enumtypid
JOIN pg_namespace n ON t.typnamespace = n.oid
WHERE t.typtype = 'e' AND n.nspname = 'public'
GROUP BY typname
I have put the select into a view so I dont have to write it everytime I want to call it. The only thing that bothers me is that if I rename the schema or use it in another schema I have to rewrite the name of the schema manually, check line 6 of the code:
WHERE t.typtype = 'e' AND n.nspname = 'public'
Public is hardtyped there. When selecting in postgres, is there a "global" variable saying from which schema you select? I was not able to find any.
Thanks
PS: I use postgres 8.4
The current schema can be retrieved using the function current_schema()
http://www.postgresql.org/docs/current/static/functions-info.html
Alternatively to wiring the schema or looking it up with current_schema(), you could make your view group by schema as well and then select on the view.
create or replace view enum_vw as
SELECT
n.nspname, t.typname, array_agg(e.enumlabel)
FROM pg_type t
JOIN pg_enum e ON t.oid = e.enumtypid
JOIN pg_namespace n ON t.typnamespace = n.oid
WHERE t.typtype = 'e'
GROUP BY n.nspname, t.typname;
select * from enum_vw where nspname = 'public';

How do you view new sequence ownership information in Postgres after using ALTER SEQUENCE?

I'm using "ALTER SEQUENCE sequence OWNED BY table.column" to change sequence association in Postgres. Is there a way to view this new information using \ds or something similar? \ds still shows the table owner as the sequence owner.
SELECT c.relname,u.usename
FROM pg_class c, pg_user u
WHERE c.relowner = u.usesysid and c.relkind = 'S'
AND relnamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname NOT LIKE 'pg_%'
AND nspname != 'information_schema'
);
OWNED BY table.column changes the associated column; OWNER TO newowner changes the role which owns the sequence. The owner role is what is displayed in \ds. I don't know a psql command to see the linked column of a sequence. OWNED BY is primary used to cascade a delete of the associated sequence when the referent column is removed.
You can get visibility into the owned by column by constructing a query against the system catalog tables pg_class, pg_depend, and pg_attribute. I'm not sure of all the exact semantics of pg_depend, but this query should show you a sequence's column dependency:
select tab.relname as tabname, attr.attname as column
from pg_class as seq
join pg_depend as dep on (seq.relfilenode = dep.objid)
join pg_class as tab on (dep.refobjid = tab.relfilenode)
join pg_attribute as attr on (attr.attnum = dep.refobjsubid and attr.attrelid = dep.refobjid)
where seq.relname = 'sequence';
Yuri Levinsky's answer modified to include the namespace column:
SELECT n.nspname, c.relname, u.usename
FROM pg_class c
INNER JOIN pg_user u ON c.relowner = u.usesysid
INNER JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE c.relkind = 'S'
AND n.nspname NOT LIKE 'pg_%'
AND n.nspname != 'information_schema'
ORDER BY 1, 2, 3;