How to print functions and triggers sourcecode in postgresql? please let me know if any one know the query to display the function, triggers source code.
\df+ in psql gives you the sourcecode.
For function:
you can query the pg_proc view , just as the following
select proname,prosrc from pg_proc where proname= your_function_name;
Another way is that just execute the commont \df and \ef which can list the functions.
skytf=> \df
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+----------------------+------------------+------------------------------------------------+--------
public | pg_buffercache_pages | SETOF record | | normal
skytf=> \ef pg_buffercache_pages
It will show the source code of the function.
For triggers:
I dont't know if there is a direct way to get the source code. Just know the following way, may be it will help you!
step 1 : Get the table oid of the trigger:
skytf=> select tgrelid from pg_trigger where tgname='insert_tbl_tmp_trigger';
tgrelid
---------
26599
(1 row)
step 2: Get the table name of the above oid !
skytf=> select oid,relname from pg_class where oid=26599;
oid | relname
-------+-----------------------------
26599 | tbl_tmp
(1 row)
step 3: list the table information
skytf=> \d tbl_tmp
It will show you the details of the trigger of the table . Usually a trigger uses a function. So you can get the source code of the trigger function just as the above that I pointed out !
Here are few examples from PostgreSQL-9.5
Display list:
Functions: \df+
Triggers : \dy+
Display Definition:
postgres=# \sf
function name is required
postgres=# \sf pg_reload_conf()
CREATE OR REPLACE FUNCTION pg_catalog.pg_reload_conf()
RETURNS boolean
LANGUAGE internal
STRICT
AS $function$pg_reload_conf$function$
postgres=# \sf pg_encoding_to_char
CREATE OR REPLACE FUNCTION pg_catalog.pg_encoding_to_char(integer)
RETURNS name
LANGUAGE internal
STABLE STRICT
AS $function$PG_encoding_to_char$function$
There are many possibilities. Simplest way is to just use pgAdmin and get this from SQL window. However if you want to get this programmatically then examinate pg_proc and pg_trigger system catalogs or routines and triggers views from information schema (that's SQL standard way, but it might not cover all features especially PostgreSQL-specific). For example:
SELECT
routine_definition
FROM
information_schema.routines
WHERE
specific_schema LIKE 'public'
AND routine_name LIKE 'functionName';
Slightly more than just displaying the function, how about getting the edit in-place facility as well.
\ef <function_name> is very handy. It will open the source code of the function in editable format.
You will not only be able to view it, you can edit and execute it as well.
Just \ef without function_name will open editable CREATE FUNCTION template.
For further reference -> https://www.postgresql.org/docs/9.6/static/app-psql.html
\sf function_name in psql yields editable source code of a single function.
From https://www.postgresql.org/docs/9.6/static/app-psql.html:
\sf[+] function_description
This command fetches and shows the definition of the named function, in the form of a CREATE OR REPLACE FUNCTION command.
If + is appended to the command name, then the output lines are numbered, with the first line of the function body being line 1.
additionally to #franc's answer you can use this from sql interface:
select
prosrc
from pg_trigger, pg_proc
where
pg_proc.oid=pg_trigger.tgfoid
and pg_trigger.tgname like '<name>'
(taken from here: http://www.postgresql.org/message-id/Pine.BSF.4.10.10009140858080.28013-100000#megazone23.bigpanda.com)
Since Version: psql (9.6.17, server 11.6)
I have tried all of above answer but For me
postgres=> \sf jsonb_extract_path_text
CREATE OR REPLACE FUNCTION pg_catalog.jsonb_extract_path_text(from_json jsonb, VARIADIC path_elems text[])
RETURNS text
LANGUAGE internal
IMMUTABLE PARALLEL SAFE STRICT
AS $function$jsonb_extract_path_text$function$
postgres=> \df+
ERROR: column p.proisagg does not exist
LINE 6: WHEN p.proisagg THEN 'agg'
^
HINT: Perhaps you meant to reference the column "p.prolang".
df seems not working for me.
To list all functions:
select n.nspname as function_schema,
p.proname as function_name,
l.lanname as function_language,
case when l.lanname = 'internal' then p.prosrc
else pg_get_functiondef(p.oid)
end as definition,
pg_get_function_arguments(p.oid) as function_arguments,
t.typname as return_type
from pg_proc p
left join pg_namespace n on p.pronamespace = n.oid
left join pg_language l on p.prolang = l.oid
left join pg_type t on t.oid = p.prorettype
where n.nspname not in ('pg_catalog', 'information_schema')
order by function_schema,
function_name;
Now if you want to search a specific word or text in all function is something like that, make sure you replace your text in the function:
with tbl as (
select n.nspname as function_schema,
p.proname as function_name,
l.lanname as function_language,
case when l.lanname = 'internal' then p.prosrc
else pg_get_functiondef(p.oid)
end as definition,
pg_get_function_arguments(p.oid) as function_arguments,
t.typname as return_type
from pg_proc p
left join pg_namespace n on p.pronamespace = n.oid
left join pg_language l on p.prolang = l.oid
left join pg_type t on t.oid = p.prorettype
where n.nspname not in ('pg_catalog', 'information_schema')
)
select *
from tbl
where definition ilike '%word or text you want to search%'
order by function_schema,
function_name;
Related
I would like to get Tablename from regclass in PostgreSQL. I have found a work around but I am not feeling so happy with it:
SELECT split_part('datastore.inline'::regclass::TEXT, '.', 2);
Is there a dedicated function to extract table name from regclass in Postgre?
You can query pg_class:
select relname
from pg_class
where oid = 'datastore.inline'::regclass;
There is no built-in function but you can create your own one:
create or replace function get_relname(regclass)
returns name language sql as $$
select relname
from pg_class
where oid = $1
$$;
select get_relname('datastore.inline'::regclass);
In order to restore my data from pgdump I need to delete custom functions from database.
This function identify them well:
SELECT pp.proname
FROM pg_proc pp
INNER JOIN pg_namespace pn on (pp.pronamespace = pn.oid)
INNER JOIN pg_language pl on (pp.prolang = pl.oid)
WHERE pl.lanname NOT IN ('c','internal')
AND pn.nspname NOT LIKE 'pg_%'
AND pn.nspname <> 'information_schema';
So, immediately after I hear for dynamic SQL and ensure that I can use it from .NET I try to apply it for that purpose.
do
$$
declare
func_rec record;
begin
for func_rec in (SELECT pp.proname as funcname
FROM pg_proc pp
INNER JOIN pg_namespace pn on (pp.pronamespace = pn.oid)
INNER JOIN pg_language pl on (pp.prolang = pl.oid)
WHERE pl.lanname NOT IN ('c','internal')
AND pn.nspname NOT LIKE 'pg_%'
AND pn.nspname <> 'information_schema')
loop
execute 'drop function '||func_rec.funcname||' cascade';
end loop;
end;
$$
In meantime I found that for drop a function I have to supply it's parameters to DROP command.
Here is one example subquery on how those parameters can be retrieved:
(SELECT typname FROM pg_type WHERE oid = funcrow.proargtypes[i])
Now remain a problem that I don't know how to put those in functional code which will add needed parameters to func_rec.funcname in order to delete such functions.
So, please help to get query for deleting custom functions from all functions.
Because functions can be overloaded in Postgres, you need to include the function's signature in the drop.
Suppose you have these functions:
get_answer(p1 integer);
get_answer(p1 integer, p2 integer);
then Postgres wouldn't know which one to drop when using drop function get_answer;.
Luckily Postgres has a function to format the arguments so that they can be used for that purpose: pg_get_function_identity_arguments.
So you need to change your select to:
SELECT pp.proname||'('||pg_get_function_identity_arguments(pp.oid)||')' as funcname
FROM pg_proc pp
INNER JOIN pg_namespace pn on (pp.pronamespace = pn.oid)
INNER JOIN pg_language pl on (pp.prolang = pl.oid)
WHERE pl.lanname NOT IN ('c','internal')
AND pn.nspname NOT LIKE 'pg_%'
AND pn.nspname <> 'information_schema';
I have few tables in my database. They all have the same columns (id, name) but differ in the table name. Those tables have names that start with letter 'h'.
Not a very interesting schema design but I have to follow it.
I need to search for id in all those tables.
I tried something similar to:
select id from (select table_name
FROM information_schema.tables
where table_name like 'h%') as t;
I got error:
ERROR: column "id" does not exist.
I understand the error now but I still do not know how to do the query?
You need dynamic SQL to do that since you cannot use values as identifiers in plain SQL. Write a PL/pgSQL function with EXECUTE:
CREATE FUNCTION f_all_tables()
RETURNS TABLE (id int) AS
$func$
DECLARE
_tbl regclass;
BEGIN
FOR _tbl IN
SELECT c.oid::regclass
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND c.relname LIKE 'h%'
AND n.nspname = 'public' -- your schema name here
LOOP
RETURN QUERY EXECUTE '
SELECT id FROM ' || _tbl;
END LOOP;
END
$func$ LANGUAGE plpgsql;
I am using a variable of the object identifier type regclass to prevent SQL injection effectively. More about that in this related answer:
Table name as a PostgreSQL function parameter
I want to get the SQL to drop a function in PostgreSQL. I write DROP FUNCTION and a get function name from pg_proc. That is not problem. However if I leave blank parameters it will not drop the function.
I checked the manual and there is written then I have to identify the function with its parameters to drop it, eg DROP FUNCTION some_func(text,integer) not just DROP FUNCTION some_func.
Where can I find the parameters? In the function's row on in the pg_proc table there is no parameters. So how can I get the SQL to drop the function?
Postgres has a dedicated function for that purpose. Introduced with Postgres 8.4. The manual:
pg_get_function_identity_arguments(func_oid) ... get argument list to identify a function (without default values) ...
pg_get_function_identity_arguments returns the argument list
necessary to identify a function, in the form it would need to appear
in within ALTER FUNCTION, for instance. This form omits default values.
Using that (and format(), introduced with Postgres 9.1), the following query generates DDL statements to drop functions matching your search terms:
SELECT format('DROP %s %I.%I(%s);'
, CASE WHEN p.proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
, n.nspname
, p.proname
, pg_catalog.pg_get_function_identity_arguments(p.oid)
) AS stmt
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname = 'dblink' -- function name
-- AND n.nspname = 'public' -- schema name (optional)
-- AND pg_catalog.pg_function_is_visible(p.oid) -- function visible to user
ORDER BY 1;
The system catalog pg_proc changed in Postgres 11. proisagg was replaced by prokind, true stored procedures were added. You need to adapt. See:
How to drop all of my functions in PostgreSQL?
Returns:
stmt
---------------------------------------------------
DROP FUNCTION public.dblink(text);
DROP FUNCTION public.dblink(text, boolean);
DROP FUNCTION public.dblink(text, text);
DROP FUNCTION public.dblink(text, text, boolean);
Found four matches in the example because dblink uses overloaded functions.
Run DROP statements selectively!
Alternatively, you can use the convenient cast to the object identifier type regprocedure which returns a complete function signature including argument types:
-- SET LOCAL search_path = ''; -- optional, to get all names schema-qualified
SELECT format('DROP %s %s;'
, CASE WHEN proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
, oid::regprocedure
) AS stmt
FROM pg_catalog.pg_proc
WHERE proname = 'dblink' -- function name
ORDER BY 1;
In Postgres 10, you can delete a function without knowing the list of parameters, as long as it is unique in its schema.
drop function if exists some_func;
See the docs.
Of course, if you have overloaded the function (or are trying to delete over multiple schemas), you will still need the above answers.
use pgadminIII and direct access to function list and right click it then select delete
If you are working on an old previous version of postgres, for which pg_get_function_identity_arguments(func_oid) doesn't exist, I create my own function get the parameters from the function, you only need to pass the oid for the function, you need to deploy the function below to your postgres db.
CREATE OR REPLACE FUNCTION public.getFunctionParameter(functionOid oid)
RETURNS text AS
$BODY$
declare
t_paras text;
paras oid[];
res text :='(';
begin
select proargtypes into t_paras from pg_proc where oid=functionOid;
if t_paras is null or t_paras='' then
return '()';
else
paras:=string_to_array(t_paras,' ');
for i in array_lower(paras,1) .. array_upper(paras,1)
loop
raise notice 'para is %',paras[i];
select format_type(paras[i]::oid,NULL) into t_paras;
res:=res||t_paras||',';
end loop;
res:=substring(res from 1 for char_length(res)-1);
res:=res||')';
return res;
end if;
end
$BODY$
LANGUAGE plpgsql ;
The function below will list the function name and parameters, change the schema name if you want to get function under some other schema, I am using public for example
SELECT n.nspname||'.'||p.proname||public.getFunctionParameter(p.oid)
FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname='public'
You will the result like below
1 "public.getfunctionparameter(integer,text)"
2 "public.getfunctionparameter(oid)"
I have seen that it is possible to convert all tables to case insensitive names using the following commands in psql:
\o /tmp/go_to_lower
select 'ALTER TABLE '||'"'||tablename||'"'||' RENAME TO ' ||
lower(tablename)||';' from pg_tables where schemaname = 'public';
psql -U username database < /tmp/go_to_lower
I have been unable to unearth a command to convert all columns to case insensitive in the same way. How can this be achieved?
EDIT: Apparently the above code only converts table names to lower case. I am aware that this code ALTER TABLE "YourTableName" RENAME TO YourTableName; will convert to case insensitive for a table name. Is there a way to do a similar function on mass for column names?
Along the same lines as the original, then, you should be able to do the following. This renames all columns that are not already in lower case, by extracting them from the information_schema, generating SQL for the changes, storing it to a file then executing the SQL again.
\t on
select 'ALTER TABLE '||'"'||table_name||'"'||' RENAME COLUMN '||'"'||column_name||'"'||' TO ' || lower(column_name)||';'
from information_schema.columns
where table_schema = 'public' and lower(column_name) != column_name
\g /tmp/go_to_lower
\i /tmp/go_to_lower
By default, all you identifiers are case insensitive, and internally PostgreSQL stores them in lowercase. In case you need to have:
case sensitive
non-ASCII characters
special characters
within your identifiers, you should use double quotes (") around your identifiers.
Please, check this bit of the PostgreSQL documentation.
EDIT: After your clarification, you can use:
SELECT 'ALTER TABLE '||quote_ident(t.relname)||' RENAME TO '||t.relname||';'
FROM pg_class t, pg_namespace s
WHERE s.oid = t.relnamespace AND s.nspname = 'public'
AND t.relkind='r' AND t.relname != lower(t.relname)
ORDER BY 1;
and for columns:
SELECT 'ALTER TABLE '||quote_ident(t.relname)||
' RENAME COLUMN '||quote_ident(a.attname)||
' TO '||a.attname||';'
FROM pg_class t, pg_namespace s, pg_attribute a
WHERE s.oid = t.relnamespace AND s.nspname = 'public'
AND t.relkind='r'
AND a.attrelid = t.oid AND NOT a.attisdropped AND a.attnum > 0
AND a.attname != lower(a.attname)
ORDER BY 1;
Then copy-paste the output into your client.
If you're using psql, you can use \t to enable rows-only mode, \o <full_file_path> to save output into the temporary file and, finally, \i <full_file_path> to execute actual statements.
I created a SQL query on Database Administrators that does just this.
Converts all identifiers to lower case
Converts spaces ' ' to '_'
Does this for all schema, table, and column names
For more information see,
How do I adopt the PostgreSQL naming convention in legacy database?
do language plpgsql $$
declare
r record;
begin
for r in
select relname, attname
from pg_attribute a
inner join pg_class c on a.attrelid = c.oid
inner join pg_namespace n on c.relnamespace = n.oid
where
n.nspname = 'public'
and
attname != lower(attname)
and
not attisdropped
loop
execute format('
alter table %1$I rename column %2$I to %3$s
', r.relname, r.attname, lower(r.attname));
end loop;
end;
$$;
Issue a begin; before trying this. Check if it is correct. Only then issue a commit;. If you are using a namespace then substitute it in the where clause.
Let me add a step by step guide using PgAdmin for beginners like myself and those who are not used to command line tools like psql:
Execute the following query in PgAdmin:
SELECT 'ALTER TABLE ' || quote_ident(c.table_schema) || '.'
|| quote_ident(c.table_name) || ' RENAME "' || c.column_name || '" TO ' || quote_ident(lower(c.column_name)) || ';' As ddlsql
FROM information_schema.columns As c
WHERE c.table_schema NOT IN('information_schema', 'pg_catalog')
AND c.column_name <> lower(c.column_name)
ORDER BY c.table_schema, c.table_name, c.column_name;
*Source: https://www.postgresonline.com/article_pfriendly/141.html. Note that you do not need to change anything here.
Now export the result to a textfile.
Open the .csv file with Excel, Notepad or any texteditor of your choice. Copy all lines except the first one ("ddlsql") and past them into a new query in PgAdmin. Make sure to remove doubled text quotations. Run it and done.