I'm trying to adapt a Postgres stored procedure into a function in order to provide some feedback to the caller.
The procedure conditionally deletes rows in specific schemas, and I'd want the function to do the same, but also return the amount of rows that were deleted for each schema.
The original stored procedure is:
create or replace procedure clear_tenants()
language plpgsql as $function$
declare
tenant text;
begin
for tenant in
select tenant_schema
from public.tenant_schema_mappings
loop
execute format($ex$
delete from %I.parent
where expiration_date_time < now()
$ex$, tenant);
end loop;
end
$function$;
My current transform into a function is:
CREATE OR REPLACE FUNCTION testfun()
RETURNS TABLE(tsname varchar, amount numeric) AS
$BODY$
declare
tenant text;
trow record;
BEGIN
for tenant in
select tenant_schema
from public.tenant_schema_mappings
loop
execute format($ex$
WITH deleted AS (
delete from %I.parent
where expiration_date_time < now()
IS TRUE RETURNING *
)
tsname := tenant;
amount := (SELECT * FROM deleted;);
return next;
$ex$, tenant);
end loop;
END
$BODY$ language plpgsql;
This is probably wrong in all kinds of ways. I'm definitely confused.
When executing this with SELECT * FROM testfun()
, I get the following error:
ERROR: syntax error at or near "tsname"
LINE 7: tsname := tenant;
^
QUERY:
WITH deleted AS (
delete from anhbawys.parent
where expiration_date_time < now()
IS TRUE RETURNING *
)
tsname := tenant;
amount := (SELECT * FROM deleted;);
return next;
CONTEXT: PL/pgSQL function testfun() line 9 at EXECUTE
SQL state: 42601
So clearly I'm not properly assigning the row's columns, but I'm not sure how.
I have found this question which seemed similar, but it's bit complex for my understanding.
CodePudding user response:
You can use GET DIAGNOSTICS after a DELETE statement to get the number of rows deleted:
CREATE OR REPLACE FUNCTION testfun()
RETURNS TABLE(tsname varchar, amount bigint) AS
$BODY$
declare
tenant text;
BEGIN
for tenant in
select tenant_schema
from tenant_schema_mappings
loop
execute format(
'delete from %I.parent
where expiration_date_time < now()', tenant);
tsname := tenant;
GET DIAGNOSTICS amount := ROW_COUNT;
return next;
end loop;
END
$BODY$
language plpgsql;
CodePudding user response:
If the answer is as simple as your question there is a system catalog for this.
select schemaname , count(n_tup_del)
from pg_catalog.pg_stat_all_tables psat
group by schemaname
You can use get diagnostics (noddy function to get my point across)
create or replace function delfunc()
returns void
as $$
declare
affected_rows int ;
begin
delete from atable where a > 998 ;
GET DIAGNOSTICS affected_rows = ROW_COUNT;
insert into logtable values(affected_rows);
end $$
language plpgsql