PostgreSQL - Function that returns labels of any ENUM - postgresql

I am trying to write a "generic" function that will return labels of any enum (in any schema)...
But I am not having much luck because I am not sure what should argument type be...
The goal would be to be able to call function like this
SELECT common.get_enum_labels('public.rainbow_colors');
SELECT common.get_enum_labels('audit.user_actions');
This is what I have so
CREATE OR REPLACE FUNCTION common.get_enum_labels(enum_name regtype)
RETURNS SETOF text AS
$$
BEGIN
EXECUTE format('SELECT unnest(enum_range(NULL::%s))::text AS enum_labels ORDER BY 1', enum_name);
END;
$$
LANGUAGE plpgsql
STABLE
PARALLEL SAFE
;
Any tips would be appreciated

The argument type should be regtype, do not forget to return something from the function
CREATE OR REPLACE FUNCTION get_enum_labels(enum_name regtype)
RETURNS SETOF text AS
$$
BEGIN
RETURN QUERY
EXECUTE format('SELECT unnest(enum_range(NULL::%s))::text ORDER BY 1', enum_name);
END;
$$
LANGUAGE plpgsql

create or replace function get_enum_labels(enum_name regtype)
returns setof text language sql stable
as $$
select enumlabel::text
from pg_enum
where enumtypid = enum_name
order by enumsortorder
$$;

Related

splitting characters using function in PostgreSQL

I tried to write function like this in PostgreSQL but I'm getting error like
ERROR: syntax error at or near "elems"
LINE 22: RETURN elems;
I want get output like
input: we###ty;rer##2hjjj
output:
we###ty
rer##2hjjj
please help me to solve this error
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE 'plpgsql'
COST 100
VOLATILE SECURITY DEFINER PARALLEL UNSAFE
AS $BODY$
DECLARE
delimeter text;
elems text[];
var text;
arr_len int;
BEGIN
SELECT unnest(string_to_array(inputstr,delimeter))
INTO elems
RETURN elems;
END
$BODY$;
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE 'plpgsql'
COST 100
VOLATILE SECURITY DEFINER
AS $BODY$
DECLARE
elems text[];
BEGIN
SELECT string_to_array(inputstr,delimeter) INTO elems;
RETURN elems;
END;
$BODY$;
Now call this function like this
SELECT UNNEST(fn_split('1,2,3',',')) as retval
Above is the screenshot which includes function definition and in the first list the command to call this function
Here is the command that you need to execute in order to call this function in the PostgreSQL query window after the creation of the function.
Your function is defined to return an array, however unnest would turn the result of creating the array into rows of strings. There is also no need to duplicate the parameter definition as local variables in a DECLARE block. And as you don't seem to want to manipulate the created array somehow, there is no need to store it in a local variable.
It seems you just want:
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE plpgsql
immutable
AS $BODY$
BEGIN
return string_to_array(inputstr,delimeter);
END
$BODY$;
Or simpler as a SQL function:
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE sql
immutable
AS
$BODY$
select string_to_array(inputstr,delimeter);
$BODY$;
Note that the language name is an identifier and should not be enclosed in single quotes. This syntax is deprecated and support for it will be removed in a future Postgres version.
Edit:
It seems you don't actually want an array, but one row per element after splitting the input value. In that case the function should be declared as returns table() not returns text[]
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS table(element text)
LANGUAGE sql
immutable
AS
$BODY$
select unnest(string_to_array(inputstr,delimeter));
$BODY$;
Then use it like this:
select *
from fn_split('we###ty;rer##2hjjj', ';');
Since Postgres 14
select unnest(string_to_array(inputstr,delimeter));
can be simplified to
select string_to_table(inputstr,delimeter);

Postgresql return nested set of values in stored procedure

I'm currently doing a test in PostgreSQL using PGTAP.
In order to minimize redundancy in my code I placed duplicate code inside a
function. I have functions that both returns a SETOF TEXT.
CREATE FUNCTION _create_common_test(
this_argument varchar
) RETURNS SETOF TEXT AS $$
DECLARE
RETURN NEXT IS(this_argument, 'i_am_argument1', 'Checking Argument 1');
MORE RETURN NEXT STATEMENTS HERE....
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION test_create_common_test_1() RETURNS SETOF TEXT AS $$
BEGIN
RETURN NEXT _create_common_test('i_am_argument1');
END
$$ LANGUAGE plpgsql;
CREATE FUNCTION test_create_common_test_2() RETURNS SETOF TEXT AS $$
BEGIN
RETURN NEXT _create_common_test('i_am_argument2');
END
$$ LANGUAGE plpgsql;
test_create_common_test_1 and test_create_common_test_2 calls the same function _create_common_test() inside their function varying only in the value passed in the argument.
As for my question, Is it possible to return the returned value of _create_common_test() which is a SETOF TEXT in the functions test_create_common_test_1 and test_create_common_test_2?
I have tried using PERFORM _create_common_test('i_am_argument2'),
CREATE FUNCTION test_create_common_test_2() RETURNS SETOF TEXT AS $$
BEGIN
PERFORM _create_common_test('i_am_argument2');
END
$$ LANGUAGE plpgsql;
but it does not enumerate the results I had inside the _create_common_test().
As correctly answered by #a_horse_with_no_name in the comments:
return query select * from _create_common_test('i_am_argument2');

