Removing else-if-elseif.. in postgresql function - postgresql

I would like to know if and there is some way to get rid code like this:
CREATE FUNCTION parent_function (json json, OUT response_status integer, OUT response json) RETURNS record
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
if <condition> then
<function_call1(json,response_status,response)>;
return;
elsif <condition> then
<function_call2(json,response_status,response)>;
return;
elsif <condition> then
<function_call3(json,response_status,response)>;
return;
end if;
END;
$$
I would like to move these conditions into separate functions where I would like based on what the function returns(there are some output parameters I need) terminate parent function without throwing exceptions and catch them in parent function?
What I would like to achive code like this:
CREATE FUNCTION parent_function (json json, OUT response_status integer, OUT response json) RETURNS record
LANGUAGE plpgsql
AS $$
DECLARE
BEGIN
<check_function1(json,response_status,response)>;
<check_function2(json,response_status,response)>;
<check_function3(json,response_status,response)>;
END;
$$
After calling message and output parameters set from function terminate further processing. Is it somehow posible?
Thanks,
Lukas

you want something like this example?
CREATE OR REPLACE FUNCTION aa_test_check1( IN test_value integer)
RETURNS TABLE( problem boolean , problemmessage text ) AS
$BODY$
begin
problem := false;
if $1 <10 then
problem := true;
problemmessage := 'integer is smaller than 10';
end if;
return next;
end;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
CREATE OR REPLACE FUNCTION aa_test_check2( IN test_value integer)
RETURNS TABLE( problem boolean , problemmessage text ) AS
$BODY$
begin
problem := false;
if $1 >20 then
problem := true;
problemmessage := 'integer is greater than 20';
end if;
return next;
end;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
CREATE OR REPLACE FUNCTION aa_test_check3( IN test_value integer)
RETURNS TABLE( problem boolean , problemmessage text ) AS
$BODY$
begin
problem := false;
if $1 =10 then
problem := true;
problemmessage := 'something is wrong, it cant be 10';
end if;
return next;
end;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
CREATE OR REPLACE FUNCTION aa_test_main( IN test_value integer)
RETURNS TABLE( status_id integer , problemmessage text ) AS
$BODY$
declare
temp_problem boolean;
temp_problemmessage text;
begin
status_id := 0;
problemmessage := 'no problem, none at all';
select * from aa_test_check1($1)
into temp_problem, temp_problemmessage;
if temp_problem then
status_id := 1;
problemmessage := temp_problemmessage;
return next;
return;
end if;
select * from aa_test_check2($1)
into temp_problem, temp_problemmessage;
if temp_problem then
status_id := 2;
problemmessage := temp_problemmessage;
return next;
return;
end if;
select * from aa_test_check3($1)
into temp_problem, temp_problemmessage;
if temp_problem then
status_id := 3;
problemmessage := temp_problemmessage;
return next;
return;
end if;
return next;
end;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100
ROWS 100;
select * from aa_test_main(10)

Related

postgresql plpgsql: not able to iterate over a array of varchar[] type

i am trying to check if a element is present in an array using plpgsql.
and i am receiving "array subscript must have integer" error while executing the function.
select test('IND') should return true and select test('ING') should return false
Below is the code
create or replace function test(country varchar)
returns varchar
language plpgsql
AS $function$
declare
results varchar;
countryarr varchar[3];
i varchar[];
begin
countryarr := array['IND','USA','MEX'];
foreach i slice 1 in array countryarr
loop
if countryarr[i]=country
then results := 'TRUE';
else
results := 'FALSE';
end if;
end loop;
return results;
end;
$function$
;
Your i is defined as a varchar[] in your code. It cannot be used as an integer.
You want something like this:
create or replace function test(country varchar)
returns varchar
language plpgsql
AS $function$
declare
countryarr varchar[3];
i text;
begin
countryarr := array['IND','USA','MEX'];
foreach i in array countryarr
loop
if i = country
then return 'TRUE';
end if;
end loop;
return 'FALSE';
end;
$function$
;
A better solution for what you are trying to achieve is:
create or replace function test(country varchar)
returns varchar
language sql
AS $function$
select case
when country = any(array['IND', 'USA', 'MEX']) then 'TRUE'
else 'FALSE'
end;
$function$;
Let your function return a boolean. Then it reduces to a single SQL statement.
create or replace function is_valid_country(country_in varchar)
returns boolean
language sql
immutable strict
AS $$
select country_in = any(array['IND', 'USA', 'MEX']) ;
$$;
with test(country) as
( values ('IND'), ('USA'), ('MEX'), ('CAN'),('UK') )
select country, is_valid_country(country) is_valid
from test;
This can be used in any subsequent sql statement. And the optimizer can in-line it.

How get row count from return type in postgres?

