3 動的MLE実行の概要
動的MLE実行を使用すると、開発者はJavaScriptコードをデータベースに保存せずに、DBMS_MLE
パッケージを介してJavaScriptスニペットを起動できます。
DBMS_MLE
パッケージを介してJavaScriptコードのスニペットを起動できます。
関連項目:
-
PL/SQLとJavaScriptの間の値の交換に使用される組込みモジュール
mle-js-bindings
の詳細は、サーバー側JavaScript APIのドキュメントを参照してください -
DBMS_MLE
パッケージの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください
トピック
- 動的JavaScript実行について
開発者は、インラインで、またはDBMS_MLE
を介してファイルをロードすることにより、JavaScriptを動的に実行できます。動的MLE実行では、MLEモジュールを使用するかわりに、JavaScriptを使用してOracle Databaseと対話する別の方法が提供されます。 - 動的実行ワークフロー
動的MLE実行に必要なステップについて説明します。 - 最終実行の結果の戻し
result
引数を使用して、最終実行の結果を取得します。
動的JavaScript実行について
開発者は、インラインで、またはDBMS_MLE
を介してファイルをロードすることにより、JavaScriptを動的に実行できます。動的MLE実行では、MLEモジュールを使用するかわりに、JavaScriptを使用してOracle Databaseと対話する別の方法が提供されます。
DBMS_MLE
パッケージを使用すると、ユーザーはOracle Database内でJavaScriptコードを実行し、PL/SQLとJavaScriptの間でシームレスにデータを交換できます。JavaScriptコード自体は、組込みJavaScriptモジュールを介してPL/SQLを実行できます。JavaScriptデータ型はOracle Databaseデータ型に自動的にマップされ、その逆も同様です。
開発者は、JavaScriptコードをVARCHAR2
変数の値として提供することも、コード量が多い場合はキャラクタ・ラージ・オブジェクト(CLOB)として提供することもできます。JavaScriptコードはDBMS_MLE
パッケージに渡され、そこで評価および実行されます。
DBMS_MLE
がPL/SQLパッケージであることを考慮すると、DBMS_MLE
を使用してコードを動的に実行する場合、たとえば、次のような場合はJavaScriptとPL/SQLが混在します。
-
JavaScriptコードの指定などの設定タスクでは、PL/SQLレイヤーとの対話が必要です
-
JavaScriptコードは、
DBMS_MLE
のファンクションをコールすることで実行されます -
JavaScriptコードの実行が完了した後、発生したエラーがすべてPL/SQLに戻されます。
親トピック: 動的MLE実行の概要
動的実行ワークフロー
動的MLE実行に必要なステップについて説明します。
ユーザーがDBMS_MLE
を使用してJavaScriptコードを作成および実行できるようにするには、複数の権限を付与する必要があります。必要な権限の詳細は、「MLEでのJavaScriptの操作に必要なシステム権限およびオブジェクト権限」を参照してください。
DBMS_MLE
を使用したJavaScriptコードの実行ワークフローは次のとおりです:
- 実行コンテキストを作成します
VARCHAR2
変数またはCLOB変数を使用してJavaScriptコードを指定します- 必要に応じてPL/SQLエンジンとMLEエンジンの間で変数を渡して、コードを実行します
- 実行コンテキストのクローズ
コードと同様に、予期しない状況に対処することが業界のベスト・プラクティスとされています。これは、標準のJavaScript例外処理機能を使用してJavaScriptコード自体で行うか、またはPL/SQLで行うことができます。
トピック
- インラインでのJavaScriptコードの指定
JavaScriptコードをPL/SQLブロックに埋め込むことでインラインで指定する場合にお薦めする方法です。 - ファイルからのJavaScriptコードのロード
BFILE
演算子を使用してCLOBで読み取る方法について説明します。
親トピック: 動的MLE実行の概要
インラインでのJavaScriptコードの指定
JavaScriptコードをPL/SQLブロックに埋め込むことでインラインで指定する場合にお薦めする方法です。
JavaScriptコードをロードする方法の1つは、引用演算子(通常はq-quote演算子と呼ばれる)を使用することです。PL/SQLコードにインラインでJavaScriptコードを指定する場合、可能なときには常にこの代替の引用演算子を使用することをお薦めします。
例3-1 q-quote演算子を使用した、PL/SQLへのJavaScriptコードのインラインでの指定
DECLARE
l_ctx dbms_mle.context_handle_t;
l_snippet CLOB;
BEGIN
l_ctx := dbms_mle.create_context();
l_snippet := q'~
// the q-quote operator allows for much more readable code
console.log(`The use of the q-quote operator`);
console.log(`greatly simplifies provision of code inline`);
~';
dbms_mle.eval(l_ctx, 'JAVASCRIPT', l_snippet);
dbms_mle.drop_context(l_ctx);
EXCEPTION
WHEN OTHERS THEN
dbms_mle.drop_context(l_ctx);
RAISE;
END;
/
結果:
The use of the q-quote operator
greatly simplifies provision of code inline
親トピック: 動的実行ワークフロー
ファイルからのJavaScriptコードのロード
BFILE
演算子を使用してCLOBで読み取る方法について説明します。
linterを使用してコード分析を実行する場合、PL/SQLにインラインでJavaScriptコードを指定することは、動的実行には最適な選択肢ではない可能性があります。JavaScriptコードを提供するもう1つの方法は、BFILE
演算子を使用してCLOBを読み取ることです。この方法では、PL/SQLとJavaScriptコードを明確に分離できます。
関連項目:
ラージ・オブジェクトの詳細は、『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』を参照してください
例3-2 DBMS_LOB.LOADCLOBFROMFILE()を使用した、BFILEからのJavaScriptコードのロード
次の例は、BFILE
およびDBMS_LOB.LOADCLOBFROMFILE()
の使用方法を示しています。
この例では、SRC_CODE_DIR
という名前のディレクトリへの読取りアクセス権があることを想定しています。ソース・コード・ファイルhello_source.js
はそのディレクトリにあります。内容は次のとおりです。
console.log('hello from hello_source');
DECLARE
l_ctx dbms_mle.context_handle_t;
l_js CLOB;
l_srcode_file BFILE;
l_dest_offset INTEGER := 1;
l_src_offset INTEGER := 1;
l_csid INTEGER := dbms_lob.default_csid;
l_lang_context INTEGER := dbms_lob.default_lang_ctx;
l_warn INTEGER := 0;
BEGIN
l_ctx := dbms_mle.create_context();
dbms_lob.createtemporary(lob_loc => l_js, cache => false);
l_srcode_file := bfilename('SRC_CODE_DIR', 'hello_source.js');
IF ( dbms_lob.fileexists(file_loc => l_srcode_file) = 1 ) THEN
dbms_lob.fileopen(file_loc => l_srcode_file);
dbms_lob.loadclobfromfile(
dest_lob => l_js,
src_bfile => l_srcode_file,
amount => dbms_lob.getlength(l_srcode_file),
dest_offset => l_dest_offset,
src_offset => l_src_offset,
bfile_csid => l_csid,
lang_context => l_lang_context,
warning => l_warn
);
IF l_warn = dbms_lob.warn_inconvertible_char THEN
raise_application_error(
-20001,
'the input file contained inconvertible characters'
);
END IF;
dbms_lob.fileclose(l_srcode_file);
dbms_mle.eval(
context_handle => l_ctx,
language_id => 'JAVASCRIPT',
source => l_js
);
dbms_mle.drop_context(l_ctx);
ELSE
raise_application_error(
-20001,
'The input file does not exist'
);
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_mle.drop_context(l_ctx);
RAISE;
END;
/
結果:
hello from hello_source
例3-3 DBMS_MLEからのMLEモジュールの参照によるBFILEからのJavaScriptコードのロード
例3-2に示すように、JavaScriptモジュールのコードはファイルに再度格納されます。この例では、SRC_CODE_DIR
という名前のディレクトリに対する読取りアクセス権があり、ファイル名がgreeting_source.js
であると想定しています。
export function greeting(){
return 'hello from greeting_source';
}
この例では、先行するファイルの内容を使用して、BFILE
からMLEモジュールを作成することから始めます。モジュールをDBMS_MLE
で使用するには、まず環境を作成し、JavaScriptコードの動的部分でモジュールを参照できるようにする必要があります。
動的MLE実行では、ECMAScriptのimport
キーワードは使用できません。かわりに、この例に示すasync/awaitインタフェースを使用してMLEモジュールを動的にインポートする必要があります。
CREATE OR REPLACE MLE MODULE greet_mod
LANGUAGE JAVASCRIPT
USING BFILE(SRC_CODE_DIR, 'greeting_source.js');
/
CREATE OR REPLACE MLE ENV greet_mod_env
imports ('greet_mod' module greet_mod);
DECLARE
l_ctx dbms_mle.context_handle_t;
l_snippet CLOB;
BEGIN
l_ctx := dbms_mle.create_context(
environment => 'GREET_MOD_ENV'
);
l_snippet := q'~
(async () => {
let { greeting } = await import('greet_mod');
const message = greeting();
console.log(message);
})();
~';
dbms_mle.eval(
l_ctx,
'JAVASCRIPT',
l_snippet
);
dbms_mle.drop_context(l_ctx);
EXCEPTION
WHEN OTHERS THEN
dbms_mle.drop_context(l_ctx);
RAISE;
END;
/
結果:
hello from greeting_source
関連項目:
MLEモジュールでBFILE
を使用してJavaScriptコードをロードする方法の詳細は、「MLEにJavaScriptコードを指定するための追加オプション」を参照してください
親トピック: 動的実行ワークフロー
最終実行の結果の戻し
result
引数を使用して、最終実行の結果を取得します。
DBMS_MLE.eval()
プロシージャのバリアントには、追加のCLOB引数result
が使用されます。DBMS_MLE.eval()
をこのようにコールすると、指定された動的MLEスニペット内の最後の文の実行結果が、result
パラメータとして指定されたCLOBに追加されます。
このオプションは、Read-Eval-Print-Loop (REPL)サーバーなどの対話型アプリケーションの実装で、Node.js内の同様のREPLセッションの動作を模倣するために役立ちます。
例3-4 最終実行の結果の戻し
DECLARE
l_ctx dbms_mle.context_handle_t;
l_snippet CLOB;
l_result CLOB;
BEGIN
dbms_lob.createtemporary(
lob_loc => l_result,
cache => false,
dur => dbms_lob.session
);
l_ctx := dbms_mle.create_context();
l_snippet := q'~
let i = 21;
i *= 2;
~';
dbms_mle.eval(
context_handle => l_ctx,
language_id => 'JAVASCRIPT',
source => l_snippet,
result => l_result
);
dbms_output.put_line('result: ' || l_result);
dbms_mle.drop_context(l_ctx);
EXCEPTION
WHEN OTHERS THEN
dbms_mle.drop_context(l_ctx);
RAISE;
END;
/
結果:
result: 42
親トピック: 動的MLE実行の概要