Here's a solution. For simplicity I considered that your report function would return a table with the name and quantity fields.
Solution link working in SQL Feedle: link
1) Create an object type that contains a representation of the columns of the table to be returned by its function.
create or replace type t_linhas as object (
nome varchar2(30),
quantidade number
);
/
2) Create a table type. Note below that the table is made up of the t_lines type that has just been created.
create or replace type t_tabela_relatorio as table of t_linhas;
/
3) Create the function returning the t_table_type that was created at startup
create or replace function fc_relatorio return t_tabela_relatorio as
v_ret t_tabela_relatorio;
cursor c_consulta_base_relatorio is
select 'Joao' as nome_cliente, 10 as qtd from dual union
select 'Pedro' as nome_cilente, 20 as qtd from dual union
select 'Isabel' as nome_ciente, 15 as qtd from dual;
begin
v_ret := t_tabela_relatorio();
for x in c_consulta_base_relatorio loop
v_ret.extend;
v_ret(v_ret.count) := t_linhas(x.nome_cliente,x.qtd);
end loop;
return v_ret;
end fc_relatorio;
/
3) Example of how to call the function:
SELECT * FROM TABLE(FC_RELATORIO())
Source: link