Select from a table, add a parameter to the result and return it from a function - postgresql

I have a function that returns the result of a select based on a parameter being passed to it. I would like to join the parameter to the returned result of the function. Here's an example:
create or replace function somefunc(param varchar)
returns table(fielda varchar, fieldb int, param varchar)
language plpgsql
as $$
begin
return query
select
fielda varchar,
fieldb int,
param varchar -- HOW DO I SELECT IT?
from
sometable
join
othertable on id = other_id
end;
$$

You just need to call the parameter correctly
I created a fake sometable table and inserted two rows with
create table sometable(fielda varchar, fieldb int);
insert into sometable values('a',1);
insert into sometable values('b',2);
Then specified the somefunc function with
create or replace function somefunc(param_in varchar)
returns table(fielda varchar, fieldb int, param varchar)
language plpgsql
as $$
begin
return query
select
sometable.fielda,
sometable.fieldb,
param_in
from sometable;
end;
$$
Check out the param_in input parameter not in contrast with the param field in the table. I removed the join with the othertable but that can also be added.

Related

Function using '= ALL ($1)' returning no values when multiple params passed

CREATE FUNCTION test(VARIADIC arr text[])
RETURNS TABLE (data_time TIMESTAMPTZ, id text, data jsonb)
AS 'SELECT data_timestamp, key, value
FROM hit_count
CROSS JOIN jsonb_each(data)
WHERE key = ALL ($1)'
LANGUAGE SQL;
If I call the function above with select test('123') it works fine. If I call it with select test('123','234') it returns nothing ie
test
------
(0 rows)
However if I define it as
CREATE FUNCTION test(VARIADIC arr text[])
RETURNS TABLE (data_time TIMESTAMPTZ, id text, data jsonb)
AS 'SELECT data_timestamp, key, value
FROM hit_count
CROSS JOIN jsonb_each(data)
WHERE key != ALL ($1)'
LANGUAGE SQL;
then the function returns all the data but those that fit the condition
Any ideas??
ALL was used as opposed to ANY the corrected function looks like this
CREATE FUNCTION test(VARIADIC arr text[])
RETURNS TABLE (data_time TIMESTAMPTZ, id text, data jsonb)
AS 'SELECT data_timestamp, key, value
FROM hit_count
CROSS JOIN jsonb_each(data)
WHERE key = ANY ($1)'
LANGUAGE SQL;

How to pass a table as argtype to postgres function?

