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;
/
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'.
PL/SQL has three collection types—associative array, VARRAY (variable-size array), and nested table.
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.
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;
/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With