MLEでのJavaScriptモジュールの使用
JavaScriptモジュールは、様々な方法で使用でき、一連のデータ定義言語(DDL)コマンドを使用して管理できます。
MLEモジュールで提供されているJavaScriptコードは、次の方法で使用できます:
-
MLEモジュールによってエクスポートされたJavaScriptファンクションは、MLEモジュール・コールと呼ばれるコール仕様を作成することで公開できます。これにより、SQLおよびPL/SQLからファンクションを直接コールできます。
-
JavaScript MLEモジュールによってエクスポートされた機能は、他のMLE JavaScriptモジュールにインポートできます。
-
DBMS_MLE
のコード・スニペットは、JavaScriptの動的起動用のモジュールをインポートできます。
ユーザーがMLEモジュールを作成および実行できるようにするには、複数の権限を付与する必要があります。
関連項目:
-
モジュール・コールの詳細は、「MLE JavaScriptモジュールのインポートの概要」を参照してください
-
DBMS_MLE
およびデータベースでのJavaScriptコードの動的起動の詳細は、「動的MLE実行の概要」を参照してください -
MLE固有の権限の詳細は、「MLEでのJavaScriptの操作に必要なシステム権限およびオブジェクト権限」を参照してください
トピック
- データベースでのJavaScriptモジュールの管理
必要な権限がある場合は、SQLでMLEモジュールをスキーマ・オブジェクトとして作成できます。 - MLEモジュール・コール用のJavaScriptコードの準備
MLEのJavaScriptモジュールは、モジュール用のECMAScript 6標準に従います。MLEモジュールのユーザーが使用すると予想されるファンクションと変数をエクスポートする必要があります。 - MLEにJavaScriptコードを提供するための追加オプション
MLEモジュールのJavaScriptソース・コードは、PL/SQLを使用してインラインで指定できますが、BFILE、BLOBまたはCLOBを使用して指定することもできます。この場合、ソース・ファイルはUTF8でエンコードする必要があります。 - モジュール・バージョン情報の指定およびJSONメタデータの指定
MLEモジュールでは、オプションのメタデータをバージョン文字列および自由形式のJSON値メタデータの形式で保持できます。 - JavaScriptモジュールの削除
DROP MLE MODULE
DDL文を使用して、MLEモジュールを削除します。 - JavaScriptモジュールの変更
MLEモジュールの属性は、ALTER MLE MODULE
文を使用して割当てまたは変更できます。 - 組込みJavaScriptモジュールの概要
MLEには、任意の実行コンテキストでインポートできる一連の組込みJavaScriptモジュールが用意されています。 - MLE JavaScriptモジュールに関連するディクショナリ・ビュー
データ・ディクショナリには、JavaScriptモジュールの詳細が含まれています。
親トピック: MLE JavaScriptモジュールおよび環境
データベースでのJavaScriptモジュールの管理
必要な権限がある場合は、SQLでMLEモジュールをスキーマ・オブジェクトとして作成できます。
独自のスキーマでMLEモジュールを作成または置換するには、少なくともCREATE MLE MODULE
権限が必要です。また、ターゲットのJavaScript言語オブジェクトに対する実行権限も必要です。
関連項目:
-
MLE固有の権限の詳細は、「MLEでのJavaScriptの操作に必要なシステム権限およびオブジェクト権限」を参照してください
-
Oracle Databaseの権限およびロールの詳細は、『Oracle Databaseセキュリティ・ガイド』を参照してください
トピック
- JavaScriptモジュールの名前付け
各JavaScriptモジュールの名前は、それが作成されるスキーマ内で一意である必要があります。完全修飾名が使用されないかぎり、現在のユーザーのスキーマが使用されます。 - データベースでのJavaScriptモジュールの作成
JavaScriptモジュールは、CREATE MLE MODULE
DDL文を使用して、MLEモジュールの名前とソース・コードを指定してデータベースに作成されます。 - シングルバイト文字セットの使用によるデータベースでのJavaScriptコードの格納
文字セット標準と、MLEでシングルバイト文字セットを使用する際の注意事項です。 - コード分析
JavaScript構文エラーには、MLEモジュールの作成時にフラグが付けられますが、CREATE MLE MODULE
コマンドを実行する前に、選択したlintツールを使用して分析を実行してください。
親トピック: MLEでのJavaScriptモジュールの使用
JavaScriptモジュールの名前付け
各JavaScriptモジュールの名前は、それが作成されるスキーマ内で一意である必要があります。完全修飾名が使用されないかぎり、現在のユーザーのスキーマが使用されます。
他のスキーマ・オブジェクト識別子と同様に、二重引用符で囲まれたモジュール名は大/小文字が区別されます。引用符で囲まれていない場合、名前は暗黙的に大文字に変換されます。
一意の名前を選択する場合、MLEオブジェクトは、表、ビュー、マテリアライズド・ビュー、順序、プライベート・シノニム、PL/SQLパッケージ、ファンクション、プロシージャおよびキャッシュ・グループとネームスペースを共有することに注意してください。
親トピック: データベースでのJavaScriptモジュールの管理
データベースでのJavaScriptモジュールの作成
JavaScriptモジュールは、CREATE MLE MODULE
DDL文を使用して、MLEモジュールの名前とソース・コードを指定してデータベースに作成されます。
MLEモジュールが作成されるとすぐに、データベース・ディクショナリに保持されます。これは、DBMS_MLE
を使用したJavaScriptコードの動的実行と比較した場合の違いの1つです。
指定された名前のMLEモジュールがすでに存在する場合、CREATE MLE MODULE
(OR REPLACE
句なし)はエラーをスローします。CREATE OR REPLACE MLE MODULE
では、既存のモジュールが存在する場合は置換され、存在しない場合は新しいモジュールが作成されます。MLEモジュールが置換される場合、そのモジュールに対する権限を再付与する必要はありません。
PL/SQLの知識のある方は、これがPL/SQLプログラム・ユニットの動作とまったく同じであることに注意してください。
モジュール名がすでに使用されている場合に既存のモジュールを置換しない場合は、CREATE OR REPLACE
ではなくIF NOT EXISTS
句を使用できます。このバリエーションの構文を例3-1に示します。IF NOT EXISTS
句とOR REPLACE
句は相互に排他的です。
関連項目:
-
完全な
CREATE MLE MODULE
構文は、『Oracle Database SQL言語リファレンス』を参照してください -
IF
[NOT
]EXISTS
構文の使用の詳細は、『Oracle Database開発ガイド』を参照してください。
例3-1 データベースでのJavaScriptモジュールの作成
この例は、MLEモジュールの作成および単純なJavaScriptファンクションのエクスポートを示しています。
CREATE MLE MODULE IF NOT EXISTS po_module LANGUAGE JAVASCRIPT AS
/**
* get the value of all line items in an order
* @param {array} lineItems - all the line items in a purchase order
* @returns {number} the total value of all line items in a purchase order
*/
export function orderValue(lineItems) {
return lineItems
.map( x => x.Part.UnitPrice * x.Quantity )
.reduce(
(accumulator, currentValue) => accumulator + currentValue, 0
);
}
/
このコード・ブロックの最初の行は、JavaScriptモジュール名をpo_module
として指定しています。残りの行は、実際のJavaScriptコードを定義します。ECMAScript標準に従い、exportキーワードは、モジュールの潜在的なコール元にエクスポートされるファンクションを示すことに注意してください。MLEは、ECMAScript 2023標準に準拠したコードを受け入れます。
親トピック: データベースでのJavaScriptモジュールの管理
シングルバイト文字セットの使用によるデータベースでのJavaScriptコードの格納
文字セット標準と、MLEでシングルバイト文字セットを使用する際の注意事項。
JavaScriptはUnicodeでエンコードされます。Unicode規格は、世界中で話されているほとんどの言語のあらゆる文字を定義する文字コード・システムです。これは、他の文字セット・エンコーディングの制限事項を克服するために開発されました。
データベースの作成には、AL32UTF8文字セットを使用することをお薦めします。データベースでAL32UTF8文字セットを使用すると、最新バージョンのUnicode標準が確実に使用され、文字セット変換エラーの可能性が最小限に抑えられます。
データベースで依然としてUS7ASCII、WE8ISO8859-n、WE8MSWIN1252などのシングルバイト文字セットが使用されている場合は、MLE JavaScriptコードでUnicode機能を使用しないように注意する必要があります。このことは、そのようなデータベースで他のタイプの入力データを処理する場合と変わりありません。
関連項目:
Unicode標準の詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください
親トピック: データベースでのJavaScriptモジュールの管理
コード分析
JavaScript構文エラーには、MLEモジュールの作成時にフラグが付けられますが、CREATE MLE MODULE
コマンドを実行する前に、選択したlintツールを使用して分析を実行してください。
MLEモジュールをデータベースに作成する場合は、他のJavaScriptプロジェクトを制御するのと同じ方法で、十分に確立されたツールチェーンを使用する必要があります。この意味では、CREATE MLE MODULE
のコールは、サーバー・アプリケーションのデプロイと同様に、デプロイメント・ステップとみなすことができます。コード・チェックは、デプロイの前に、継続的インテグレーション/継続的デプロイメント(CI/CD)パイプラインなどによって、ビルド・ステップ中に実行する必要があります。
JavaScriptコードに構文エラーを含むCREATE MLE MODULE
を使用してモジュールを作成すると、そのモジュールは作成されますが、無効な状態になります。このチェックはモジュール内で呼び出されたSQL文には適用されないため、コードが期待どおりに機能するように個別のテストを実行する必要があります。
コードをソース・コード・リポジトリにチェックインする前に、linterと呼ばれるツールでコードを処理することは、業界のベスト・プラクティスとみなされています。他の開発プロジェクトと同様に、自分自身とチームにとって最適なオプションを自由に選択できます。考えられるオプションには、ESLint、JSHint、JSLint、および静的コード分析を実行して構文エラー、バグ、その他の問題のあるコードにフラグを付けるものがあります。また、これらを使用して特定のコーディング・スタイルを適用することもできます。多くの統合開発環境(IDE)では組込み機能としてlintが提供され、ファイルがディスクに保存されるとすぐにこのツールを起動して、問題にフラグを付けます。
lintの動的実行に加えて、高度に自動化されたDevOps環境を使用してコード分析を自動化し、ビルド・パイプラインの一部としてlintを起動できます。通常、このステップは、JavaScriptモジュールをデータベースに送信する前に発生します。
この目的は、実行時に問題が発生する前に、できるだけ多くの潜在的な問題を検出することです。ユニット・テストはこれらのリスクをさらに軽減するために役立ち、開発プロセスへのユニット・テストの組込みは業界のベスト・プラクティスになっています。どの方法を選択しても、JavaScriptモジュールをデータベースに送信する前に、コード分析ステップが発生します。
親トピック: データベースでのJavaScriptモジュールの管理
MLEモジュール・コール用のJavaScriptコードの準備
MLEのJavaScriptモジュールは、モジュール用のECMAScript 6標準に従います。MLEモジュールのユーザーが使用すると予想されるファンクションと変数をエクスポートする必要があります。
エクスポートされない変数およびファンクションは、モジュール内でプライベートとみなされます。例3-3は、MLE JavaScriptモジュールでのパブリック・ファンクションとプライベート・ファンクションの両方の使用を示しています。
ECMAScriptモジュールは、インポート文または動的インポート・コールを使用して、他のECMAScriptモジュールをインポートできます。この機能は、MLEにもあります。MLE環境では、MLEモジュールを補完するメタデータが提供されます。
MLEのコンソール出力は、コンソール・オブジェクトを使用することで容易になることに注意してください。デフォルトでは、console.log()
に書き込まれたものはすべてDBMS_OUTPUT
にルーティングされ、最終的に画面に表示されます。
例3-1のようなJavaScriptコードは、コール仕様なしでSQLまたはPL/SQLからアクセスすることはできません。コール仕様は、PL/SQLプログラム・ユニット(ファンクション、プロシージャまたはパッケージ)と考えることができます。ここで、例3-2に示すように、そのPL/SQL本体がJavaScriptモジュールおよびファンクションへの参照に置き換えられます。コール仕様の詳細は、「MLE JavaScriptファンクション」を参照してください。
関連項目:
例3-2 パブリック・ファンクションのコール仕様の作成
この例では、例3-1で作成したモジュールpo_module
を使用します。po_module
でエクスポートされる唯一のファンクションであるorderValue()
のコール仕様は、次のように記述できます:
CREATE OR REPLACE FUNCTION order_value(
p_line_items JSON
) RETURN NUMBER AS
MLE MODULE po_module
SIGNATURE 'orderValue';
/
ファンクションを作成すると、特定の購買オーダーの値を計算できます:
SELECT
po.po_document.PONumber,
order_value(po.po_document.LineItems[*]) order_value
FROM
j_purchaseorder po;
結果:
PONUMBER ORDER_VALUE
---------- -----------
1600 279.3
672 359.5
例3-3 JavaScriptモジュールのパブリック・ファンクションとプライベート・ファンクション
パブリック(エクスポート済)ファンクションに加えて、モジュールにプライベートなファンクションを追加できます。この例では、値の計算はmap()
ファンクションから取り出され、別のファンクションに移動されます(リファクタリング)。
次のコードの最初のファンクションlineItemValue()
はプライベートとみなされ、2番目のファンクションorderValue()
はパブリックです。exportキーワードは、このコード・リストの最後に指定されていますが、例3-1に示すように、変数およびファンクションの接頭辞として出現することもあります。どちらのバリエーションも有効なJavaScript構文です。
CREATE OR REPLACE MLE MODULE po_module LANGUAGE JAVASCRIPT AS
/**
* calculate the value of a given line item. Factored out of the public
* function to allow for currency conversions in a later step
* @param {number} unitPrice - the price of a single article
* @param {number} quantity - the quantity of articles ordered
* @returns {number} the monetary value of the line item
*/
function lineItemValue(unitPrice, quantity) {
return unitPrice * quantity;
}
/**
* get the value of all line items in an order
* @param {array} lineItems - all the line items in a purchase order
* @returns {number} the total value of all line items in a purchase order
*/
function orderValue(lineItems) {
return lineItems
.map( x => lineItemValue(x.Part.UnitPrice, x.Quantity) )
.reduce(
(accumulator, currentValue) => accumulator + currentValue, 0
);
}
export { orderValue }
/
親トピック: MLEでのJavaScriptモジュールの使用
MLEにJavaScriptコードを指定するための追加オプション
MLEモジュールのJavaScriptソース・コードは、PL/SQLを使用してインラインで指定できますが、BFILE、BLOBまたはCLOBを使用して指定することもできます。この場合、ソース・ファイルはUTF8でエンコードする必要があります。
BFILE句を使用してMLEモジュールを作成すると、GoldenGateなどの論理レプリケーションで問題が発生する可能性があります。DDLコマンドがターゲット・データベースで成功するには、ターゲット・データベースに同じディレクトリが存在する必要があります。さらに、このディレクトリに同じJavaScriptファイルが存在する必要があります。これらの条件が満たされないと、ターゲット・データベースでMLEモジュールを作成するコールが失敗します。
BFILEを使用するかわりに、BLOBまたはCLOBを使用して、MLEモジュールを作成することもできます。例3-5に、CLOBを使用してJavaScriptモジュールを作成する方法を示します。BLOBを使用する場合、構文は同じですが、BLOBの値はCLOBの値とは異なります。
例3-4 BFILEを使用したJavaScriptソース・コードの指定
この例では、JS_SRC_DIR
は、myJavaScriptModule.js
というファイルにモジュールのソース・コードを含むローカル・ファイル・システム上の場所にマッピングするデータベース・ディレクトリ・オブジェクトです。ディレクトリの場所からファイルをロードすると、MLEはソース・コードをディクショナリに格納します。それ以降MLEモジュールをコールしても、ソース・コードがディスクからリフレッシュされることはありません。myJavaScriptModule.js
に新しいバージョンのモジュールが格納されている場合は、別のCREATE OR REPLACE MLE MODULE
のコールを使用してデプロイする必要があります。
CREATE MLE MODULE mod_from_bfile
LANGUAGE JAVASCRIPT
USING BFILE(JS_SRC_DIR,'myJavaScriptModule.js');
/
例3-5 CLOBを使用したJavaScriptソース・コードの指定
CREATE OR REPLACE MLE MODULE mod_from_clob_inline
LANGUAGE JAVASCRIPT USING CLOB (
SELECT q'~
export function clob_hello(who){
return `hello, ${who}`;
}
~')
/
別の方法として、表に格納されているJavaScriptソース・コードを使用することもできます。このバリエーションの例では、スキーマに、src
列のJavaScriptソース・コードを含むjavascript_src
という名前の表と、追加のメタデータがあると想定しています。次の文は、CLOBをフェッチしてモジュールを作成します。
CREATE OR REPLACE MLE MODULE mod_from_clob_table
LANGUAGE JAVASCRIPT USING CLOB (
SELECT src
FROM javascript_src
WHERE
id = 1 AND
commit_hash = 'ac1fd40'
)
/
このようなステージング表は、継続的インテグレーション(CI)パイプラインを使用してJavaScriptコードをデータベースにデプロイする環境にあります。
親トピック: MLEでのJavaScriptモジュールの使用
モジュール・バージョン情報の指定およびJSONメタデータの指定
MLEモジュールでは、オプションのメタデータをバージョン文字列および自由形式のJSON値メタデータの形式で保持できます。
どちらの種類のメタデータも純粋に情報を提供し、MLEの動作には影響しません。これらは、モジュールとともにデータ・ディクショナリに格納されます。
VERSION
フラグは、デプロイされているコードのバージョンに関する内部リマインダとして使用できます。VERSION
フィールドに格納された情報により、開発者および管理者は、バージョン管理システムでコードを識別できます。
JSONメタデータの形式はスキーマにバインドされません。開発者は有用なものや参考になるものを追加できます。MLEモジュールがrollup.js
やwebpackなどのツールで作成されたソースの集合である場合、関連するpackage-lock.json
ファイルをモジュールとともに格納すると便利です。
メタデータ・フィールドを使用して、ソフトウェア部品構成表(SBOM)を作成できます。これにより、セキュリティ・チームおよび管理者は、特にサードパーティ・モジュールが使用されている場合に、デプロイ済パッケージに関する情報を追跡できます。
アップストリーム・リポジトリの依存関係および脆弱性を追跡することにより、セキュリティの脆弱性がレポートされた後に更新が必要なコンポーネントを簡単に識別できます。
関連項目:
- MLE JavaScriptモジュールに関連するディクショナリ・ビュー
- メタデータ・フィールドを使用したSBOMの格納の詳細は、「ソフトウェア部品構成表」を参照してください
例3-6 CREATE MLE MODULEでのVERSION文字列の指定
CREATE OR REPLACE MLE MODULE version_mod
LANGUAGE JAVASCRIPT
VERSION '1.0.0.1.0'
AS
export function sq(num) {
return num * num;
}
/
例3-7 MLEモジュールへのJSONメタデータの追加
この例では、例3-6で作成したモジュールversion_mod
を使用します。
ALTER MLE MODULE version_mod
SET METADATA USING CLOB
(SELECT
'{
"name": "devel",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}'
)
/
親トピック: MLEでのJavaScriptモジュールの使用
JavaScriptモジュールの削除
DROP MLE MODULE
DDL文を使用して、MLEモジュールを削除します。
DROP
文は、削除するモジュールの名前およびオプションでスキーマを指定します。スキーマが指定されていない場合は、現在のユーザーのスキーマとみなされます。
存在しないMLEモジュールを削除しようとすると、エラーがスローされます。これが望ましくない場合は、IF EXISTS
句を使用できます。指定されたMLEモジュールが存在しない場合、DROP MLE MODULE
コマンドは暗黙的にスキップされます。
例3-8 MLEモジュールの削除
DROP MLE MODULE unused_mod;
例3-9 IF EXISTSを使用したMLEモジュールの削除
DROP MLE MODULE IF EXISTS unused_mod;
親トピック: MLEでのJavaScriptモジュールの使用
JavaScriptモジュールの変更
MLEモジュールの属性は、ALTER MLE MODULE
文を使用して割り当てまたは変更できます。
ALTER MLE MODULE
文は、変更するモジュールの名前およびオプションでスキーマを指定します。モジュール名にスキーマの接頭辞が付けられていない場合は、現在のユーザーのスキーマとみなされます。
例3-10 MLEモジュールの変更
ALTER MLE MODULE change_mod
SET METADATA USING CLOB(SELECT'{...}');
親トピック: MLEでのJavaScriptモジュールの使用
組込みJavaScriptモジュールの概要
MLEには、任意の実行コンテキストでインポートできる一連の組込みJavaScriptモジュールが用意されています。
組込みモジュールは、ユーザー定義のMLEモジュールとしてデータベースにデプロイされませんが、MLEランタイムの一部として含まれます。特に、MLEは、次の3つの組込みJavaScriptモジュールを提供します:
-
mle-js-oracledb
は、JavaScript MLE SQLドライバです。 -
mle-js-bindings
は、PL/SQLエンジンから値をインポートおよびエクスポートする機能を提供します。 -
mle-js-plsqltypes
は、PL/SQLラッパー型の定義を提供します。たとえば、PL/SQLをラップするJavaScript型と、OracleNumber
などのSQL型です。 -
mle-js-fetch
には、フェッチAPIポリフィルの一部が提供されており、開発者は外部リソースを起動できます。 -
mle-encode-base64
には、base64でエンコードされたデータを操作するためのコードが含まれます。 mle-js-encodings
は、UTF-8およびUTF-16エンコーディングのテキストを処理する機能を提供します。-
mle-js-plsql-ffi
は、PL/SQLパッケージ、ファンクションおよびプロシージャをJavaScriptオブジェクトとして処理する機能を提供します。
これらのモジュールを使用して、データベースと対話し、JavaScriptエンジンとデータベース・エンジンの間の型変換を提供します。
関連項目:
組込みJavaScriptモジュールの詳細は、サーバー側JavaScript APIのドキュメントを参照してください
親トピック: MLEでのJavaScriptモジュールの使用
MLE JavaScriptモジュールに関連するディクショナリ・ビュー
データ・ディクショナリには、JavaScriptモジュールの詳細が含まれます。
トピック
- USER_SOURCE
各JavaScriptモジュールのソース・コードは、[USER | ALL | DBA | CDB]_SOURCE
ディクショナリ・ビューを使用して外部化されます。 - USER_MLE_MODULES
JavaScript MLEモジュールに関連するメタデータは、[USER | ALL | DBA | CDB]_MLE_MODULES
にあります。
親トピック: MLEでのJavaScriptモジュールの使用
USER_SOURCE
各JavaScriptモジュールのソース・コードは、[USER | ALL | DBA | CDB]_SOURCE
ディクショナリ・ビューを使用して外部化されます。
BFILE演算子を使用してファイル・システムを参照して作成されたモジュールには、モジュールの作成時のコードが表示されます。
*_SOURCE
の詳細は、『Oracle Databaseリファレンス』を参照してください。
例3-11 JavaScriptモジュールのソース・コードの外部化
SELECT
line,
text
FROM
USER_SOURCE
WHERE
name = 'PO_MODULE';
出力例:
LINE TEXT
----- -------------------------------------------------------------
1 /**
2 * calculate the value of a given line item. Factored out of the public
3 * function to allow for currency conversions in a later step
4 * @param {number} unitPrice - the price of a single article
5 * @param {number} quantity - the quantity of articles ordered
6 * @returns {number} the monetary value of the line item
7 */
8 function lineItemValue(unitPrice, quantity) {
9 return unitPrice * quantity;
10 }
11
12
13 /**
14 * get the value of all line items in an order
15 * @param {array} lineItems - all the line items in a purchase order
16 * @returns {number} the total value of all line items in a purchase order
17 */
18 export function orderValue(lineItems) {
19
20 return lineItems
21 .map( x => lineItemValue(x.Part.UnitPrice, x.Quantity) )
22 .reduce(
23 (accumulator, currentValue) => accumulator + currentValue, 0
24 );
25 }
USER_MLE_MODULES
JavaScript MLEモジュールに関連するメタデータは、[USER | ALL | DBA | CDB]_MLE_MODULES
にあります。
指定されたJSONメタデータ、バージョン情報、言語、名前および所有者は、このビューで確認できます。
*_MLE_MODULES
の詳細は、『Oracle Databaseリファレンス』を参照してください。
例3-12 スキーマに定義されているMLEモジュールの検索
SELECT MODULE_NAME, VERSION, METADATA
FROM USER_MLE_MODULES
WHERE LANGUAGE_NAME='JAVASCRIPT'
/
出力例:
MODULE_NAME VERSION METADATA
------------------------------ ---------- -----------
MY_MOD01 1.0.0.1
MY_MOD02 1.0.1.1
MY_MOD03