Postgres: variable saying from which schema I select - postgresql

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';

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 retrieve Index-Fillfactor from Postgresql Catalog tables?

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'

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;

Get table and column "owning" a sequence

I can run the following line:
ALTER SEQUENCE seqName OWNED BY table.id;
How can I get the 'owner' set by OWNED BY for a sequence (in this case: table.id)?
You may use following query:
select s.relname as seq, n.nspname as sch, t.relname as tab, a.attname as col
from pg_class s
join pg_depend d on d.objid=s.oid and d.classid='pg_class'::regclass and d.refclassid='pg_class'::regclass
join pg_class t on t.oid=d.refobjid
join pg_namespace n on n.oid=t.relnamespace
join pg_attribute a on a.attrelid=t.oid and a.attnum=d.refobjsubid
where s.relkind='S' and d.deptype='a'
It returns all sequences with owner information. Just filter them in WHERE clause and that's it.
Get the "owning" table and column
ALTER SEQUENCE seqName OWNED BY table.id;
Your ALTER SEQUENCE statement causes an entry in the system catalog pg_depend with the dependency type (deptype) 'a' and a refobjsubid greater than 0, pointing to the attribute number (attnum) in pg_attribute. With that knowledge you can devise a simple query:
SELECT d.refobjid::regclass, a.attname
FROM pg_depend d
JOIN pg_attribute a ON a.attrelid = d.refobjid
AND a.attnum = d.refobjsubid
WHERE d.objid = 'public."seqName"'::regclass -- your sequence here
AND d.refobjsubid > 0
AND d.classid = 'pg_class'::regclass;
Double quotes ("") are only needed for otherwise illegal names (mixed case, reserved words, ...).
No need to assert that refclassid is of type regclass since the join to pg_attribute does that automatically.
No need to assert that the sequence is a sequence since schema-qualified object names are unique across the database.
No need to join to pg_class or pg_namespace at all.
The schema name is only needed to disambiguate or if it's not in the search_path.
The same table name (or sequence name for that matter) can be used in multiple schemas. A cast to the object identifier type regclass observes the current search_path to pick the best match if you omit the schema qualification. If the table is not visible, you get an error message.
What's more, a regclass type is displayed as text to the user automatically. (If not, cast to text.) The schema-name is prepended automatically where necessary to be unambiguous in your session.
Get the actual "owner" (the role)
To get the role owning a specific sequence, as requested:
SELECT c.relname, u.usename
FROM pg_class c
JOIN pg_user u ON u.usesysid = c.relowner
WHERE c.oid = '"seqName"'::regclass; -- your sequence here
I was able to list the table and corresponding sequence for a particular column using the following SQL statement:
SELECT table_schema
, table_name
, column_name
, LTRIM(RTRIM(RTRIM(column_default, '::regclass)'),''''),'nextval(''') AS SEQUENCE_NAME
FROM information_schema.columns
WHERE column_default like '%nextval%';
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'
);
I use that query for get all queries.
Change CTE to filter the result
WITH table_with_sequence as (
SELECT
d.refobjid::regclass::text tablename,
c.relname::text sequencename,
np.nspname::text schemaname,
a.attname::text attname,
u.usename::text
FROM
pg_depend d
INNER JOIN pg_class c ON c.oid = d.objid
AND c.relkind = 'S'
INNER JOIN pg_namespace np ON np.oid = c.relnamespace
AND (np.nspname NOT LIKE 'pg_%'
AND np.nspname != 'information_schema')
INNER JOIN pg_user u ON u.usesysid = c.relowner
INNER JOIN pg_attribute a ON a.attrelid = d.refobjid
AND a.attnum = d.refobjsubid
)
SELECT
'ALTER SEQUENCE '|| QUOTE_LITERAL(QUOTE_IDENT(schemaname) || '.' || QUOTE_IDENT(sequencename)) ||' OWNED BY ' || tablename || '.' || QUOTE_IDENT(attname)
FROM table_with_sequence

