Unit testing plpgsql procedure which has TYPE data - postgresql

we have a TYPE t_string_array in our postgres database defined as character varying[].
We have a stored procedure which takes list of names and gives the result out in a cursor.
the procedure definition is
create or replace procedure test_lookup( in_speed t_string_array, inout display refcursor,
inout out_error_text TEXT);
I am trying to test this procedure with the block
do
$$
declare
display refcursor;
out_error_text text;
begin
call test_lookup(['Basic']::t_string_array,display::refcursor,out_error_text::text);
RAISE NOTICE 'mymsg1 = %', out_error_text;
RAISE NOTICE 'myvar1 = %', out_error_code;
END;
$$
I am getting error ERROR: syntax error at or near "["
I tried using call test_lookup('basic'::t_string_array,display::refcursor,out_error_text::text)
call test_lookup(array['basic']::character varying[],display::refcursor,out_error_text::text);
all gave me error.
Can you please suggest a way to test this procedure.

Related

psql pgadmin Procedure error column "trip" does not exist LINE 7: CALL example2(Trip)

I want to create a stored procedure in pgadmin that will output the number of rows from the "Trip" table. The table itself is output in cmd, the number of rows in this table is also output in cmd. But when writing a procedure and calling it, such an error comes out. I have psql version 15. How can I fix this error?
My code:
CREATE PROCEDURE example2(INOUT _name character varying) AS $$
BEGIN
SELECT count(*) FROM "_name";
END;
$$ LANGUAGE plpgsql;
CALL example2(Trip)
Error:
ERROR: ERROR: The "trip" column does not exist
LINE 7: CALL example2(Trip)
You are better off using a function then a procedure as it is easier to get value out. Using dynamic SQL along with the format function to properly quote the _name parameter.
CREATE OR REPLACE FUNCTION public.example2(_name character varying)
RETURNS integer
LANGUAGE plpgsql
AS $function$
DECLARE
ct integer;
BEGIN
EXECUTE format('SELECT count(*) FROM %I', _name) INTO ct;
RETURN ct;
END;
$function$
select example2('animals');
example2
----------
8

string array as parameter to plpgsql procedure

Can some one guide me how to test this procedure. (code got compiled but dont know if it is correct or not).
CREATE OR REPLACE PROCEDURE create_update_h( p_a_pkg_array CHARACTER VARYING [],p_u_pkg_array CHARACTER VARYING [] , inout out_error_code TEXT , inout out_error_text text )
LANGUAGE 'plpgsql'
calling with
do
$$
DECLARE out_error_code TEXT;
DECLARE out_error_text TEXT;
BEGIN
CALL create_update_h(
['t','t','t']::CHARACTER VARYING [],[result1,result2,result3]::CHARACTER VARYING [],out_error_code::TEXT,out_error_text::TEXT);
RAISE NOTICE 'myvar1 = %', out_error_code;
RAISE NOTICE 'mymsg1 = %', out_error_text;
END;
$$
giving error
ERROR: syntax error at or near "["
LINE 9: [t,t,t]::CHARACTER VARYING [],[result1,result2,result3]::CH...
^
SQL state: 42601
Character: 162
I tried the above script to test the proc . Could somebody tell me how to call a proceudre that has 2 arrays as input.
The syntax for array constructor in PostgreSQL is:
ARRAY[field, field ...]
The keyword ARRAY is mandatory

PostgreSQL using NO_DATA_FOUND exception in a sored Procedure

When I try to run a PostgreSQL stored procedure including the "STRICT" option and a record variable (rec) as I try to save (run the create statement) I get the following error:
ERROR: syntax error at or near "rec"
LINE 14: INTO STRICT rec
I' am following the guidelines stated on the official documentation https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW
where the only reference missing is that this can or can't be used inside a function or a stored procedure. I guess there should be a reasonable answer to this issue I couldn't found. I was able to succeed running an equivalent code inside a Do block, so it seams there is some incompatibility declaring a record type variable and functions.
This is the function code I was running:
CREATE OR REPLACE FUNCTION test_nodata()
RETURNS TABLE(id int, active boolean)
LANGUAGE plpgsql
AS $$
DECLARE
rec record;
tab VARCHAR ='text_maintenance_news';
BEGIN
RETURN QUERY
SELECT tm.id, tm.active
INTO STRICT rec
FROM text_maintenance_news tm
WHERE tm.active
LIMIT 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE 'Query from % has no data', tab;
END;
$$
As mentioned at the official documents, postgreSQL doesn't consider no data as an error but as a warning that the programmer must handle. Main reason to include the STRICT option.
Do block code (It works!) and result:
DO
LANGUAGE plpgsql
$$
DECLARE
rec record;
tab varchar = 'text_maintenance_news';
BEGIN
SELECT *
INTO STRICT rec
FROM text_maintenance_news
WHERE active
LIMIT 1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE 'Query from % return no data', tab;
END;
$$
ERROR: Query from text_maintenance_news return no data
CONTEXT: PL/pgSQL function inline_code_block line 13 at RAISE
SQL state: P0001

