plpgsql in EDB: SPL procedure with SPL-style OUT parameter or a function cannot be invoked using CALL in PL/pgSQL - enterprisedb

I'm trying to run natively correct plpgsql code in EDB environment. Unfortunately there is a problem. Interestingly, the first run does not generate an error. Restarts generate an error, but after a few repetitions, there is no error again.
In PosgreSQL, the syntax DOES NOT CAUSE any problems.
Below is an example:
CREATE OR REPLACE PROCEDURE test1()
AS $procedure$
DECLARE
BEGIN
null;
END;
$procedure$
LANGUAGE plpgsql
;
CREATE OR REPLACE PROCEDURE test2()
AS $procedure$
DECLARE
BEGIN
call test1();
END;
$procedure$
LANGUAGE plpgsql
;
CREATE OR REPLACE PROCEDURE test3()
AS $procedure$
DECLARE
BEGIN
call test2();
END;
$procedure$
LANGUAGE plpgsql
;
And now try to run it in postgresql way and EDB way:
--run it few times as edb - error occurs randomly
begin
test3();
end;
--once again as plpgs - no error occurs but... check last call
do
$$
begin
CALL test3();
end;
$$
--once again as plpgs with exception block. - now error occurs same as edb call
do
$$
declare
v_sqlstate text;
v_message text;
v_context text;
begin
CALL test3();
EXCEPTION
WHEN OTHERS THEN
GET STACKED DIAGNOSTICS v_sqlstate = returned_sqlstate,v_message = message_text,v_context = pg_exception_context;
RAISE NOTICE 'sqlstate: %,message: %,context: %', v_sqlstate,v_message,v_context;
end;
$$
Error is:
ERROR: SPL procedure with SPL-style OUT parameter or a function cannot be invoked using CALL in PL/pgSQL
HINT: You might want to use SELECT instead.
CONTEXT: PL/pgSQL function test3() line 4 at CALL
edb-spl function inline_code_block line 2 at procedure/function invocation statement
SQL state: 42809
What am I missing???

I find that this might be a bug fixed in EPAS 13.8 (DB-1818).
https://www.enterprisedb.com/docs/epas/13/epas_rel_notes/epas13_8_12_rel_notes/
I guess you may try your test in this or later new minor version.
Best Regards.

Related

Execute query passed in argument in Postgresql

I'm learning plpgsql and I have an exercise where I have to check if a query passed in function argument raises an exception or not and for that I need to run that query but I have no idea how to that.
For the moment I have this :
CREATE OR REPLACE FUNCTION exec(query varchar(100)) RETURNS BOOLEAN AS $$
BEGIN
BEGIN
raise notice 'query : %', query;
PERFORM query;
return 1;
EXCEPTION
when undefined_table then
raise notice 'undefined table';
WHEN undefined_column THEN
raise notice 'undefined column';
WHEN foreign_key_violation THEN
raise notice 'foreign key violation ';
WHEN syntax_error THEN
raise notice 'syntaxe error';
END;
return 0;
END
$$ LANGUAGE PLPGSQL;
Right now the problem I have is with the 5th line. It's where I'd want to perform the query to catch an error and then return 1 if no exception is caught or else return 0 after the "END" if there's an error.
Thank you for your help!
You cannot to execute dynamic query by statement PERFORM. You should to use statement EXECUTE.
CREATE OR REPLACE FUNCTION exec(query text)
RETURNS BOOLEAN
AS $$
BEGIN
RAISE NOTICE 'query : %', query;
EXECUTE query;
RETURN true;
EXCEPTION
WHEN when undefined_table THEN
RAISE NOTICE 'undefined table';
WHEN undefined_column THEN
RAISE NOTICE 'undefined column';
WHEN foreign_key_violation THEN
RAISE NOTICE 'foreign key violation ';
WHEN syntax_error THEN
RAISE NOTICE 'syntax error';
RETURN false;
END;
$$ LANGUAGE PLPGSQL;
Good start for programming in PL/pgSQL is reading related documentation. It has only few pages. The programming of stored procedures in PL/pgSQL is partially different from application's programming or from programming of stored procedures in other RDBMS.

Unable to get value for input parameter inside postgres function

