So you want to use pipelined table functions and cursor_sharing in 10.1.0. Check this out…
First create this test package:
CREATE OR REPLACE PACKAGE ptf_test AS TYPE t_ptf_row IS RECORD ( dummy dual.dummy%TYPE ); TYPE t_ptf_tab IS TABLE OF t_ptf_row; FUNCTION get_data_1 RETURN t_ptf_tab PIPELINED; FUNCTION get_data_2 (p_in IN VARCHAR2) RETURN t_ptf_tab PIPELINED; END; / SHOW ERRORS CREATE OR REPLACE PACKAGE BODY ptf_test AS FUNCTION get_data_1 RETURN t_ptf_tab PIPELINED AS l_row t_ptf_row; BEGIN SELECT dummy INTO l_row FROM dual; PIPE ROW(l_row); RETURN; END; FUNCTION get_data_2 (p_in IN VARCHAR2) RETURN t_ptf_tab PIPELINED AS l_row t_ptf_row; BEGIN SELECT dummy INTO l_row FROM dual; PIPE ROW(l_row); RETURN; END; END; / SHOW ERRORS
Then turn on cursor_sharing and query the pipelined table functions:
SQL> ALTER SESSION SET CURSOR_SHARING=SIMILAR; Session altered. SQL> SELECT * 2 FROM TABLE(ptf_test.get_data_1); D - X 1 row selected. SQL> SELECT * 2 FROM TABLE(ptf_test.get_data_2('x')); FROM TABLE(ptf_test.get_data_2('x')) * ERROR at line 2: ORA-22905: cannot access rows from a non-nested table item SQL>
Now turn it off and try again:
SQL> ALTER SESSION SET CURSOR_SHARING=EXACT; Session altered. sys@db10g> SELECT * 2 FROM TABLE(ptf_test.get_data_1); D - X 1 row selected. SQL> SELECT * 2 FROM TABLE(ptf_test.get_data_2('x')); D - X 1 row selected. SQL>
So you can’t use cursor_sharing and pipelined table functions with parameters together. It took me a while to figure out the problem, but when I did it wasn’t long before support came back with an unfixed bug relating to it (Bug 4178323).
The solution? Don’t use cursor_sharing ๐
Cheers
Tim…
Note. Script changed to use ALTER SESSION to prevent anyone leaving their test instance in an dodgy state. Thanks for the heads-up Gary ๐
If you use object types (i don’t like the plsql types – they just create “fake” object types that make people go “what is this type in my dictionary”), you can solve this with CAST as well:
ops$tkyte@ORA10G> create or replace type myscalarType as object ( dummy varchar2(1) )
2 /
Type created.
ops$tkyte@ORA10G> create or replace type myArrayType as table of myScalarType
2 /
Type created.
ops$tkyte@ORA10G>
ops$tkyte@ORA10G>
ops$tkyte@ORA10G> CREATE OR REPLACE PACKAGE ptf_test AS
2 FUNCTION get_data_1
3 RETURN myArrayType PIPELINED;
4
5 FUNCTION get_data_2 (p_in IN VARCHAR2)
6 RETURN myArrayType PIPELINED;
7
8 END;
9 /
Package created.
ops$tkyte@ORA10G> SHOW ERRORS
No errors.
ops$tkyte@ORA10G>
ops$tkyte@ORA10G> CREATE OR REPLACE PACKAGE BODY ptf_test AS
2 FUNCTION get_data_1
3 RETURN myArrayType PIPELINED
4 AS
5 l_row dual%rowtype;
6 BEGIN
7 SELECT dummy
8 INTO l_row
9 FROM dual;
10
11 PIPE ROW( myScalarType( l_row.dummy ) );
12 RETURN;
13 END;
14
15 FUNCTION get_data_2 (p_in IN VARCHAR2)
16 RETURN myArrayType PIPELINED
17 AS
18 l_row dual%rowtype;
19 BEGIN
20 SELECT dummy
21 INTO l_row
22 FROM dual;
23
24 PIPE ROW( myScalarType( l_row.dummy ) );
25 RETURN;
26 END;
27 END;
28 /
Package body created.
ops$tkyte@ORA10G> SHOW ERRORS
No errors.
ops$tkyte@ORA10G>
ops$tkyte@ORA10G>
ops$tkyte@ORA10G> ALTER SYSTEM SET CURSOR_SHARING=SIMILAR;
System altered.
ops$tkyte@ORA10G>
ops$tkyte@ORA10G> SELECT * FROM TABLE(ptf_test.get_data_1);
D
–
X
ops$tkyte@ORA10G> SELECT * FROM TABLE(ptf_test.get_data_2(‘x’));
SELECT * FROM TABLE(ptf_test.get_data_2(‘x’))
*
ERROR at line 1:
ORA-22905: cannot access rows from a non-nested table item
ops$tkyte@ORA10G> SELECT * FROM TABLE(cast( ptf_test.get_data_2(‘x’) as myArrayType ) );
D
–
X
I quite like the PL/SQL way of doing it. It’s nice to have the type definition in with the code.
I agree, the naming convention sucks though.
Cheers
Tim…
Error is in 9iR2 as well.
But your test script would have been a bit safer with
ALTER Session SET CURSOR_SHARING=SIMILAR;
rather than
ALTER SYSTEM SET CURSOR_SHARING=SIMILAR;
Gary — am I glad I came back to read any followups ๐
I would have been banging my head soon trying to figure out “what the heck is up” on my test box ๐
Doh – alter system, gotta read those scripts a little closer.
Now you know why I never test anything in asktom (the database).
Gary: I’ve changed the post to use ALTER SESSION as suggested. Thanks for the heads-up!
Cheers
Tim…