create table test_tbl (id int, name character varying(10));
insert test_tbl values(1,'A');
insert test_tbl values(2,'B');
insert test_tbl values(3,'C');
insert test_tbl values(4,'D');
insert test_tbl values(5,'F');
Now i want to pass this table as a input argtype to function.
create function myfn (in tbl (how to define the table input))
as
return set of <some type>
begin
return query AS
select concat(id,name)
from test_tbl
where id in (select id from in_tbl);
end;
How to declare table type input argument?
How to call this function with table input?
select * from myfn(<pass the table - test_tbl>);
You can use the type regclass and build a dynamic query
create or replace function myfn (in tbl regclass)
returns TABLE(id INT)
as $$
begin
RETURN QUERY EXECUTE format('select id
from test
where id in (select id from %s)',tbl);
end
$$ LANGUAGE plpgsql;
and you call it using
select * from myfn('mytablename');

plpgSQL return record type from FUNCTION

I'm trying to use a plgSQL witch return me a record type :
CREATE FUNCTION actu(id INTEGER) RETURNS RECORD AS $$
DECLARE
ret RECORD;
BEGIN
SELECT id_photo, id_user, lien, titre
FROM photo
WHERE id_user IN (
SELECT id_userabo
FROM abo
WHERE id_user = id )
ORDER BY date_publi DESC LIMIT 10;
RETURN ret;
END;$$
LANGUAGE plpgsql;
When I'm trying to use it with :
SELECT * FROM actu(4)
AS (id_photo Integer, id_photo Integer, lien Varchar, titre Varchar);
pgAdmin4 send me error :
ERROR: ERROR: the request has no destination for the resulting data
HINT: If you want to cancel the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgsql function fil_actu(integer), line 5 with SQL statement
The immediate error is, that the result of a select statement needs to be stored somewhere (that's what the error says). You would need to use select .. into ret from ... to store the result, but that wouldn't work as a variable of type record can only store one row from a result.
You apparently want to return more than just one row, so you need to define the function as returns table() and then use return query in PL/pgSQL to return the result of a query. But for a simple function encapsulating a SELECT query, a language sql function is more efficient.
CREATE FUNCTION actu(id INTEGER)
-- adjust the data types for the returned columns!
RETURNS table (id_photo int, id_user int, lien text, titre text)
AS $$
SELECT id_photo, id_user, lien, titre
FROM photo
WHERE id_user IN (SELECT id_userabo
FROM abo
WHERE id_user = id )
ORDER BY date_publi DESC
LIMIT 10;
$$
LANGUAGE sql;
You can use that function like this:
select *
from actu(42);
You may define those types inside the function, but with different names for the types. The return type can be a TABLE type and use RETURN QUERY to return the results.
CREATE FUNCTION actu(id INTEGER) RETURNS TABLE
(typ_id_photo Integer, typ_id_user Integer, typ_lien Varchar, typ_titre Varchar)
AS $$
BEGIN
RETURN QUERY
SELECT id_photo, id_user, lien, titre
FROM photo p
WHERE id_user IN (SELECT id_userabo
FROM abo
WHERE id_user = id )
ORDER BY date_publi DESC
LIMIT 10;
END;$$
LANGUAGE plpgsql;

Greenplum/Postgres 8 function dynamic result set?

I need to write a function that returns a table with unknown number of columns.
If i receive 'None' in column input parameter then that column shouldn't be included in the output. In postgres 9+ there is a solution for this problem.
something like below:
CREATE OR REPLACE FUNCTION data_of(id integer,col1 varchar,col2 varchar, col3 varchar)
RETURNS TABLE (count_rec, dimensions text[] ) AS
$func$
DECLARE
_dimensions text := 'col1, col2, col3'; -- If i receive 'None' in input param then i exclude that from column list
BEGIN
RETURN QUERY EXECUTE format('
SELECT count(*) as count_rec,
string_to_array($1) -- AS dimensions
FROM x
WHERE id = $2'
, _dimensions)
USING _dimensions , _id;
END
$func$ LANGUAGE plpgsql;
But in Greenplum (Postgres 8.2) i could not find any. Is there any similar solution?
thanks
You have 2 options to do it: use set-returning function returning "record" or returning your custom type.
First option:
create table test (a int, b int, c int, d varchar, e varchar, f varchar);
insert into test select id, id*2, id*3, (id*4)::varchar, (id*4)::varchar, (id*4)::varchar from generate_series(1,10) id;
create or replace function test_func(column_list varchar[]) returns setof record as $BODY$
declare
r record;
begin
for r in execute 'select ' || array_to_string(column_list, ',') || ' from test' loop
return next r;
end loop;
return;
end;
$BODY$
language plpgsql
volatile;
select * from test_func(array['a','c','e']) as f(a int, c int, e varchar);
Second option:
create table test (a int, b int, c int, d varchar, e varchar, f varchar);
insert into test select id, id*2, id*3, (id*4)::varchar, (id*4)::varchar, (id*4)::varchar from generate_series(1,10) id;
create type testtype as (
a int,
c int,
e varchar
);
create or replace function test_func() returns setof testtype as $BODY$
declare
r testtype;
begin
for r in execute 'select a,c,e from test' loop
return next r;
end loop;
return;
end;
$BODY$
language plpgsql
volatile;
select * from test_func();
But I'm 99% sure you're trying to do something wrong. In Greenplum the result of function execution cannot be used as a "table" in join conditions, because the function executes on the master. You even won't be able to create a table out of the last query returning the data from your function because of this limitation
In short, this is not a recommended way to work with data in Greenplum

Update table being returned in PostgreSQL

I'm looking for help with a PostgreSQL function that returns a table.
I would like to know if there is a way of updating the table that is being returned.
Here's an example,
create or replace function fn_function()
return table(column01 integer, column02 integer, column03 boolean) as $$
return query
select col1, col2, false
from tableXYZ;
/* how can i update the table, let's say column03 before the function exits */
end
$$ language plpgsql;
Can i give an alias to the table being returned?
The postgre version in use is 9.0.8.
Thx in advance.
Here is a set based solution.
The RETURNS TABLE is just portal to get data out you can't do anything inside the function that defines it. You could create another function and call this one and do things to the result set. However I use a temp table so you can manipulate the data before you send it out.
CREATE OR REPLACE FUNCTION fn_function()
RETURNS TABLE(column01 integer, column02 integer, column03 boolean) AS $$
BEGIN
CREATE TEMP TABLE temp_tableXYZ (column01 integer, column02 integer, column03 boolean) ON COMMIT DROP;
INSERT INTO temp_tableXYZ (column01, column02, column03)
SELECT col1,col2,col3
FROM tableXYZ;
--WHERE filter if you can.
UPDATE temp_tableXYZ
SET col1 = 9999;
RETURN QUERY select column01, column02, column03 from temp_tableXYZ;
END;
$$ LANGUAGE plpgsql;
You can call it using an alias like this:
SELECT * FROM fn_function() as my_table;
Just do a query which returns the values you want. It can be plain sql:
create or replace function fn_function()
returns table (
column01 integer, column02 integer, column03 boolean
) as $$
select col1, col2, col2 > 10
from tableXYZ;
$$ language sql;
In the example above column 3 will be true if col2 > 10 and false otherwise. Another example using a subselect:
create or replace function fn_function()
returns table (
column01 integer, column02 integer, column03 boolean
) as $$
select col1, col2, (select max(col1) > 10 from t where col2 = tableXYZ.col1)
from tableXYZ;
$$ language sql;
Notice that it is not return but returns
To select from table, modify the results of select and pass them as results of a function try something like:
create or replace function fn_function()
returns table (
column01 integer, column02 integer, column03 boolean
) as $$
begin
for rec in select col1, col2, false as col3
from tableXYZ;
loop
rec.col3 := col1 > col2;
return next rec;
end loop;
return;
end
$$ language plpgsql;
Details here.
To select get the results of this function simply
SELECT function_alias.col1, function_alias.col2
FROM fn_function() function_alias;
You can do with this function same things you can do with normal tables.