Reputation: 1536
Can I create a user defined function in Postgres either through the C-Language Function API or by using pl/pgsql
which accepts a callback function as parameter?
As far as I see there is no way to do this through the C-Language API since it only accepts sql datatypes and there is no datatype for function
. But maybe I'm missing something?
Upvotes: 10
Views: 5218
Reputation: 4824
--create an being parametered function.
CREATE OR REPLACE FUNCTION public.select1() RETURNS integer
LANGUAGE sql
IMMUTABLE
AS $function$ select 10;
$function$
--create an function with function as input parameter.
CREATE OR REPLACE FUNCTION public.func_func(fn_name text)
RETURNS SETOF parent_tree
LANGUAGE plpgsql
AS $function$
begin
RETURN QUERY EXECUTE
format('select * from parent_tree where parent_id = %s::regprocedure', fn_name);
end
$function$
--Call it.
select * from func_func('select1()');
Upvotes: 1
Reputation: 8920
Old question and already has an accepted answer. But it doesn't clearly explain how to do this. So I thought of adding a more clear answer.
Let's assume you pass the callback function's name to your main function as a varchar value.
CREATE OR REPLACE FUNCTION public.get_function_fields(fn_name character varying)
...
...
Now if you want to call this fn_name
function inside a query, you need to use EXECUTE
command, and properly cast your function name using regproc
as below.
EXECUTE 'create temp table if not exists temp_call as select * from ' || fn_name::regproc || '() limit 1';
Important part is this: ...|| fn_name::regproc || '()..
. As you can see, you have to append the parenthesis and cast the function name with ::regproc
.
Hope it will help someone!
Upvotes: 4
Reputation: 66243
Since each function / procedure must have an entry in pg_proc, you can use the primary key for identifying the procedure. This would also eliminate the problems with procedures having the same name but different number of parameters or different parameter types.
Shorthands for this are the types regproc
and regprocedure
with the associated casts for easier handling. Lookup the manual for these.
Identifying the function and passing it around is no problem:
select 'pg_database_size(oid)'::regprocedure; -- create "reference"
regprocedure
-----------------------
pg_database_size(oid)
Use regprocedure
as the parameter type.
The problem I did not yet figure out is how to actually call such a thing in a convenient way.
Upvotes: 9
Reputation: 143071
I think you can't, but since there are no anonymous functions, passing function name should do.
Upvotes: 2