In the below postgres function I am passing 'sample' (integer) as an input parma but when I try to print it's value using raise notice inside the function body I get the following error
ERROR: column "sample" does not exist LINE 1: SELECT sample
CREATE OR REPLACE FUNCTION public.test_function(
sample integer)
RETURNS json
LANGUAGE 'sql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
DO $$
BEGIN
raise notice 'test: %',sample;
END
$$;
select json_agg(1);
$BODY$;
select "test_function"(10);
It's the anonymous pl/pgsql DO block that does not 'see' the sample parameter. Here is a rewrite in pl/pgsql that does 'see' it.
CREATE OR REPLACE function test_function(sample integer)
RETURNS json LANGUAGE plpgsql COST 100 VOLATILE PARALLEL UNSAFE AS
$BODY$
BEGIN
raise notice 'test: %',sample;
return json_agg(1 + sample);
END
$BODY$;
pl/pgsql DO blocks are more or less encapsulated and can not return anything either.

Function Doesn't Work: ERROR: syntax error at or near "DELETE"

I am trying to create a function inside Postgres. For some reason my query works perfectly fine when I run it from inside the Query tool. Once I added the query to my function, I get the error
ERROR: syntax error at or near "DELETE"
Not sure what is the problem.
CREATE FUNCTION public.remove_email_header()
RETURNS pg_trigger
LANGUAGE 'plpgsql'
AS $BODY$
DELETE FROM public.spam_dictionary WHERE words LIKE '%FROM%';
$BODY$;
ALTER FUNCTION public.remove_email_header()
OWNER TO postgres;
Two Things to note.
A plpgsql Postgres function uses BEGIN END
The plpgsql should not be quoted.
CREATE FUNCTION remove_email_header()
RETURNS trigger
LANGUAGE plpgsql
AS $BODY$
BEGIN
DELETE FROM public.spam_dictionary WHERE words LIKE '%FROM%';
END
$BODY$;

NZSQL/CODE - How to use PRINT in Netezza

We are using Aginity Workbench for Netezza SQL and I was wondering if anyone knows of a equivalent in NZSQL for the TSQL "PRINT" function?
We use it for printing errors when someone tries to execute a query that would rewrite data when it shouldnt, and the only solution I am finding is using netezza command line "-t".
Thanks in advance!
You can use RAISE to do this, as documented here.
Here is an example:
CREATE OR REPLACE PROCEDURE RAISE_DEMO()
RETURNS VARCHAR(ANY)
EXECUTE AS OWNER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
MYNAME varchar;
BEGIN
MYNAME := 'SCOTT';
RAISE NOTICE 'Hello, %', MYNAME;
END;
END_PROC;
TESTDB.ADMIN(ADMIN)=> call raise_demo();
NOTICE: Hello, SCOTT
RAISE_DEMO
------------
(1 row)
If you change NOTICE to EXCEPTION, then the execution will stop.
CREATE OR REPLACE PROCEDURE RAISE_DEMO()
RETURNS VARCHAR(ANY)
EXECUTE AS OWNER
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
MYNAME varchar;
BEGIN
MYNAME := 'SCOTT';
RAISE EXCEPTION 'Hello, %, this is an exception', MYNAME;
RAISE NOTICE 'You should not see this message';
END;
END_PROC;
TESTDB.ADMIN(ADMIN)=> call raise_demo();
ERROR: Hello, SCOTT, this is an exception
TESTDB.ADMIN(ADMIN)=>
This behavior is in documented in the link I provided at the top.

Writing Errors to File in Postgresql

I want to write errors to a file in Postgresql, so whenever error occurs in a function it writes to a file, so I have captured the error and I pass on the error to another function and the return of that function is written to a file. Below is a sample function,
CREATE OR REPLACE FUNCTION test(TEXT)
RETURNS VOID
STRICT
LANGUAGE plpgsql
AS $$
declare STATEMENT TEXT;
declare sql_code TEXT;
BEGIN
BEGIN
EXECUTE 'DROP TABLE ' || $1;
EXCEPTION WHEN others THEN
sql_code := SQLERRM;
STATEMENT := 'COPY (select * from test1('''||sql_code||''')) to ''/tmp/errors.txt''';
EXECUTE STATEMENT;
RETURN;
END;
RAISE NOTICE 'Dropped table successfully %', $1;
RETURN;
END;
$$;
CREATE OR REPLACE FUNCTION test1(TEXT)
RETURNS TEXT
STRICT
LANGUAGE plpgsql
AS $$
declare error TEXT;
BEGIN
error := $1;
RETURN STATEMENT;
END;
$$;
This thing works fine but I want to know if there is any good way to capture the error and log it to a file ? Please suggest.
Changing logging levels would be preferable though there may be good reasons to prevent this.
Failing that you could write a secondary logging routine in, say, pl/perlu, or pl/python, which could write to a file. Just be careful that you don't overwrite your data files O.o.....