Oracle(11g) ベースのアプリケーションでは、パイプライン関数を多用しています。以下の (簡略化された) 例に示すように、このような関数からのエラー報告は難しいことがわかりました。プロシージャは Java から呼び出されるように存在し、PL/SQL の実行中にどこかで発生したエラーを受け取ります。
オラクルの部分:
set serveroutput on
create table dummy (id NUMBER);
create or replace package mytest
as
type t_rec is record (id integer);
type t_tab is table of t_rec;
type t_ref_cur IS REF CURSOR RETURN t_rec;
function foo
return t_tab pipelined;
procedure bar( p_ref_cur out t_ref_cur);
end mytest;
/
show errors
create or replace package body mytest
as
function foo
return t_tab pipelined
is
v_cur SYS_REFCURSOR;
v_sql varchar2(2000);
v_rec t_rec;
begin
v_sql := 'select wrong_column from DUMMY';
open v_cur for v_sql;
loop
fetch v_cur into v_rec;
exit when v_cur%notfound;
pipe row (v_rec);
end loop;
exception
when no_data_needed then
null;
when others then
dbms_output.put_line(SQLCODE||' '||sqlerrm );
raise no_data_found;
end foo;
procedure bar( p_ref_cur out t_ref_cur)
is
begin
open p_ref_cur for select * from table(foo);
end bar;
end mytest;
/
show errors
-- call procedure bar() from pl/sql
set serveroutput on
declare v_ref_cur mytest.t_ref_cur;
v_rec mytest.t_rec;
begin
mytest.bar(v_ref_cur);
loop
fetch v_ref_cur into v_rec;
exit when v_ref_cur%notfound;
dbms_output.put_line(v_rec.id);
end loop;
end;
/
show errors
上記の関数を実行すると、例外が表示されます。
ORA-00904: "WRONG_COLUMN": invalid column name
Java 部分:
package test1;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import oracle.jdbc.OracleTypes;
public class start {
public static void main(String[] args)
{
try
{
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@...", "…", "…");
CallableStatement stmt = con.prepareCall("BEGIN mytest.bar(?); END;");
stmt.registerOutParameter(1, OracleTypes.CURSOR);
stmt.executeQuery();
ResultSet rs = (ResultSet)stmt.getObject(1);
while (rs.next())
{
System.out.println(rs.getInt(1));
}
stmt.close();
con.close();
} catch (Exception e)
{
e.printStackTrace();
}
}
}
例外はキャッチされません。結果セットが空です。
これは予想される動作ですか?私たちは何か間違ったことをしていますか?回避策はありますか?