Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Oracle 12 have problems with local collection types in SQL?

To make a long story short I propose to discuss the code you see below.

When running it:

  • Oracle 11 compiler raises

    "PLS-00306: wrong number or types of arguments tips in call to 'PIPE_TABLE'"

    "PLS-00642: Local Collection Types Not Allowed in SQL Statement"

  • Oracle 12 compiles the following package with no such warnings, but we have a surprise in runtime

    when executing the anonymous block as is - everything is fine (we may pipe some rows in the pipe_table function - it doesn't affect)

    now let's uncomment the line with hello; or put there a call to any procedure, and run the changed anonumous block again we get "ORA-22163: left hand and right hand side collections are not of same type"

And the question is: Does Oracle 12 allow local collection types in SQL? If yes then what's wrong with the code of PACKAGE buggy_report?

CREATE OR REPLACE PACKAGE buggy_report IS

  SUBTYPE t_id IS NUMBER(10);
  TYPE t_id_table IS TABLE OF t_id;

  TYPE t_info_rec IS RECORD ( first NUMBER );
  TYPE t_info_table IS TABLE OF t_info_rec;
  TYPE t_info_cur IS REF CURSOR RETURN t_info_rec;

  FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED;

  FUNCTION get_cursor RETURN t_info_cur;

END buggy_report;
/

CREATE OR REPLACE PACKAGE BODY buggy_report IS

  FUNCTION pipe_table(p t_id_table) RETURN t_info_table PIPELINED IS
    l_table t_id_table;
    BEGIN
      l_table := p;
    END;

  FUNCTION get_cursor RETURN t_info_cur IS
    l_table  t_id_table;
    l_result t_info_cur;
    BEGIN

      OPEN l_result FOR SELECT * FROM TABLE (buggy_report.pipe_table(l_table));

      RETURN l_result;
    END;
END;
/

DECLARE
  l_cur buggy_report.t_info_cur;
  l_rec l_cur%ROWTYPE;
  PROCEDURE hello IS BEGIN NULL; END;
BEGIN

  l_cur := buggy_report.get_cursor();

  -- hello;

  LOOP
    FETCH l_cur INTO l_rec;
    EXIT WHEN l_cur%NOTFOUND;
  END LOOP;

  CLOSE l_cur;

  dbms_output.put_line('success');
END;
/
like image 399
diziaq Avatar asked Oct 16 '15 05:10

diziaq


People also ask

What is collections in Oracle PL SQL?

A collection is an ordered group of elements having the same data type. Each element is identified by a unique subscript that represents its position in the collection. We have already discussed varray in the chapter 'PL/SQL arrays'.

How many types of collections are there in Oracle?

PL/SQL has three collection types—associative array, VARRAY (variable-size array), and nested table.

What are the collection methods in Oracle?

A collection method is a built-in function or procedure that operates on collections and is called using dot notation. You can use the methods EXISTS , COUNT , LIMIT , FIRST , LAST , PRIOR , NEXT , EXTEND , TRIM , and DELETE to manage collections whose size is unknown or varies.


1 Answers

In further experiments we found out that problems are even deeper than it's been assumed.

For example, varying elements used in the package buggy_report we can get an ORA-03113: end-of-file on communication channel when running the script (in the question). It can be done with changing the type of t_id_table to VARRAY or TABLE .. INDEX BY ... There are a lot of ways and variations leading us to different exceptions, which are off topic to this post.

The one more interesting thing is that compilation time of buggy_report package specification can take up to 25 seconds, when normally it takes about 0.05 seconds. I can definitely say that it depends on presence of TYPE t_id_table parameter in the pipe_table function declaration, and "long time compilation" happen in 40% of installation cases. So it seems that the problem with local collection types in SQL latently appear during the compilation.

So we see that Oracle 12.1.0.2 obviously have a bug in realization of using local collection types in SQL.

The minimal examples to get ORA-22163 and ORA-03113 are following. There we assume the same buggy_report package as in the question.

-- produces 'ORA-03113: end-of-file on communication channel'
DECLARE   
  l_cur buggy_report.t_info_cur;

  FUNCTION get_it RETURN buggy_report.t_info_cur IS BEGIN RETURN buggy_report.get_cursor(); END;    
BEGIN
   l_cur := get_it();

   dbms_output.put_line('');
END;
/

-- produces 'ORA-22163: left hand and right hand side collections are not of same type'
DECLARE  
  l_cur buggy_report.t_info_cur;

  PROCEDURE hello IS BEGIN NULL; END;
BEGIN
  l_cur := buggy_report.get_cursor;

  -- comment `hello` and exception disappears
  hello;

  CLOSE l_cur;
END;
/
like image 146
diziaq Avatar answered Sep 23 '22 16:09

diziaq