11

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?

4 Answers 4

9

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.

Sign up to request clarification or add additional context in comments.

1 Comment

You have to build dynamic SQL and use EXECUTE in a plpgsql function. Cast regproc back to text to build the query string. Be sure to safeguard against SQLi with quote_ident() - function names are not safe. Consider: CREATE FUNCTION ";delete from users;"() RETURNS int AS 'SELECT 1' LANGUAGE sql;
5

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!

1 Comment

is casting to regproc, in this case, only to validate the 'character varying' string as an existing function name ? otherwise just concatenating the function name as a string should work too i think.... ... ie this works : CREATE FUNCTION g ( _f_ varchar ) RETURNS VOID AS $$ BEGIN EXECUTE 'select * from ' || _f_ || '()' ; RETURN ; END $$ LANGUAGE PLPGSQL ;
2

I think you can't, but since there are no anonymous functions, passing function name should do.

3 Comments

Do you know how I call a function when I only have the function name in pl/pgsql or through the c api?
@Kungi, something like EXECUTE 'SELECT '||funcname||'()'….
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.