I have a function that return a table (my customer type).
How I can get row count of return object?
CREATE TYPE observer_holder AS ("CustomerName" TEXT,"CustomerFamily" TEXT)
CREATE OR REPLACE FUNCTION getItem(i_callStateText TEXT, i_maxText TEXT)
RETURNS SETOF observer_holder
LANGUAGE plpgsql
AS $$
declare
sendOffset INTEGER;
fetchRecord RECORD;
result observer_holder;
runQuery2 BOOLEAN := lower(trim(both ' ' from i_callStateText)) ='notnull' AND (position('::tsrange' in i_maxText) < 1);
query1 TEXT := '...';
query2 TEXT := '...';
BEGIN
FOR fetchRecord IN EXECUTE CASE WHEN runQuery2 THEN query2 ELSE query1 END LOOP
result."CustomerFamily" := customerRecord.family;
result."CustomerName" := customerRecord.name;
.
.
.
RETURN next result;
END LOOP;
-- my question , how get result count?
RAISE notice 'row count: %', length(result::observer_holder); >> Exception
RETURN;
END; $$;
I need result row count. Please help me.

PostgreSQL 9.3: isnumeric() in a condition

I need to check whether the given text is numeric or not from the
function.
Creating function for isnumeric():
CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Function from which I am calling the isnumeric() function:
create or replace function tm(var text)
returns varchar as
$$
begin
if (select isnumeric(var))=t::BOOLEAN then
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
end;
$$
language plpgsql;
Calling functon:
select tm('1');
Getting an error:
Here is the error details:
ERROR: column "t" does not exist
LINE 1: SELECT (select isnumeric(var))=t::BOOLEAN
You don't need a select (and it's actually wrong, as the error indicates) - just call isnumeric directly.
Also, by the way, your function is missing a return statement.
To sum it all up:
create or replace function tm(var text)
returns varchar as
$$
begin
if (isnumeric(var)) then -- call isnumeric directly
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
return '0'; -- missing return value in the OP
end;
$$
language plpgsql;
this will help you to identify your field is numeric or not:
select * from Table where field_name ~ '^[0-9]*$'
for decimal values you can use^[0-9.]*$ instead ^[0-9]*$
select getDataType('2021'); == Number
select getDataType('2021-05-12 23:12:10'); == Date
select getDataType('2021-05-12'); == Date
select getDataType('2X'); == String
CREATE
OR REPLACE FUNCTION getDataType ( TEXT ) RETURNS TEXT AS $$ DECLARE
x VARCHAR;
BEGIN
x = $1 :: NUMERIC;
RETURN 'Number';
EXCEPTION
WHEN OTHERS THEN
BEGIN
x = $1 :: DATE;
RETURN 'Date';
EXCEPTION
WHEN OTHERS THEN
RETURN 'String';
END;
END;
$$ STRICT LANGUAGE plpgsql IMMUTABLE;

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;

Looping in PostgreSQL

I am new to PostgreSQL and have a simple task with a looping structure.
Trying to print 0 to 10. Here is my function:
CREATE OR REPLACE FUNCTION LOOPING()
RETURNS TABLE(asd text) AS
$BODY$declare
i integer;
Begin
i:=0;
WHILE i > 10 LOOP
select i;
i:=(i+1);
END LOOP;
end;$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100
ROWS 1000;
ALTER FUNCTION LOOPING()
OWNER TO postgres;
I have tried with while loop. If anybody can do this task with for loop it will be very helpful.
You have several hick-ups in there. One working way (of many):
CREATE OR REPLACE FUNCTION f_loop()
RETURNS TABLE(asd int) AS
$BODY$
BEGIN
asd := 0;
WHILE asd < 11 LOOP
RETURN NEXT;
asd := asd + 1;
END LOOP;
END
$BODY$ LANGUAGE plpgsql IMMUTABLE
Call:
SELECT * FROM f_loop();
FOR loop
CREATE OR REPLACE FUNCTION f_loop()
RETURNS TABLE(asd int) AS
$BODY$
BEGIN
FOR i IN 0..10 LOOP
asd := i;
RETURN NEXT;
END LOOP;
END
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Or, for this simple case:
CREATE OR REPLACE FUNCTION f_loop()
RETURNS SETOF int AS
$BODY$
BEGIN
FOR i IN 0..10 LOOP
RETURN NEXT i;
END LOOP;
END
$BODY$ LANGUAGE plpgsql IMMUTABLE;
Details in the excellent manual.
Your problem as far as I can see is that you have to return the value properly and RETURN NEXT in my experiments (on Pg 9.1) did not work as I expected it to.
I tested this and it was working:
create or replace function loop() returns table (i int)
language plpgsql as
$$
declare i_array int[];
begin
for i in 0 .. 10 loop
i_array := i_array || i;
end loop;
return query select unnest(i_array);
end;
$$;