Reputation: 13
I’m discovering PL/ pgSQL and the functions creation. In order to create a code more human readable I would like use custom nested functions or in other words I want call a function with the results of one other. My functions are:
CREATE SCHEMA IF NOT EXISTS routing_roaddata_func;
CREATE OR REPLACE FUNCTION "routing_roaddata_func".get_nav_strand_ids(link_id_v bigint ) RETURNS TABLE
(nav_strand_ids bigint) as $$
BEGIN
RETURN QUERY select nav_strand_id from rdf_wvd_211f0_1.rdf_nav_strand where link_id = link_id_v ;
END;
$$ LANGUAGE plpgsql;
--------------
CREATE OR REPLACE FUNCTION "routing_roaddata_func".get_condition_type(strand_ids_v bigint) RETURNS TABLE
(condition_id_ bigint )
AS $$
BEGIN
condition_id_ := (select condition_type from rdf_wvd_211f0_1.rdf_condition where nav_strand_id = strand_ids_v );
END;
$$ LANGUAGE plpgsql;
---------------
CREATE OR REPLACE FUNCTION "routing_roaddata_func".get_condition_type2(strand_ids_v bigint, out condition_id_ bigint)
AS $$
BEGIN
condition_id_ := (select condition_type from rdf_wvd_211f0_1.rdf_condition where nav_strand_id = strand_ids_v );
END;
$$ LANGUAGE plpgsql;
----------------
And I get some troubles when I want use its. I try :
select "routing_roaddata_func".get_nav_strand_ids(820636761); -- works
select "routing_roaddata_func".get_condition_type("routing_roaddata_func".get_nav_strand_ids(820636761)); -- the returns is empty
select "routing_roaddata_func".get_condition_type2("routing_roaddata_func".get_nav_strand_ids(820636761)); -- works
select * from "routing_roaddata_func".get_condition_type("routing_roaddata_func".get_nav_strand_ids(820636761)); **--ERROR: set-returning functions must appear at top level of FROM**
It's annoying because my final goal is to add a where clause like that to detect the presence of one modality in the returned values.
select * from "routing_roaddata_func".get_condition_type("routing_roaddata_func".get_nav_strand_ids(820636761)) where condition_type = 23;
Someone could explain me the problem of the "set-returning functions" ? How can I proceed ?
Upvotes: 0
Views: 337
Reputation: 45795
Set Returning Function (in Postgres terminology - function that returns table) cannot be used as argument of any other function. You can pass more values as one parameter using by an arrays, or you can use LATERAL
join:
create or replace function fx(int[])
returns table (a int, b int) as $$
begin
for i in 1..3 loop
foreach b in array $1 loop
a := i; return next;
end loop;
end loop;
end;
$$ language plpgsql;
-- ARRAY(subselect) does an array from table
postgres=# select * from fx(array(select generate_series(1,3)));
┌───┬───┐
│ a │ b │
╞═══╪═══╡
│ 1 │ 1 │
│ 1 │ 2 │
│ 1 │ 3 │
│ 2 │ 1 │
│ 2 │ 2 │
│ 2 │ 3 │
│ 3 │ 1 │
│ 3 │ 2 │
│ 3 │ 3 │
└───┴───┘
(9 rows)
-- using LATERAL join
create or replace function fx1(int)
returns table (a int, b int) as $$
begin
for i in 1..3 loop
a := i; b := $1; return next;
end loop;
end;
$$ language plpgsql;
-- for any row of function generate_series is called function fx1
postgres=# select fx1.*
from generate_series(1,3) g(v),
LATERAL fx1(v) order by a, b;
┌───┬───┐
│ a │ b │
╞═══╪═══╡
│ 1 │ 1 │
│ 1 │ 2 │
│ 1 │ 3 │
│ 2 │ 1 │
│ 2 │ 2 │
│ 2 │ 3 │
│ 3 │ 1 │
│ 3 │ 2 │
│ 3 │ 3 │
└───┴───┘
(9 rows)
Upvotes: 2