Is there a way to track Functions dependencies in Postgresql? - postgresql

I have a lot of functions and stored procedures in my PostgreSQL database that is dependent on each other. I want to run a script that will compile those function fist which is independent and not referring any other functions. Then I want to compile next level functions and so on until I reach top level function.
SQL Server has sys.sql_expression_dependencies table which keeps track of referencing objects and referenced objects? Do we have anything like that in Postgres? if not how to achieve it.

What is reason? PostgreSQL PL/pgSQL functions has not compile (better validation) time dependency. There is runtime dependency only. Currently there is not a tool for this purpose, what I know. But some dependency can be taken from PL profiler https://bitbucket.org/openscg/plprofiler.

You can try this query:
select t.*, f.* from
(
SELECT table_name,table_schema,
table_schema||'.'||table_name full_name,
table_type
FROM information_schema.tables
WHERE table_schema not in ('information_schema') and table_schema not like 'pg%'
) t
JOIN
(
SELECT n.nspname AS schema_name,
p.proname AS function_name,
pg_get_function_arguments(p.oid) AS args,
pg_get_functiondef(p.oid) AS func_def
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname not in ('pg_catalog','information_schema') and n.nspname not like 'pg%'
) f
on position(t.table_name in f.func_def) >0

Related

How to find the number of functions, stored procedures in postgresql?

