postgres local schema qualifier - sql

i am using postgres schemas to group views and functions and to keep multiple versions of them in a database (sometimes needed for backwards compatibility) since there are multiple versions of the same function in different schemas i cannot simply reference it by name but need to write the full qualified name "schema.funcname" to access it.
when referencing functions within schemaA from another function in schemaA i always have to write schemaA.funcname. this bugs me when i rename the schema later - is there a qualifier indicating that the function in the same schema schould be used? maybe like the "this" qualifier in java?
hope it can be understood what i am meaning
thx

You can use set schema to change search path for current session:
create schema test1;
create schema test2;
create function test1.f() returns int as $body$ begin return 1; end; $body$ language plpgsql;
create function test2.f() returns int as $body$ begin return 2; end; $body$ language plpgsql;
set schema 'test1';
select f();
set schema 'test2';
select f();
You can also add search_path to function definition:
create or replace function test1.x() returns int as $body$ begin return 1; end; $body$ language plpgsql;
create or replace function test1.f() returns int as $body$ begin return x(); end; $body$ language plpgsql set search_path = 'test1';
create or replace function test2.x() returns int as $body$ begin return 2; end; $body$ language plpgsql;
create or replace function test2.f() returns int as $body$ begin return x(); end; $body$ language plpgsql set search_path = 'test2';
select test1.f();
select test2.f();

Related

Using the parameters given in stored procedure in a trigger function

I would like to know if it is possible to use the parameter "delivery_date_ which is given to the stored procedure "delivery" inside trigger function "insert_error".
CREATE OR REPLACE PROCEDURE delivery (delivery_date date)
LANGUAGE 'plpgsql'
AS
$BODY$
DECLARE
BEGIN
END;
$BODY$
CREATE OR REPLACE FUNCTION insert_error() RETURNS TRIGGER
LANGUAGE 'plpgsql'
AS
$BODY$
BEGIN
--being able to use the parameter "delivery_date" here--
END;
$BODY$
DROP TRIGGER check_insert ON transactions;
CREATE TRIGGER check_insert
BEFORE INSERT ON transactions
FOR EACH ROW
EXECUTE PROCEDURE insert_error();
CREATE OR REPLACE FUNCTION insert_error() RETURNS TRIGGER
LANGUAGE 'plpgsql'
AS
$BODY$
begin
------ you can use any of these code:
CALL delivery(now()::date); -- call with current datetime
CALL delivery(new."date"); -- call with from inserted date field
CALL delivery(current_timestamp::date); -- and etc.
return new;
END;
$BODY$

Return a table that already exist in postgresql function

I have a bunch of functions that return the same table schema, so I have to repeat the same table schema over and over between those functions' declarations, to make this example simple let's say we have two functions that return the same table schema:
Table: people
CREATE TABLE people(full_name TEXT, age integer);
Functions:
CREATE OR REPLACE FUNCTION get_people_by_age(_age integer)
RETURNS TABLE(full_name TEXT, age integer)
LANGUAGE PLPGSQL
AS
$$
BEGIN
RETURN QUERY SELECT * FROM people WHERE people.age = $1;
END
$$
CREATE OR REPLACE FUNCTION get_people_by_name(_full_name text)
RETURNS TABLE(full_name TEXT, age integer)
LANGUAGE PLPGSQL
AS
$$
BEGIN
RETURN QUERY SELECT * FROM people WHERE people.full_name = $1;
END
$$
Is there a way to refer to the existing table within the function declarations? I imagine something like this:
CREATE OR REPLACE FUNCTION get_people_by_age(_age integer)
RETURNS TABLE(people)
LANGUAGE PLPGSQL
AS
$$
BEGIN
RETURN QUERY SELECT * FROM people WHERE people.age = $1;
END
$$
CREATE OR REPLACE FUNCTION get_people_by_name(_full_name text)
RETURNS TABLE(people)
LANGUAGE PLPGSQL
AS
$$
BEGIN
RETURN QUERY SELECT * FROM people WHERE people.full_name = $1;
END
$$
Where instead of declaring the same schema in every function I refer to a table that already exists, is it possible?
Use returns setof
CREATE OR REPLACE FUNCTION get_people_by_name(_full_name text)
RETURNS setof people
LANGUAGE PLPGSQL
AS
$$
BEGIN
RETURN QUERY SELECT * FROM people WHERE people.full_name = _full_name;
END
$$;
Or a bit simpler as a SQL function:
CREATE OR REPLACE FUNCTION get_people_by_name(_full_name text)
RETURNS setof people
LANGUAGE sql
AS
$$
SELECT * FROM people WHERE people.full_name = _full_name;
$$;

Return id of the deleted entry PostgreSQL

I have a function that delete an entry from my table. Also I need to return the id of the deleted entry.
CREATE OR REPLACE FUNCTION mydb.remove_item(item_id_param text)
RETURNS TABLE(id integer)
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RETURN QUERY
DELETE FROM mydb.items_table
WHERE item_id = item_id_param;
END;
$BODY$
When I execute the above function, it shows error as;
ERROR: cannot open DELETE query as cursor
CONTEXT: PL/pgSQL function mydb.remove_item(text) line 6 at RETURN QUERY
What is wrong in my function?
You need to use the RETURNING clause in order to return the IDs of the deleted rows:
CREATE OR REPLACE FUNCTION mydb.remove_item(item_id_param int)
RETURNS TABLE(id integer)
LANGUAGE plpgsql
AS $BODY$
BEGIN
RETURN QUERY
DELETE FROM mydb.items_table
WHERE item_id = item_id_param
RETURNING items_table.id; --<< this
END;
$BODY$
;
You do not need plpgsql for this. A simple scalar SQL function will do.
create or replace function mydb.remove_item(item_id_param int) returns int as
$BODY$
DELETE FROM mydb.items_table
WHERE item_id = item_id_param
RETURNING items_table.id;
$BODY$
language sql;

Sql create a view X_myview where X is given into a function(X text) which creates the view

Trying to create a function that given the name of a table will create a function with the table name concatenated to _myView
eg if the name of the table is students the function will create a view called students_myView
Here's what I have so far.
create or replace function skyline_naive(tableName text)
as $$
declare
name text;
begin
name:= $1;
create or replace view name_myView as select * from name;
end
$$ language plpgsql;
A dynamic command in PLPgSQL must be executed as a string with EXECUTE statement.
To make it work, you should write it like this:
create or replace function skyline_naive(tableName text)
returns void as $$
begin
execute format('create or replace view %1$s_myView as select * from %1$s;', tableName)
return;
end;
$$ language
plpgsql;

plpgsql function. How to compare value to set of values?

I have a trigger function.
I wish to check if an status is one of (5,6,4,7)
CREATE OR REPLACE FUNCTION a()
RETURNS trigger AS
$BODY$
begin
if old.status = (5,6,4,7) then
do something.
end if;
return old;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
how do I change it to proper syntax?
Use IN operator:
...
if old.status IN (5,6,4,7) then
do something.
end if;
...
This is reference of this link.
It only work with postgresql 9.x
CREATE OR REPLACE FUNCTION a()
RETURNS trigger AS
$BODY$
begin
if old.status = ANY (VALUES (5),(6),(4),(7))) then
do something.
end if;
return old;
end;
$BODY$
LANGUAGE plpgsql VOLATILE