Amazon redshift stored procedure, CONTINUE cannot be used outside a loop; - amazon-redshift

Im building a stored procedure in amazon redshift.
This is an example of what im trying to do.
CREATE OR REPLACE PROCEDURE test_sp1()
LANGUAGE plpgsql
AS $$
DECLARE v_test RECORD;
BEGIN
FOR v_test IN select * from pg_user
LOOP
RAISE INFO 'before loop';
CONTINUE;
RAISE INFO 'after loop';
END LOOP;
END;
$$;
CALL test_sp1();
This piece of code gives me an exception
"[42601][500310] Amazon Invalid operation: CONTINUE cannot be used outside a loop".
Why can i not use continue in this loop?

The error appears to be happening when CONTINUE passes control to the beginning of the loop but there's no more iterating to be done.

Related

Continue a PL/pgSQL block even if it finds an error

I've gotten the essence of the function below from: How to re-check an SQL function created with check_function_bodies=false?
The context is: I'm migrating some functions from Oracle to PostgreSQL. While migrating them, I used the option which establishes a non-verification of their bodies, so that all function could be created without being compiled/verified, what would "speed" the process. Therefore, now - using the function bellow as a mean - I am trying to make an analysis of each function created in this X schema.
My problem is that the function doesn't continue when it finds an error. My central thought is to run the recompile_function() once and get all the messages fired when an error is found for each function. I have tried to enclosure the statement that verifies the function within a sub-block (BEGIN, EXCEPTION, END). It didn't work though.
What am I missing here?
CREATE OR REPLACE FUNCTION public.recompile_functions()
RETURNS void
LANGUAGE plpgsql
AS
$function$
DECLARE
l_func regprocedure;
BEGIN
--test plpgsql functions
FOR l_func IN (
SELECT oid
FROM pg_proc
WHERE pronamespace='<<schema>>'::regnamespace
AND prolang=(SELECT oid FROM pg_language WHERE lanname='plpgsql')
AND pg_proc.oid NOT IN (select tg.tgfoid FROM pg_trigger tg)
AND pg_proc.prokind = 'f'
)
LOOP
BEGIN
PERFORM plpgsql_validator(l_func);
EXCEPTION
WHEN OTHERS THEN
RAISE EXCEPTION 'Function % failed validation checks: %', l_func::text, SQLERRM;
END;
END LOOP;
END;
$function$

How to re-create function with same name in postgres?

I need to re-create a group of functions but I don't want to check their parameters to use drop if there are functions with the same names but different parameters.
Is this possible to drop/recreate them only by name?
Or is this possible to catch exceptions, raise errors and continue to execute the transaction?
I'm trying to do it using
DO $$
BEGIN
BEGIN
CREATE OR REPLACE FUNCTION public.test(id integer)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
begin
end;
$function$
;
EXCEPTION
WHEN duplicate_function THEN RAISE NOTICE 'already exists';
END;
END;
$$;
But It completes scripts quietly and does not raise any errors.
You are correct in that 42723 is raised when a named object already, However, it is not a named exception. Thus your exception handles does not recognized, so it takes no action. You can get what you want by directly referencing the SQLSTATE and your error code.
DO $$
BEGIN
BEGIN
CREATE FUNCTION public.test(id integer)
RETURNS text[]
LANGUAGE plpgsql
AS $function$
begin
end;
$function$
;
EXCEPTION
WHEN SQLSTATE '42723' THEN RAISE NOTICE 'already exists';
END;
END;
$$;
Raise notice sends the text following to sysout, which is often not accessible in a production system. You might want to change to raise exception.

POSTGRESQL Database Triggers anf functions

I am trying to create a trigger in postgres that if you are trying to add an existing id within a customers table it will raise an error and won't allow you to do it.
Trigger Code:
create trigger id_check()
before insert on customers
for each row execute procedure duplicates()
Function:
create or replace function duplicates()
returns trigger as $BODY$
begin
if exists(select 1 from customers where id = new.id)
then raise notice 'cannot have a duplicate id'
return new;
end;
$BODY$ LANGUAGE plpgsql;
I keep getting errors either and I'm not understanding what's wrong? Any help would be great.
As indicated a unique constraint is the appropriate method to properly handle this. But if you insist on your trigger then then you must cleanup the syntax errors: need semi-colon after raise statement, and end if at conclusion of IF. Also, learn now to format your code.
create or replace function duplicates()
returns trigger as $BODY$
begin
if exists(select 1 from customers where id = new.id)
then raise notice 'cannot have a duplicate id'; --- added ;
end if; --- added line
return new;
end;
$BODY$ LANGUAGE plpgsql;

Postgres: syntax error when trying to create multiple stored procedures from a single file

I am using Postgres version 13.1. I want to have a single file where I could store all stored procedures and create them in one shot. But when I put multiple stored procedures in a single file, I get the following error. What am I missing?
In my test.sql file I have the following content:
create or replace procedure tmp1(
)
language plpgsql as
$$
declare
l_count integer;
begin
select 1 into l_count;
raise info 'count: %', l_count;
end;
$$
create or replace procedure tmp2(
)
language plpgsql as
$$
declare
l_count integer;
begin
select 1 into l_count;
raise info 'count: %', l_count;
end;
$$
If I only have the first procedure it gets created and I can call it successfully. But the moment I have the second identical procedure with a different name, it gives me an error as follows (when run from psql):
psql=> \i test.sql
psql:test.sql:23: ERROR: syntax error at or near "create"
LINE 12: create or replace procedure tmp2(
OK - right after posting I tried putting a ";" after the end of first procedure and it works

How to quit a plpgsql procedure

In my plpgsql procedure, I start with checking if primary key for the input table exists. If not I raise a notice and want to quit the procedure. Otherwise, I continue with the rest of procedure. I spent a bit of time searching online but no clear answer. Please note that I am referring to a procedure which doesn't return anything so I can't use RETURN.
You can use return.
create or replace procedure test(text)
language plpgsql as $$
begin
raise notice '%', $1;
return;
raise notice 'never executed';
end $$;
call test('hello');
NOTICE: hello
CONTEXT: PL/pgSQL function test(text) line 3 at RAISE
CALL