Postgres Stored procedure in select statement cannot get the datas

I am trying to get the data from the Database use function of select prison();.but i got error .Please advise me.
CREATE OR REPLACE FUNCTION prison() RETURNS refcursor AS $$
DECLARE
ref refcursor;
BEGIN
OPEN ref FOR SELECT round,ben_sc,ben_st FROM prison_issue;
RETURN ref;
END;
$$ LANGUAGE plpgsql;
and calling like this
select prison();
also i tried.but cannot executed the rows.
BEGIN;
SELECT prison();
-- Returns: <unnamed portal 2>
FETCH ALL IN "<unnamed portal 24>";
COMMIT;
There is no need for a PL/pgSQL function for this:
CREATE OR REPLACE FUNCTION prison()
RETURNS setof prison_issue
AS $$
SELECT * FROM prison_issue;
$$ LANGUAGE sql;
You also need to use:
select * from prison();
to retrieve the data, do not use select prison() (which only returns a single record, not multiple rows)
You didn't show us your definition of the table prison_issue if you don't want to return all columns you need something like this:
CREATE OR REPLACE FUNCTION prison()
RETURNS table (round integer, ben_sc text, ben_st text)
AS $$
SELECT SELECT round,ben_sc,ben_st FROM prison_issue;
$$ LANGUAGE sql;
You will need to adjust the part table (round integer, ben_sc text, ben_st text) to match the data type of the columns you select.
Below is an example code.I have assumed the data types.Replace with the real ones.
CREATE OR REPLACE FUNCTION prison() RETURNS TABLE(round numeric,ben_sc character varying,ben_st character varying) AS $$
BEGIN
RETURN QUERY SELECT p.round,p.ben_sc,p.ben_st FROM prison_issue p;
END;
$$ LANGUAGE plpgsql;

Return ResultSet in pgsql function

I have the function below...
CREATE OR REPLACE FUNCTION class_listing(var_sem integer, var_sy character) RETURNS SETOF RECORD AS
DECLARE
current_offering record;
BEGIN
SELECT subcode, offerno INTO current_offering FROM offering WHERE SY=var_sem AND SEM=var_sy;
END;
How to return current_offering as resultset?
You can use a SQL or PLpgSQL functions. Using anonymous records as returning type is not practical (mainly it is not friendly, when you write queries). Use RETURNS TABLE or OUT parameters instead.
CREATE OR REPLACE FUNCTION class_listing(var_sem integer, var_sy varchar)
RETURNS TABLE (subcode varchar, offerno int) AS $$
BEGIN
RETURN QUERY SELECT o.subcode, o.offerno
FROM offering
WHERE SY=var_sem AND SEM=var_sy;
END;
$$ LANGUAGE plpgsql;
or SQL language
CREATE OR REPLACE FUNCTION class_listing(var_sem integer, var_sy varchar)
RETURNS TABLE (subcode varchar, offerno int) AS $$
SELECT o.subcode, o.offerno
FROM offering
WHERE SY=$1 AND SEM=$2;
$$ LANGUAGE sql;
Attentions - query based functions works (with small exception) as optimizer barrier. So be careful when you use it in complex queries.
For completeness - your example can be written as:
CREATE OR REPLACE FUNCTION class_listing(var_sem integer, var_sy varchar)
RETURNS SETOF RECORD AS $$
DECLARE current_offering record;
BEGIN
FOR current_offering IN
SELECT o.subcode, o.offerno
FROM offering
WHERE SY=var_sem AND SEM=var_sy;
LOOP
RETURN NEXT current_offering;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
But this form is deprecated now

Hstore as argument type in postgresql

Is it possible to declare hstore as an argument type while creating a function in postgresql?
CREATE FUNCTION samplehstore(uname hstore)
RETURNS SETOF void AS
DECLARE
BEGIN
RAISE NOTICE 'uname : %', uname ;
END;
LANGUAGE plpgsql
Yes. Just tested:
create or replace function samplehstore(_h hstore)
returns text as
$$
begin
return _h->'a';
end
$$
language plpgsql;
select samplehstore('a=>1'::hstore)
>>> 1
Your example is ideally right, but you just forgot to surround the function body inside a string (the hstore part is ok). I recommend doing that this way (see $$ added):
CREATE FUNCTION samplehstore(uname hstore)
RETURNS SETOF void AS $$
DECLARE
BEGIN
RAISE NOTICE 'uname : %', uname ;
END;
$$
LANGUAGE plpgsql;
The PostgreSQL's functions are basically an string, and dollar-quoting is an syntax similar to single quotes, try this:
SELECT $$my string$$, $id$my string$id$, 'my string';
The three are equivalents. See the docs for more information.