How can I find the number of User-defined functions and Stored Procedures in PostgreSQL database?
It will work for you :
(editted by #a_horse_with_no_name 's warn)
SELECT count(*)
FROM information_schema.routines
WHERE routines.specific_schema='schema_name'
This excludes metadata schemas of postgres:
select count(*) from information_schema.routines t where t.routine_schema not in ('pg_catalog', 'information_schema');
If you're only interested in the number of procedures then:
select count(*) from information_schema.routines t where t.routine_schema not in ('pg_catalog', 'information_schema') and t.routine_type = 'PROCEDURE';

How to take entire database Store Procedure Scripts

How to take entire database store procedures full scripts same as the MS SQL 2008 R2 Generate Script feature. Need help.
The following query will return the complete DDL statements for each function that is owned by the current user in the schema public:
select pg_get_functiondef(p.oid)||';'
from pg_proc p
join pg_namespace n on n.oid = p.pronamespace
join pg_user u on u.usesysid = p.proowner
where n.nspname = 'public'
and p.prokind <> 'a'
and u.usename = current_user;
prokind <> 'a' is necessary because pg_get_functiondef() doesn't work with user defined aggregate functions.
If you want the functions from a different schema or owner, just change the where conditions accordingly.
You can spool the output to a file to get a SQL script containing all functions.

How do I execute the result of a query using the psql client?

Using the psql client version 8.4.20, I created this select command that generates a bunch of other select commands:
mydatabase=# select concat('select count(*) from ', table_schema, '.', table_name, ';') from information_schema.tables where table_name like '%stockindex_alias%';
select count(*) from de_de.merged_stockindex_alias_de_de;
select count(*) from en_us.merged_stockindex_alias_en_us;
select count(*) from es_la.merged_stockindex_alias_es_la;
select count(*) from fr_fr.merged_stockindex_alias_fr_fr;
select count(*) from nl_nl.merged_stockindex_alias_nl_nl;
select count(*) from pt_br.merged_stockindex_alias_pt_br;
select count(*) from zh_hk.merged_stockindex_alias_zh_hk;
I know I can use \g to store those seven statements into a file, then execute the file with \i.
How can I execute the result of the query (those seven statements) in a single command without the intermediate file? I've tried \set, EXECUTE, searched the web, but can't get it right.
EDIT: The previous select statements erroneously had the word "table" in them, which I have fixed.
I don't know if it works in 8.4; it works in 9.2.
DO $$
DECLARE
x text;
BEGIN
FOR x IN (select concat('select count(*) from ', table_schema, '.', table_name, ';') from information_schema.tables where table_name like '%stockindex_alias%' LOOP
EXECUTE x;
END LOOP;
END;
$$;
Basically you create an anonymous function block and execute it. Function blocks (or whatever the correct name is) allow for variable declaration and dynamic execution.
If you can get by with an approximate count, you can use the system catalogs:
SELECT s.nspname AS locale, c.reltuples AS count
FROM pg_class c
JOIN pg_namespace s ON s.oid = c.relnamespace
WHERE c.relname LIKE '%stockindex_alias%';
This will be most accurate immediately after a VACUUM ANALYZE (assuming you are a superuser or own all the affected tables) and gradually reducing in accuracy as the affected tables are modified.

postgresql extracting function source

Need to extract the source of a PostgreSQL function using SQL.
I am seeing this odd behavior with one of the function, all other functions (around 200+ ) work absolutely fine.
When I run the following statement, it works:
select prosrc from pg_proc where proname= 'accounts_count';
However when I run the following, it returns an empty string:
select routine_definition
from information_schema.routines
where specific_name = 'accounts_count_66243'
PostgreSQL version 8.3. I have tried using both pgAdmin III and psql.
Not a show stopper, but would be useful to know why this might be.
Any ideas anyone?
if you look on definition of information_schema.routines, then you can find following filter:
FROM pg_namespace n, pg_proc p, pg_language l, pg_type t, pg_namespace nt
WHERE n.oid = p.pronamespace AND p.prolang = l.oid AND p.prorettype = t.oid
AND t.typnamespace = nt.oid AND (pg_has_role(p.proowner, 'USAGE'::text)
OR has_function_privilege(p.oid, 'EXECUTE'::text));
so my theory:
there are some issue in rights and ownership of related function (probably) - try to use different account for validation of this theory (postgres is best)

Find out if user got permission to select/update/... a table/function/... in PostgreSQL

What is the recommended way to figure out if a user got a certain right (e.g. select or execute) on a certain class (e.g. table or function) in PostgreSQL?
At the moment I got something like
aclcontains(
someColumnWithAclitemArray,
makeaclitem(userOid,grantorOid,someRight,false))
but it's terrible since I have to check for every grantorOid that is possible and for every userOid the user can belong to.
On a related note: what are the possible rights you can test for?
I haven't found any documentation but reading the source code I guess:
INSERT
SELECT
UPDATE
DELETE
TRUNCATE
REFERENCES
TRIGGER
EXECUTE
USAGE
CREATE
CONNECT
There also seems to be a CREATE TEMP right, but I can't figure out the correct text to use in the makeaclitem-function.
I've found that a better approach (and I seem to remember this was taken from some queries built into psql, or maybe the information_schema views) is to use the has_*_privilege functions, and simply apply them to a set of all possible combinations of user and object. This will take account of having access to an object via some group role as well.
For example, this will show which users have which access to non-catalogue tables and views:
select usename, nspname || '.' || relname as relation,
case relkind when 'r' then 'TABLE' when 'v' then 'VIEW' end as relation_type,
priv
from pg_class join pg_namespace on pg_namespace.oid = pg_class.relnamespace,
pg_user,
(values('SELECT', 1),('INSERT', 2),('UPDATE', 3),('DELETE', 4)) privs(priv, privorder)
where relkind in ('r', 'v')
and has_table_privilege(pg_user.usesysid, pg_class.oid, priv)
and not (nspname ~ '^pg_' or nspname = 'information_schema')
order by 2, 1, 3, privorder;
The possible privileges are detailed in the description of the has_*_privilege functions at http://www.postgresql.org/docs/current/static/functions-info.html#FUNCTIONS-INFO-ACCESS-TABLE.
'CREATE TEMP' is a database-level privilege: it permits a user to use a pg_temp_* schema. It can be tested with has_database_privilege(useroid, datoid, 'TEMP').
Take a look at the "Access Privilege Inquiry Functions" and also the "GRANT" reference page.
Because Redshift is supporting values() only in INSERT INTO queries, the below query can be used with the obviously not-so-nice union all select.
select usename, nspname || '.' || relname as relation,
case relkind when 'r' then 'table' when 'v' then 'view' end as relation_type,
priv
from pg_class join pg_namespace on pg_namespace.oid = pg_class.relnamespace,
pg_user,
(select 'select' as priv,1 as privorder union all select 'insert',2 union all select 'update',3 union all select 'delete',4)
where relkind in ('r', 'v')
and has_table_privilege(pg_user.usesysid, pg_class.oid, priv)
and not (nspname ~ '^pg_' or nspname = 'information_schema')
order by 2, 1, 3, privorder;
Edit:
Also, I realized, that in our db Dataiku creates tables that can have CAPITAL letter in them, so, if table not exist error happens, you should use the lower() function