PostgreSQL: How to recognize data type? - postgresql

How to recognize the data type of anyelement inside function?
CREATE OR REPLACE FUNCTION test1(par1 int,**par2 anyelement**)
RETURNS BOOL
AS $$
DECLARE rc bool := true;
BEGIN
-- ?
RETURN rc;
END;
$$
LANGUAGE plpgsql;

Use pg_typeof(any):
create or replace function test(par anyelement)
returns text language plpgsql as $$
begin
return pg_typeof(par)::text;
end $$;
select test(100::int), test('2012-12-12'::date);
test | test
---------+------
integer | date
(1 row)

Related

Select Statement using Stored Procedure

May I ask on how to call a method when the content of the stored procedure is about select statement? (Using postgreSQL)
CREATE OR REPLACE PROCEDURE select_table(table_name VARCHAR(255))
language plpgsql
as $$
BEGIN
EXECUTE('SELECT * FROM' || ' ' || quote_ident(table_name));
END $$;
CALL select_table('employee_table');
EDITED(USING FUNCTION)
CREATE OR REPLACE FUNCTION select_table(table_name VARCHAR(255))
language plpgsql
as $$
BEGIN
SELECT * FROM table_name
RETURN table_name;
END $$;
In PostgreSQL procedures doesn't execute any select statements and doesn't have return.
For returning data you can use functions. But functions also cannot return different structural data, examples:
CREATE OR REPLACE FUNCTION fr_test()
RETURNS TABLE(id integer, bookname character varying)
LANGUAGE plpgsql
AS $function$
begin
return QUERY
SELECT tb.id, tb.bookname from rbac.books tb;
end;
$function$
;
or
CREATE OR REPLACE FUNCTION fr_test()
RETURNS setof public.books
LANGUAGE plpgsql
AS $function$
begin
return QUERY
SELECT * from public.books;
end;
$function$
;
But for returning difference tables you can do it using procedures and using out refcursor, like as in Oracle. For example:
create or replace procedure pr_test(OUT r1 refcursor)
as $$
begin
open r1 for
select * from public.books;
end;
$$ language plpgsql;

How to insert function argument in a $$ $$ string in Postgresql?

So I have a function with an argument for example:
CREATE OR REPLACE FUCNTION example(arg int)
RETURNS int4
LANGUAGE plpgsql
AS $$
BEGIN
--function body
somequery := $q1$ SELECT field*arg FROM randomtable $q1$
EXECUTE somequery;
END
$$
Right now arg is just a string, how do I pass real arg from function argument ?
For your example, you don't need dynamic SQL to begin with, but if you really do, use a parameter placeholder:
CREATE OR REPLACE FUCNTION example(arg int)
RETURNS int4
LANGUAGE plpgsql
AS $$
declare
somequery text;
result int;
BEGIN
somequery := 'SELECT field*$1 FROM randomtable';
EXECUTE somequery
into result
using arg;
return result;
END;
$$
But without more information about the real problem you are trying to solve, the above can be simplified to:
CREATE OR REPLACE FUCNTION example(arg int)
RETURNS int4
LANGUAGE plpgsql
AS $$
declare
result int;
BEGIN
SELECT field * arg
into result
FROM randomtable;
return result;
END;
$$

Declare type of setof bigint in plpgsql function and assign into from select union

The following code currently works on PostgreSQL 13.3 (via Supabase.io). Both functions get_owned_base_ids and get_bases_editable have return type of setof bigint:
CREATE FUNCTION get_owned_base_ids()
returns setof bigint
stable
language sql
as $$
select id
from bases
where bases.owner_user_id = auth.uid();
$$;
-- CREATE FUNCTION get_bases_editable()
-- returns setof bigint
-- ... similar to get_owned_base_ids()
-- $$;
CREATE FUNCTION xyz (base_id bigint)
returns int
language plpgsql
as $$
BEGIN
IF base_id not in (select get_owned_base_ids() UNION select get_bases_editable()) THEN
-- note: actual function logic is simplified for this question
return 1;
END IF;
return 0;
END;
$$;
Is it possible to define a setof bigint and assign that from the select union? Something like this:
CREATE FUNCTION xyz (base_id bigint)
returns int
language plpgsql
as $$
DECLARE
allowed_base_ids bigint; -- needs to be a setof
BEGIN
select into allowed_base_ids get_owned_base_ids() UNION select get_bases_editable();
IF kv.base_id not in allowed_base_ids THEN
-- note: actual function logic is simplified for this question
return 1;
END IF;
return 0;
END;
$$;
It usually does not make much sense and use much memory of the result set is large, but you can use an array:
DECLARE
allowed_base_ids bigint[];
BEGIN
allowed_base_ids := array(SELECT * FROM get_owned_base_ids()
UNION ALL
SELECT * FROM get_bases_editable());
IF kv.base_id <> ALL (allowed_base_ids) THEN
...
END IF;
END;

How postgresql return a data set like the follows?

Just like the below function. I don't know how to return a set of inside parameter in postgresql?
create or replace function g_i(num int)
returns setof integer
as $$
declare
i int;
begin
while i < $1 loop
select i; -- How to write statements here?
end loop;
end;
$$ language plpgsql;
create or replace function g_i(num int)
returns setof integer
as $$
declare
i int;
begin
i := 0;
while i< $1 loop
i := i+1;
return query select i;
end loop;
end;
$$ language plpgsql;

How do you pop an array in postgres?

I'm wondering how to pop a value off from the top of an Array in postgresql using plpgsql?
CREATE FUNCTION pop_off(arr ANYARRAY) RETURNING ANYARRAY AS $$
BEGIN
-- return array with first element removed
END;
$$ LANGUAGE plpgsql;
Well, this wasn't as tough as I thought. Let's leverage the array_length method...
CREATE OR REPLACE FUNCTION pop_off(arr ANYARRAY) RETURNS ANYARRAY AS $$
BEGIN
RETURN (SELECT arr[2:array_length(arr,1)]);
END;
$$ LANGUAGE plpgsql;
There we go! Now let's test it...
LOG: statement: CREATE OR REPLACE FUNCTION pop_off(arr ANYARRAY) RETURNS ANYARRAY AS $$
BEGIN
RETURN (SELECT arr[2:array_length(arr,1)]);
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION
test_database=# SELECT pop_off('{1,2,3}'::int[]);
LOG: statement: SELECT pop_off('{1,2,3}'::int[]);
pop_off
---------
{2,3}
(1 row)