動的実行ワークフロー

動的MLE実行に必要なステップについて説明します。

ユーザーがDBMS_MLEを使用してJavaScriptコードを作成および実行できるようにするには、複数の権限を付与する必要があります。必要な権限の詳細は、「MLEでのJavaScriptの操作に必要なシステム権限およびオブジェクト権限」を参照してください。

DBMS_MLEを使用したJavaScriptコードの実行ワークフローは次のとおりです:
  1. 実行コンテキストを作成します
  2. VARCHAR2変数またはCLOB変数を使用してJavaScriptコードを指定します
  3. 必要に応じてPL/SQLエンジンとMLEエンジンの間で変数を渡して、コードを実行します
  4. 実行コンテキストのクローズ

コードと同様に、予期しない状況に対処することが業界のベスト・プラクティスとされています。これは、標準のJavaScript例外処理機能を使用してJavaScriptコード自体で行うか、またはPL/SQLで行うことができます。

トピック

インラインでのJavaScriptコードの指定

引用演算子の使用は、動的実行の実行時にJavaScriptコードをインラインで提供するために推奨される方法です。

引用演算子(通常はq-quote演算子と呼ばれる)は、JavaScriptコードをPL/SQLブロック内に直接埋め込むことでロードするために使用できるオプションの1つです。PL/SQLコードにインラインでJavaScriptコードを指定する場合、可能なときには常にこの代替の引用演算子を使用することをお薦めします。

q-quote演算子は動的実行の推奨メソッドですが、インライン・コール仕様を使用するときは、{{...}}などのデリミタを使用してJavaScriptコードを囲むことに注意してください。これらのデリミタ・オプションについてさらに学習するには、「インラインMLEコール仕様の作成」を参照してください。

例4-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およびラージ・オブジェクト開発者ガイド』を参照してください

例4-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
場合によっては、例4-3に示すように、動的MLE実行を、データベースに保持されているMLEモジュールと混在させる必要があります。

例4-3 DBMS_MLEからのMLEモジュールの参照によるBFILEからのJavaScriptコードのロード

例4-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コードを指定するための追加オプション」を参照してください