how to iterate and append jsonb in postgres db function - postgresql

I have a DB function say "myFunction(input integer)" which takes an input and returns a set of json as below
select * from myFunction(1)
>> [{"a":"b","c":"d"},{"e":"f"}]
I have a DB table "table1" with column 'column1'.
I need to pass the values from table1.column1 into myFunction as an argument and append its result to build one json array
I have created the below db function and it works fine with only one problem, as it appends an empty json at begining.
[{},{"a":"b","c":"d"},{"e":"f"},{"k":"l"}]
kindly help me to provide some optimal solutions or get rid of empty json object in array.
CREATE OR REPLACE FUNCTION myWrapperFunction()
RETURNS SETOF json
LANGUAGE 'plpgsql'
COST 100
STABLE STRICT
ROWS 1000
AS $BODY$
DECLARE
_elements INTEGER[];
_element INTEGER;
_results json;
_result json;
_all_result jsonb;
val json ='{}'::json;
BEGIN
SELECT ARRAY_AGG( DISTINCT column1) into _elements from table1;
FOREACH _element IN ARRAY _elements
LOOP
SELECT * FROM myFunction(_element) into _results;
IF _results IS NOT null THEN
val=val::jsonb||_results::jsonb;
END IF;
END LOOP;
RETURN QUERY select val;
RETURN ;
END; $BODY$;
ALTER FUNCTION myWrapperFunction()
OWNER TO postgres;

Related

How multiple rows can be selected from a table in triggers in postgres

I am trying to write a trigger in which I have to create a Json after getting data(multiple rows) from another table.
I have two table task and data. data table contains multiple information about the task in key/value pair.
task schema
taskid
description
value
data table schema
id
taskid
key
value
Now in trigger I want to fetch all data corresponding to a task and prepare a JSON from that.
I am using below
CREATE OR REPLACE FUNCTION event()
RETURNS trigger AS
$BODY$
DECLARE
_message json;
_data data;
BEGIN
SELECT * INTO _data FROM data WHERE data.taskid = New.taskid;
IF TG_OP = 'INSERT' THEN
_messag:=json_build_object('taskId',NEW.taskid,'description',NEW.description,'value',NEW.value,'clientis',_data);
END IF;
INSERT INTO events(message)
VALUES(_messag);
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
Here, I am using below query to get all data from data table corresponding to a taskid
SELECT * INTO _data FROM data WHERE data.taskid = New.taskid;
Here, the problem is that I am getting only one row. How can all rows will be fetched? If anyone has any idea?
You can aggregate everything into a single JSON value:
declare
...
_data jsonb; --<< change the data type to jsonb
begin
...
IF TG_OP = 'INSERT' THEN
-- only select everything if you really need it
SELECT jsonb_agg(to_jsonb(data))
INTO _data
FROM data
WHERE data.taskid = New.taskid;
_message := json_build_object('taskId',NEW.taskid,'description',NEW.description,'value',NEW.value,'clientis',_data);
END IF;
...
It works for me:
CREATE OR REPLACE FUNCTION event()
RETURNS trigger AS
$BODY$
DECLARE
_message json;
_data jsonb;
BEGIN
*****SELECT json_agg(tmp)
INTO _data
FROM (
-- Your subquery goes here, for example:
SELECT data.key, data.value
FROM.data
WHERE data.taskid = New.taskid
) tmp;*****
IF TG_OP = 'INSERT' THEN
_messag:=json_build_object('taskId',NEW.taskid,'description',NEW.description,'value',NEW.value,'clientis',_data);
END IF;
INSERT INTO events(message)
VALUES(_messag);
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
Research link: select statement in postgres function called inside a trigger

How to combine custiom defined variables and display them as records of a table in postgres

I'm a beginner in plpgsql and working on a project which requires me to write a function that returns two variables in the form of 2 columns (res,Result). I've done a quite a bit of searching but didn't find answer for the same. The reference to my code is below
CREATE OR REPLACE FUNCTION propID(character varying)
RETURNS SETOF RECORD AS $val$
DECLARE
t_row record;
res BOOLEAN;
result character varying;
value record;
BEGIN
FOR t_row IN SELECT property_id FROM property_table WHERE ward_id::TEXT = $1 LOOP
RAISE NOTICE 'Analyzing %', t_row;
res := false; -- here i'm going to replace this value with a function whos return type is boolean in future
result := t_row.property_id;
return next result; --here i want to return 2 variables (res,result) in the form of two columns (id,value)
END LOOP;
END;
$val$
language plpgsql;
Any help on the above query would be very much appreciated.
Assuming that property_id and ward_id are integers you can achieve your goal in a simple query like this:
select some_function_returning_boolean(property_id), property_id
from property_table
where ward_id = 1; -- input parameter
If you absolutely need a function, it can be an SQL function like
create or replace function prop_id(integer)
returns table (res boolean, id int) language sql
as $$
select some_function_returning_boolean(property_id), property_id
from property_table
where ward_id = $1
$$;
In a plpgsql function you should use return query:
create or replace function prop_id(integer)
returns table (res boolean, id int) language plpgsql
as $$
begin
return query
select some_function_returning_boolean(property_id), property_id
from property_table
where ward_id = $1;
end
$$;

In clause in postgres

