3

I have a package with 2 pipelined functions. When I'm trying to call one function with another function as it's argument I'm getting "ORA-06553: PLS-306: wrong number or types of arguments in call" error.

Here is the package:

create or replace NONEDITIONABLE TYPE RESULTING_RECORD_RT as object
   (
          CALENDAR  NVARCHAR2(1024), 
          PRODUCT   NVARCHAR2(1024), 
          MEASURE   NVARCHAR2(1024), 
          VALUE     NUMBER
   );
/
create or replace NONEDITIONABLE TYPE RESULTING_COLS_RT IS TABLE OF RESULTING_RECORD_RT;
/
create or replace package pipe_pkg as
function pipe_func_emp return RESULTING_COLS_RT PIPELINED;
function pipe_func_emp2(input_Set IN resulting_cols_rt) return RESULTING_COLS_RT PIPELINED;
end;
/
create or replace package body pipe_pkg as
function pipe_func_emp return RESULTING_COLS_RT
PIPELINED
is
    test_tbl resulting_cols_rt:= resulting_cols_rt();
begin
    test_tbl.extend;
    test_tbl(1):=resulting_record_rt('A','B','C',1);
    test_tbl.extend;
    test_tbl(2):=resulting_record_rt('A','B','D',2);
    PIPE ROW(test_tbl(1));
    PIPE ROW(test_tbl(2));
    return;
end;
function pipe_func_emp2(input_Set IN resulting_cols_rt) return RESULTING_COLS_RT
PIPELINED
is
    v_tmp NVARCHAR2(10240);
    l_res SYS_REFCURSOR;
    recs resulting_record_rt;
begin
    open l_res for select * from table(input_Set);
    loop
        fetch l_res into recs;
        PIPE ROW(recs);
        exit when l_res%notfound;
    end loop;
    close l_res;
    return;
end;
end;
/

I'm calling the functions as follows:

select * from TABLE(pipe_pkg.pipe_func_emp2(CURSOR(select * from TABLE(pipe_pkg.pipe_func_emp()))));

And the call throws error:

ORA-06553: PLS-306: wrong number or types of arguments in call to 'PIPE_FUNC_EMP2'
06553. 00000 -  "PLS-%s: %s"

What am I doing wrong?

0xdb
  • 3,539
  • 1
  • 21
  • 37
brungel
  • 33
  • 4

1 Answers1

4

The function pipe_func_emp2 expected RESULTING_COLS_RT as it's argument, but got REF CURSOR. These are incompatible types.

Try following reproducible example of a chaining of the pipelined functions:

create or replace type somerow  as object (id int, val varchar2 (8))
/
create or replace type sometab is table of somerow
/
create or replace package pack as
    function func1 return sometab pipelined;
    function func2 (cur sys_refcursor) return sometab pipelined;
end;
/
create or replace package body pack as
    function func1 return sometab pipelined is
        tab sometab := sometab (somerow (1,'AAA'), somerow (2,'BBB'));
    begin
        for i in 1..tab.count loop 
            pipe row (tab(i)); 
        end loop;
        return;
    end;
    function func2 (cur sys_refcursor) return sometab pipelined is
        sr somerow;
    begin
        loop
            fetch cur into sr;
            exit when cur%notfound;
            pipe row (sr);
        end loop;
        close cur;
        return;
    end;
end;
/

The query and it's outcome:

select * 
from table (pack.func2 (
    cursor (select value (p) from table (pack.func1()) p )))
/

        ID VAL     
---------- --------
         1 AAA     
         2 BBB     
0xdb
  • 3,539
  • 1
  • 21
  • 37
  • Nice. I tried to make this work on the example of the Question and I couldn't make it happen. Any reason why you didn't make you example based on that? – Scratte May 04 '21 at 21:29
  • Thanks. I got the same result with two identical rows with the value 2. – Scratte May 04 '21 at 21:49
  • Never mind. `EXIT WHEN cur%NOTFOUND;` just needs to be moved up a line.. ;) Talking about spending time on a typo :D – Scratte May 04 '21 at 22:01
  • @Scratte Sorry, typo [fixed on db<>fiddle](https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c7b72adec14760454d43d315c89f32d0). The code in the example above is correct. – 0xdb May 04 '21 at 22:08
  • No need to be sorry. I made the exact same typo in my own example ;) – Scratte May 04 '21 at 22:12
  • 1
    The same error in the OP's example, I didn't keep track of it ;) – 0xdb May 04 '21 at 22:16
  • Thank you @0xdb! So, it should receive REF CURSOR as an argument instead of the object type and in the query, "*" should be replaced with VALUE function. Is there a way to make it work with the object type as an argument and not REF CURSOR? – brungel May 05 '21 at 08:00
  • 1
    @brungel Yes, it's possible (see [first revision of my answer](https://stackoverflow.com/revisions/67389699/1)). I changed it because select full table contents makes almost no sense with pipelined functions. – 0xdb May 05 '21 at 08:17