Is it possible to discover the column types from a Postgres function?

I'm working on a utility that is using templates to generate a data access layer against a Postgres database. As part of this I'm trying to dynamically discover the return types of the stored procedures. This is easy enough in simple cases where a single standard type is returned, but I'm struggling when it comes to it returning a user defined type.
I'd appreciate if someone could provide the necessary SQL to return this data.
Thanks
Mark
I appreciate the answers that I have so far, which effectively boil to to the following SQL
SELECT p.proname, t.typname, p,proretset
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
INNER JOIN pg_type t ON p.prorettype = t.oid
WHERE n.nspname = 'public'
--and proname = 'foo'
ORDER BY proname;
This will return the name of the return types. However I still need to decompose the type into the properties that make it up when it returns a user defined type.
In the case that a function returns a record I don't think there is any way to discover its return structure other than calling the function and examining its return values.
psql meta commands are an easy shortcut to finding information schema stuff.
try test=# \d? to find introspection info.
then psql -E -c '\df' will show the sql behind the show function command:
d$ psql -E -c '\df+'
********* QUERY **********
SELECT n.nspname as "Schema",
p.proname as "Name",
pg_catalog.pg_get_function_result(p.oid) as "Result data type",
pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
CASE
WHEN p.proisagg THEN 'agg'
WHEN p.proiswindow THEN 'window'
WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
ELSE 'normal'
END as "Type",
CASE
WHEN p.provolatile = 'i' THEN 'immutable'
WHEN p.provolatile = 's' THEN 'stable'
WHEN p.provolatile = 'v' THEN 'volatile'
END as "Volatility",
pg_catalog.pg_get_userbyid(p.proowner) as "Owner",
l.lanname as "Language",
p.prosrc as "Source code",
pg_catalog.obj_description(p.oid, 'pg_proc') as "Description"
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang
WHERE pg_catalog.pg_function_is_visible(p.oid)
AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
ORDER BY 1, 2, 4;
**************************
In your case the would be what you want:
pg_catalog.pg_get_function_result(p.oid) as "Result data type",
This query will list the stored procedures with the types.
SELECT proname, proargnames as arguments,
oidvectortypes(proargtypes) as arguments_type,
t.typname as return_type,prosrc as source
FROM pg_catalog.pg_namespace n
JOIN pg_catalog.pg_proc p ON pronamespace = n.oid
JOIN pg_type t ON p.prorettype = t.oid
WHERE nspname = 'public'
You can always filter by proname.
Just to get started:
SELECT
*
FROM
pg_proc
JOIN pg_type ON pg_type.oid = ANY(proallargtypes)
WHERE
proname = 'foo';
Are you looking for this?
SELECT proname,
pg_get_function_result(oid)
FROM pg_proc
WHERE proname = 'foo';
if the function returns a record then the type is not known until runtime, demonstrated with:
create or replace function func() returns record language plpgsql immutable as $$
declare
r record;
q record;
begin
select 10, 'hello' into r;
select 11, 'hello', 'helloagain' into q;
if random()>0.5 then
return r;
else
return q;
end if;
end;$$;
in other words, you can't know the type until after you call the function. Once you have called the function, you could dynamically determine information about the record by passing it into a C-language function as referenced here
Thanks for the help guys, I'm think JackPDouglas is correct and that since functions that return record sets can be polymorphic that there's no way to find out the return type definition.
However here's the SQL I was looking for to get the definition of a function that returns a composite type:
SELECT t.typname, attname, a.typname
from pg_type t
JOIN pg_class on (reltype = t.oid)
JOIN pg_attribute on (attrelid = pg_class.oid)
JOIN pg_type a on (atttypid = a.oid)
WHERE t.typname = (
SELECT t.typname
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
INNER JOIN pg_type t ON p.prorettype = t.oid
WHERE n.nspname = 'public'
and proname = 'foo'
ORDER BY proname
);