what is the difference - sql

I'm not even sure what this is called?
But I'm trying to learn what the difference is between writing a function like this is in plpgsql:
CREATE OR REPLACE FUNCTION foo() RETURNS TRIGGER AS $$
....
$$ LANGUAGE plpgsql;
vs
CREATE OR REPLACE FUNCTION foo() RETURNS TRIGGER AS $foo$
....
$foo$ LANGUAGE plpgsql;
is there a difference when using $$ vs $foo$? why would someone choose one over another?
perhaps I've just missed some documentation explaining the difference. If someone could enlighten me, I'd really appreciate it.

Whatever you type between the $ signs after the AS becomes the delimiter tag. You could write:
CREATE OR REPLACE FUNCTION foo() RETURNS TRIGGER AS $!!unicorns!!$
....
$!!unicorns!!$ LANGUAGE plpgsql;
The $...$ notation denotes a dollar-quoted string constant in PostgreSQL.

Related

Passing parameter to SQL Function in plpgsql

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.

Set PgSQL runtime-paramter from function parameter?

I created a pl/pgsql function with a varchar parameter. Within this function I tried to set a runtime paramter to the value of the function parameter.
CREATE FUNCTION test_function (param VARCHAR)
RETURNS VOID AS $tf$
BEGIN
SET choice.p = param;
RAISE NOTICE '%', current_setting('choice.p');
END; $tf$ LANGUAGE plpgsql;
However, the value printed is 'param'. param is treated like a string instead of a parameter name. Why is it like this, and how can I achieve what i try to do?
The PL/pgSQL variables is working only for SELECT and DML commands. These statements has a execution plan, that can be executed with parameters. PLpgSQL runtime is able to use plpgsql variables as parameters. The static SQL commands without a plan like DDL, SET, SHOW, .. cannot to use a plpgsql variables. There is not unique way how to do it - and there is risk of ambiguous semantic. You should to use dynamic SQL in this case.
DO $$
BEGIN
EXECUTE format('SET choice.p = %L', 'some text);
RAISE NOTICE '%', current_setting('choice.p');
END;
$$;
The main reason why your example doesn't work is simple - SQL SET command doesn't support a expressions, and then there is not a correct way, how to apply plpgsql variables there.

How to write in plpgsql code in plpythonu funtion (PostgreSQL)

I have a function written in plpythonu.
I want to add a 2 line code that will be written in plpgsql to this function.
This is my function:
CREATE OR REPLACE FUNCTION A(x integer)
RETURNS integer AS
$$
plpythonu code...
####################
add some comands in plpgsql
####################
plpythonu code...
$$
LANGUAGE plpythonu VOLATILE
How do I do that?
The plpgsql code is ready I just need to know how to make plpythonu accept it.
I know I can create a function for the plpgsql code and call it from python but it seems excessive.
Any ideas?
In the same way as for clear SQL code - execute (by using DO clause). You can not put plpgsql (as any other pl language) in function by another language.

VARIADIC parameter must be the last input parameter

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

Function as parameter to another function in Postgres

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