Need Output from table with in clause in PostgreSQL
I tried to make loop or ids passed from my code. I did same to update the rows dynamically, but for select I m not getting values from DB
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying
)
RETURNS void
AS
$$
DECLARE
ArrayText text[];
i int;
BEGIN
select string_to_array(branchidcol, ',') into ArrayText;
i := 1;
loop
if i > array_upper(ArrayText, 1) then
exit;
else
SELECT
pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight,
pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE
pd.accountgroupid = accountgroupIdCol AND pd.branchid IN(ArrayText[i]::numeric);
i := i + 1;
end if;
END LOOP;
END;
$$ LANGUAGE 'plpgsql' VOLATILE;
There is no need for a loop (or PL/pgSQL actually)
You can use the array directly in the query, e.g.:
where pd.branchid = any (string_to_array(branchidcol, ','));
But your function does not return anything, so obviously you won't get a result.
If you want to return the result of that SELECT query, you need to define the function as returns table (...) and then use return query - or even better make it a SQL function:
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying )
RETURNS table(branchid integer, totallr integer, totalarticle integer, totalweight numeric, totalamount integer)
AS
$$
SELECT pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight, pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE pd.accountgroupid = accountgroupIdCol
AND pd.branchid = any (string_to_array(branchidcol, ',')::numeric[]);
$$
LANGUAGE sql
VOLATILE;
Note that I guessed the data types for the columns of the query based on their names. You have to adjust the line with returns table (...) to match the data types of the select columns.

Query to insert array of json object into postgres

I have a table with field fields json[]. I have created a function to insert the record into that table and here is the call
select * from add('[{"name":"Yes","value":"yes"},{"name":"No","value":"no"},{"name":"Neutral","value":"neutral"}]') as result;
and here is the function itself
CREATE OR REPLACE FUNCTION public.add(
_fields json[]) RETURNS SETOF json
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
query text;
BEGIN
insert into my_table(fields)
values(_fields);
query = 'SELECT json_build_object(''message'', ''Added.'')';
RETURN QUERY EXECUTE query;
END;
$BODY$;
but this is showing
malformed array literal: "[{"name":"Yes","value":"yes"},{"name":"No","value":"no"},{"name":"Neutra
then I tried this
select * from add('{"name":"Yes","value":"yes"},{"name":"No","value":"no"},{"name":"Neutral","value":"neutral"}') as result;
and this insert statement in function like
insert into polls(fields) values(array([''||_fields||'']::json[]));
and this is showing
syntax error at or near "["
I was missing " for each individual object. This is how to create json object
{"{\"name\":\"Yes\",\"value\":\"yes\"}","{\"name\":\"No\",\"value\":\"no\"}","{\"name\":\"Neutral\",\"value\":\"neutral\"}"}
so the final query is
select * from add('{"{\"name\":\"Yes\",\"value\":\"yes\"}","{\"name\":\"No\",\"value\":\"no\"}","{\"name\":\"Neutral\",\"value\":\"neutral\"}"}') as result;

Syntax error at or near "unnest"

This request:
unnest('{1,2}'::int[]);
gives to me this error:
syntax error at or near "unnest"
neither unnest('{1,2}'); works
Why?
intire:
CREATE OR REPLACE FUNCTION result() RETURNS setof users AS
$$
DECLARE
BEGIN
unnest('{1,2}'::int[]);
RETURN QUERY SELECT * FROM users;
END;
$$ LANGUAGE plpgsql;
SELECT result();
EDIT
The core idea:
To retrive and manipualate with the bigint[] which is stored inside in a column.
So, i have got this:
SELECT * FROM users WHERE email = email_ LIMIT 1 INTO usr;
Then, usr.chain contains some bigint[] data. For example, {1,2,3,4,5,6,7,8,9,10}. I want to save only the 4 last of them.
How to retrieve {7,8,9,10} and {1,2,3,4,5,6} and iterate over these arrays?
I only found the solution is to use SELECT FROM unnest(usr.chain) AS x ORDER BY x ASC LIMIT (sdl - mdl) OFFSET mchain and so on. but unnest function gives to me this stupid error. I'm really do not understand why it happends. It doesn't work in sucj easy case I wrote at the beginning of the question. subarray function doesn't work because of the data type is bigint[] not int[]
Futher more, the code unnest(ARRAY[1,2]) gives to me the same error.
http://www.postgresql.org/docs/9.2/static/functions-array.html
The same error for array_append function
to iterate over array:
CREATE OR REPLACE FUNCTION someresult(somearr bigint[] ) RETURNS setof bigint AS
$$
DECLARE
i integer;
x bigint;
BEGIN
for x in select unnest($1)
loop
-- do something
return next x;
end loop;
-- or
FOR i IN array_lower($1, 1) .. array_upper($1, 1)
LOOP
-- do something like:
return next ($1)[i];
end loop;
END;
$$ LANGUAGE plpgsql;
select someresult('{1,2,3,4}') ;
array_append ....
CREATE OR REPLACE FUNCTION someresult2(somearr bigint[],val bigint ) RETURNS bigint[] AS
$$
DECLARE
somenew_arr bigint[];
BEGIN
somenew_arr = array_append($1, $2 );
return somenew_arr;
END;
$$ LANGUAGE plpgsql;
select someresult2('{1,2,3,4}' ,222) ;
so, here you have basic example how to iterate and append arrays. Now can you write step by step what you want to do, to achieve .