How to call a stored procedure in another procedure and use the result of it in the same procedure of Postgresql?

I want to use the inout return in my procedure like this:
do $$
declare
film_count text;
begin
-- get the number of films
CALL abc('999-M-120-20200906-E726265',
'911120006710', '120', null);
film_count = o_ricode;
-- display a message
raise notice 'The number of films is %', film_count;
end $$;
where o_ricode is inout param of proc 'abc'.
ERROR: procedure parameter "o_ricode" is an output parameter but the corresponding argument is not writable CONTEXT: PL/pgSQL function inline_code_block line 6 at CALL SQL state: 42601
Calling abc procedure separately giving the expected results but calls in another procedure not working.
CREATE OR REPLACE PROCEDURE abc(
INOUT o_ricode text)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
BEGIN
o_ricode := 'SUCCESS';
END;
$BODY$;
The message is clean - you can use only variables on positions of INOUT arguments. Procedure is not a function, and the function is not the procedure.
CREATE PROCEDURE proc(INOUT arg1 text)
AS $$
BEGIN
RAISE NOTICE 'arg1 = %', arg1;
arg1 := 'xxxx';
END;
$$ LANGUAGE plpgsql;
DO $$
DECLARE var text;
BEGIN
-- CALL proc('AHOJ'); -- this is your issue
var := 'AHOJ';
-- procedure invocation and passing value by ref
-- in this context, the procedure has not result,
-- but it can have side effects (outer variables
-- used as INOUT arguments can be changed)
CALL proc(var);
RAISE NOTICE 'var = %', var;
END;
$$;
NOTICE: arg1 = AHOJ
NOTICE: var = xxxx
DO
Procedures and functions (in Postgres) has different mechanism of passing INOUT variables. For procedures Postgres emulates passing value by reference (it is only emulation). Passing values (and taking result) is significantly different for functions.
CREATE FUNCTION func(INOUT arg1 text)
AS $$
BEGIN
RAISE NOTICE 'arg1 = %', arg1;
arg1 := 'xxxx';
END;
$$ LANGUAGE plpgsql;
DO $$
DECLARE var text;
BEGIN
-- function execution, argument is passed as value,
-- and the variable has assigned the result of function
var := func('AHOJ');
RAISE NOTICE 'var = %', var;
END;
$$;
NOTICE: arg1 = AHOJ
NOTICE: var = xxxx
DO

How to use EXECUTE FORMAT ... USING in postgres function

CREATE OR REPLACE FUNCTION dummytest_insert_trigger()
RETURNS trigger AS
$BODY$
DECLARE
v_partition_name VARCHAR(32);
BEGIN
IF NEW.datetime IS NOT NULL THEN
v_partition_name := 'dummyTest';
EXECUTE format('INSERT INTO %I VALUES ($1,$2)',v_partition_name)using NEW.id,NEW.datetime;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION dummytest_insert_trigger()
OWNER TO postgres;
I'm trying to insert using
insert into dummyTest values(1,'2013-01-01 00:00:00+05:30');
But it's showing error as
ERROR: function format(unknown) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Context: PL/pgSQL function "dummytest_insert_trigger" line 8 at EXECUTE statement
I'm unable get the error.
Your function could look like this in Postgres 9.0 or later:
CREATE OR REPLACE FUNCTION dummytest_insert_trigger()
RETURNS trigger AS
$func$
DECLARE
v_partition_name text := quote_ident('dummyTest'); -- assign at declaration
BEGIN
IF NEW.datetime IS NOT NULL THEN
EXECUTE
'INSERT INTO ' || v_partition_name || ' VALUES ($1,$2)'
USING NEW.id, NEW.datetime;
END IF;
RETURN NULL; -- You sure about this?
END
$func$ LANGUAGE plpgsql;
About RETURN NULL:
To ignore result in BEFORE TRIGGER of PostgreSQL?
I would advice not to use mixed case identifiers. With format( .. %I ..) or quote_ident(), you'd get a table named "dummyTest", which you'll have to double quote for the rest of its existence. Related:
Are PostgreSQL column names case-sensitive?
Use lower case instead:
quote_ident('dummytest')
There is really no point in using dynamic SQL with EXECUTE as long as you have a static table name. But that's probably just the simplified example?
You need explicit cast to text:
EXECUTE format('INSERT INTO %I VALUES ($1,$2)'::text ,v_partition_name) using NEW.id,NEW.datetime;