Debugging long PL/PgSQL function can be a headache because everything is rolled back when an exception is raised « somewhere » within the function and applying all the modifications « by hand » is tedious and error-prone.
One simple way to get some help is by creating a simple « dump » method like so:
create or replace function public.dump(_record record) returns void language plpgsql
as $$
begin
raise info '%', _record;
end;
$$;
select
id,
title,
dump(todo.items.*)
from todo.items;
Thanks Vedran Bilopavlović for the idea (which you can find fully developed here: https://medium.com/@vbilopav/why-i-rely-on-postgresql-functions-for-everything-pros-cons-and-best-practice-article-review-987eba321234)
You can also pass part of a table with named fields like so:
create or replace function public.dump(_record jsonb) returns void language plpgsql
as $$
begin
raise info '%', _record;
end;
$$;
SELECT dump(jsonb_agg(to_jsonb(t)))
FROM thirdparty AS t;
And you can even make it « pretty »:
create or replace function public.dump(_record TEXT) returns void language plpgsql
as $$
begin
raise info '%', _record;
end;
$$;
SELECT dump(jsonb_pretty(jsonb_agg(to_jsonb(t))))
FROM thirdparty AS t;
Bear in mind that these 3 « dump » functions can co-exist and Postgres will use the appropriate one automatically (depending on what parameter type you pass them).