Suppose I create two functions like so:
create function test() returns int
as
$$
select 1::int
$$
language sql;
create function test(int default 5) returns int
as
$$
select $1
$$
language sql;
If I do this:
select * from test();
I get an error saying that function test() is not unique. Is there any way to call the first function above? Similarly, how can I call the second function above using the default value?
No - there's not a way and it is documented:
https://www.postgresql.org/docs/current/static/typeconv-func.html
Functions that have default values for parameters are considered to
match any call that omits zero or more of the defaultable parameter
positions. If more than one such function matches a call, the one
appearing earliest in the search path is used. If there are two or
more such functions in the same schema with identical parameter types
in the non-defaulted positions (which is possible if they have
different sets of defaultable parameters), the system will not be able
to determine which to prefer, and so an “ambiguous function call”
error will result if no better match to the call can be found.
Emphasis mine.
Related
I have written the below function and it works in Postgres 12.5:
CREATE OR REPLACE FUNCTION export_to_s3()
RETURNS TRIGGER
AS $export_to_s3$
BEGIN
PERFORM aws_s3.query_export_to_s3(
'select * from test.allowed_object_status',
aws_commons.create_s3_uri(
'test-db-dumps',
'allowed_object_status.csv',
'eu-west-2'),
options :='format csv, delimiter $$,$$'
);
RETURN NEW;
END;
$export_to_s3$ LANGUAGE plpgsql;
Now i would like to make test.allowed_object_status and allowed_object_status.csv parameters that i pass into export_to_s3().
I have tried a few things but failed so any help would be great.
A second part to my question and less important is it possible for a function to return nothing/void. I made this function a trigger but thats only because I cant figure out how to declare a function that dose not return anything after executing
Solution
This the solution i come up with thanks to the comments from #404 below.
CREATE OR REPLACE FUNCTION export_to_s3(query_cmd text, bucket_prefix text)
RETURNS VOID
AS $export_to_s3$
BEGIN
PERFORM
aws_s3.query_export_to_s3(
query_cmd,
aws_commons.create_s3_uri(
'test-db-dumps',
bucket_prefix,
'eu-west-2'),
options :='format csv, delimiter $$,$$'
);
END;
$export_to_s3$ LANGUAGE plpgsql;
I am sure there is a better way of doing it but very new to plpgsql
You can pass arguments to a trigger function, but that works different than you'd imagine.
You declare the trigger function without parameters.
In the CREATE TRIGGER statement, you specify string literals as function arguments.
These parameters can be accessed in the PL/pgSQL function body through TG_ARGV[], and the argument count is in TG_NARGS.
See the documentation for details.
I'm having a hard time understanding the below plsql function. what exactly does the function return and what exactly does the function do?
function getsysparm(a_name varchar2,
a_default varchar2 := null,
a_date sys_params.date_expires%type := null)
return varchar2;
That's not a function, it's just a function declaration, and from the looks of it, probably in a package spec. You need to look in the package body to see the actual code for the function.
Function accepts 3 parameters: one is mandatory (a_name), while another two are optional.
It returns a string (value whose datatype is VARCHAR2), for example "Abby" or "Stack Overflow" or "x".
What does it exactly do? Who knows ... you didn't post any code. See whether
select text
from user_source
where name = 'GETSYSPARM'
returns something you could have a look at.
When I define a function such as this one:
create or replace function test_func_a()
returns table(search_path name[], public_func_result text) as $$
select current_schemas('true'), trim(' does it work ');
$$ language sql stable security definer set search_path = pg_temp;
select test_func_a();
test_func_a
-------------------------------------------
("{pg_catalog,pg_temp_2}","does it work")
Why am I still able to use a function in the public schema such as trim or current_schemas for that matter? Shouldn't it only work if I explicitly use public.trim()?
Functions that are in schemas that I've created do not work in the same fashion. In this example I attempt to use a function in the util schema without setting it in the search_path:
create or replace function test_func_b()
returns table(search_path name[], public_func_result text) as $$
select current_schemas('true'), trim_whitespace(' does it work ');
$$ language sql stable security definer set search_path = pg_temp;
ERROR: function trim_whitespace(unknown) does not exist
LINE 3: select current_schemas('true'), trim_whitespace(' does it ...
^
HINT: No function matches the given name and argument types. You might need
to add explicit type casts.
Outside of functions, my search_path is set as this:
select current_schemas('true');
current_schemas
------------------------------------------------------------
{pg_temp_2,pg_catalog,public,util}
Look inside your public schema. Do you see TRIM? current_schemas? No, they're not there. Have a read of this https://www.postgresql.org/docs/current/static/ddl-schemas.html
On the public schema:
By default [...] tables (and other objects) are automatically put into
a schema named "public". Every new database contains such a schema.
[...] There is nothing special about the public schema except that it
exists by default. It can be dropped, too.
So how is it resolving current_schemas?
In addition to public and user-created schemas, each database contains
a pg_catalog schema, which contains the system tables and all the
built-in data types, functions, and operators. pg_catalog is always
effectively part of the search path. If it is not named explicitly in
the path then it is implicitly searched before searching the path's
schemas. This ensures that built-in names will always be findable.
However, you can explicitly place pg_catalog at the end of your search
path if you prefer to have user-defined names override built-in names.
Have a look inside pg_catalog (under Catalogs in PGAdmin), current_schemas is in the function list there.
And the built-in function TRIM is a keyword which PG recognises, see https://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
How to create two VARIADIC parameters. Look at my code and correct me.
CREATE OR REPLACE FUNCTION ip_source_test(text,text,date,date,VARIADIC int[],VARIADIC text[])
RETURNS TABLE (no_documents int, "Report By" text, "Report_By" text) AS
$$
BEGIN
IF 'Source Member' = $1 THEN
RETURN QUERY SELECT.....
ELSEIF 'company' = $1 THEN
RETURN QUERY SELECT.....
ELSE
RAISE NOTICE 'Not Worked';
END IF;
RETURN;
END;
$$ LANGUAGE plpgsql;
Error: VARIADIC parameter must be the last input parameter.
In SQL code im supposed to use 6 parameters. Please update me with sample code.
There can be only one VARIADIC per function, since variadic encompasses all the other arguments passed by the caller.
If you mean for the caller to use arrays, there's no point in using variadic anyway, the function signature could look like:
CREATE FUNCTION ip_source_test(text,text,date,date,int[], text[])
The error message tells you:
VARIADIC parameter must be the last input parameter.
It follows logically that a function can only take a single VARIADIC parameter. There can be other (non-VARIADIC) parameters before that one. The manual:
Effectively, all the actual arguments at or beyond the VARIADIC
position are gathered up into a one-dimensional array
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?
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.
I think you can't, but since there are no anonymous functions, passing function name should do.
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!
--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()');