SQL文のエラー処理
node-oracledb
のようにError
オブジェクトをpromiseまたはコールバックとして戻すのではなく、MLE JavaScriptドライバはエラーのスローを使用します。この概念は、PL/SQL開発者にとって非常になじみ深いものです。
JavaScriptコードでのtry-catch-finallyの使用は、PL/SQL開発者がbegin-exception-endブロックを使用して処理中にエラーを検出する方法に似ています。
例外を再スローする必要がある場合は、JavaScriptのthrow()
コマンドを使用します。これにより、catchブロックで処理された後にエラーがスタックをバブルアップします。例7-14に、この概念を示します。
例7-13 JavaScriptファンクションの内部でのSQLエラー処理
CREATE TABLE log_t (
id NUMBER GENERATED ALWAYS AS IDENTITY
CONSTRAINT pk_log_t PRIMARY KEY,
err VARCHAR2(255),
msg VARCHAR2(255)
);
CREATE OR REPLACE PACKAGE logging_pkg as
PROCEDURE log_err(p_msg VARCHAR2, p_err VARCHAR2);
END logging_pkg;
/
CREATE OR REPLACE PACKAGE BODY logging_pkg AS
PROCEDURE log_err(p_msg VARCHAR2, p_err VARCHAR2)
AS
PRAGMA autonomous_transaction;
BEGIN
INSERT INTO log_t (
err,
msg
) VALUES (
p_err,
p_msg
);
COMMIT;
END log_err;
END logging_pkg;
/
CREATE OR REPLACE MLE MODULE js_err_handle_mod
LANGUAGE JAVASCRIPT AS
/**
*short demo showing how to use try/catch to catch an error
*and proceeding normally. In the example, the error is
*provoked
*/
export function errorHandlingDemo(){
try{
const result = session.execute(
`INSERT INTO
surelyThisTableDoesNotExist
VALUES
(1)`
);
console.log(`there were ${result.rowsAffected} rows inserted`);
} catch(err) {
logError('this is some message', err);
//tell the caller that something went wrong
return false;
}
//further processing
//return successful completion of the code
return true;
}
/**
*log an error using the logging_pkg created at the beginning
*of this example. Think of it as a package logging errors in
*a framework for later analysis.
*@param msg an accompanying message
*@param err the error encountered
*/
function logError(msg, err){
const result = session.execute(
`BEGIN
logging_pkg.log_err(
p_msg => :msg,
p_err => :err
);
END;`,
{
msg: {
val: msg,
dir: oracledb.BIND_IN
},
err: {
val: err.message,
dir: oracledb.BIND_IN
}
}
);
}
/
次のようにモジュールjs_err_handle_mod
を使用して、ファンクションjs_err_handle_mod_f
を作成します:
CREATE OR REPLACE FUNCTION js_err_handle_mod_f
RETURN BOOLEAN
AS MLE MODULE js_err_handle_mod
SIGNATURE 'errorHandlingDemo()';
/
これで、ファンクションをコールし、戻り値を使用して、処理が成功したかどうかを確認できます:
DECLARE
l_success boolean := false;
BEGIN
l_success := js_err_handle_mod_f;
IF l_success THEN
DBMS_OUTPUT.PUT_LINE('normal, successful completion');
ELSE
DBMS_OUTPUT.PUT_LINE('an error has occurred');
END IF;
END;
/
この場合、エラーはMLEモジュール内で捕捉されます。エラーはアプリケーションによって記録されるため、管理者は状況を評価して修正アクションを実行できます。
例7-14 JavaScriptのthrow()コマンドを使用したエラー処理
この例は、catchブロックにおけるJavaScriptのthrow()
コマンドの使用を示しています。例7-13でjs_err_handle_mod
について表示された画面出力とは異なり、コール側のPL/SQLブロックがエラーを捕捉し、それを適宜処理するか、再度生成する必要があります。
CREATE OR REPLACE MLE MODULE js_throw_mod
LANGUAGE JAVASCRIPT AS
/**
*a similar example as Example 7-13, however, rather than
*processing the error in the JavaScript code, it is re-thrown up the call stack.
*It is now up to the called to handle the exception. The try/catch block is not
*strictly necessary but is used in this example as a cleanup step to remove Global
*Temporary Tables (GTTs) and other temporary objects that are no longer required.
*/
export function rethrowError(){
try{
const result = session.execute(
`INSERT INTO
surelyThisTableDoesNotExist
VALUES
(1)`
);
console.log(`there were ${result.rowsAffected} rows inserted`);
} catch(err){
cleanUpBatch();
throw(err);
}
//further processing
}
function cleanUpBatch(){
//batch cleanup operations
return;
}
/
次のコール仕様を使用すると、エラーの捕捉に失敗すると予期しないエラーが発生し、エンド・ユーザーまでコール・スタックを伝播できます。
CREATE OR REPLACE PROCEDURE rethrow_err_proc
AS MLE MODULE js_throw_mod
SIGNATURE 'rethrowError()';
/
BEGIN
rethrow_err_proc;
END;
/
結果:
BEGIN
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-04171: at rethrowError (USER1.JS_THROW_MOD:11:24)
ORA-06512: at "USER1.RETHROW_ERROR_PROC", line 1
ORA-06512: at line 2
エンド・ユーザーに、このタイプのエラーが表示されないようにします。かわりに、よりわかりやすいメッセージを表示します。この例を続けて、単純な修正として例外ブロックを追加します:
BEGIN
rethrow_err_proc;
EXCEPTION
WHEN OTHERS THEN
logging_pkg.log_err(
'something went wrong',
sqlerrm
);
--this would be shown on the user interface;
--for the sake of demonstration this workaround
--is used to show the concept
DBMS_OUTPUT.PUT_LINE(
'ERROR: the process encountered an unexpected error'
);
DBMS_OUTPUT.PUT_LINE(
'please inform the administrator referring to application error 1234'
);
END;
/
結果:
ERROR: the process encountered an unexpected error
please inform the administrator referring to application error 1234
PL/SQL procedure successfully completed.