※ 本記事は、Martin Bachによる”Ad-hoc MLE JavaScript in Oracle Database 23c: DBMS_MLE“を翻訳したものです。
2024年4月1日
場合によっては、MLE JavaScriptをアドホック方式で実行することが理にかなっています。通常は、JavaScriptコードをモジュールにラップする前にテストします。この目標を達成するには、多くの方法があります:
DBMS_MLEを直接使用(この投稿)- APEXのSQLワークショップの使用
- Database Actionsの使用
この投稿では、DBMS_MLEの使用方法を示します。パッケージは、JavaScript開発者ガイドに記載されています。パッケージ参照は、『PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。将来の投稿では、他の2つのオプションについて説明します。
前提条件
DBMS_MLEは、Oracle Database 21c for Linux x86-64で導入されました。このパッケージは、Multilingual Engine(MLE)と対話する唯一の方法を提供しましたが、PL/SQLレイヤーとの対話が必要でした。Oracle Database 23cでも使用できますが、今では、フレームワーク(APEXなど)またはRead-Eval-Print-Loop (REPL)サーバー(あるいはその両方)でパッケージを使用することをお薦めします。アドホック・テストよりも深刻なことは、MLEモジュールと環境、またはインライン・コール仕様で実行する必要があります。この記事では、Oracle Database 23cに付属しているDBMS_MLEについて説明します。互換性の理由から、古い構文(たとえばrequireキーワードの使用)は引き続き有効ですが、新しいコードでは使用しないでください。
APEXおよびDatabase Actionsはコマンドラインよりも優れたエクスペリエンスを提供しますが、DBMS_MLEはテストを行う場合に便利です。APEXまたはDatabase Actionsを使用できない場合、この投稿は時間を節約するのに役立ちます。
DBMS_MLEを使用したアドホックJavaScriptの記述
DBMS_MLEを使用する前に、必要な権限(動的MLEの実行)が必要です。それがないと、ランタイム・エラーが発生します。
大まかに言えば、2つの異なるシナリオがあります:
- 組込みモジュール以外のモジュールを参照せずに、JavaScriptコードを記述する場合
- MLEモジュールからエクスポートされたファンクションを起動する場合
これについて詳しく見ていきましょう。
組込みモジュールおよびアドホック・スクリプティングのコール
グローバル・スコープには、便宜上配置された多数のオブジェクトが含まれます。たとえば、SODA APIまたはデータベース・ドライバとの対話では、次のようなインポートは必要ありません:
set serveroutput on;
declare
l_ctx dbms_mle.context_handle_t;
l_source_code clob;
begin
-- Create execution context for MLE execution and provide an environment_
l_ctx := dbms_mle.create_context();
-- using q-quotes to avoid problems with unwanted string termination
l_source_code :=
q'~
const result = session.execute(
`select 'hello, world'`,
[],
{
outFormat: oracledb.OUT_FORMAT_ARRAY
}
);
const message = result.rows[0][0];
console.log(message);
~';
dbms_mle.eval(
context_handle => l_ctx,
language_id => 'JAVASCRIPT',
source => l_source_code,
source_name => 'example01'
);
dbms_mle.drop_context(l_ctx);
exception
when others then
dbms_mle.drop_context(l_ctx);
raise;
end;
/
コンソールに「hello world」というメッセージが出力されます。前述のコード・スニペットは、実行コンテキストの概念を理解していることを前提としています。理解していない場合は、JavaScript開発者ガイドのセキュリティの章を参照してください。
MLEモジュールによってエクスポートされた機能の呼出し
スキーマに格納されているMLEモジュールによってエクスポートされた機能を起動する場合、この例では少し変更する必要があります。FAKERJS_MODULEとしてスキーマにfaker-js/fakerを作成するとします。その場合、モジュールの使用が会社のポリシーおよびプロジェクトのライセンスに準拠していることを確認し、fakerjsを安全に使用することを確認してから続行します。
cdn.jsdelivr.netなどからESM (ECMAScript)バージョンのモジュールを取得する必要があることを忘れないでください。アカウントが読取り権限を持つデータベース・サーバーのディレクトリ・オブジェクトにファイルを格納します。この例では、ファイルはディレクトリ名SRC_CODE_DIRに格納されます:
create mle module fakerjs_module
language javascript
version '8.4.1'
using BFILE(SRC_CODE_DIR, 'faker-8.4.1.js');
/
MLE環境も必要です:
create mle env fakerjs_env imports (
'fakerjs' module fakerjs_module
);
これで、fakerjs/fakerを使うようになりました。ノードと同様に、動的インポートを使用する必要があります。このルールを無視した場合は、次のことがノードに示されます:
> import oracledb from "oracledb";
import oracledb from "oracledb";
^^^^^^
Uncaught:
SyntaxError: Cannot use import statement inside the Node.js REPL, alternatively use
dynamic import: const { default: oracledb } = await import("oracledb");
したがって、最初のコード・スニペットは次のようになります:
set serveroutput on;
declare
l_ctx dbms_mle.context_handle_t;
l_source_code clob;
begin
-- Create execution context for MLE execution _providing an environment_
l_ctx := dbms_mle.create_context(
environment => 'FAKERJS_ENV'
);
-- using q-quotes to avoid problems with unwanted string termination
l_source_code :=
q'~
(async() => {
const { faker } = await import ("fakerjs");
console.log(
faker.lorem.paragraphs(5)
)
})();
~';
dbms_mle.eval(
context_handle => l_ctx,
language_id => 'JAVASCRIPT',
source => l_source_code,
source_name => 'example02'
);
dbms_mle.drop_context(l_ctx);
exception
when others then
dbms_mle.drop_context(l_ctx);
raise;
end;
/
最初の例と比較して、注目すべき点がいくつかあります:
- 動的インポートを許可するには、インライン非同期関数を”wrapper”として宣言する必要があります
- 環境を
dbms_mle.create_context()に指定する必要があります。そうしないと、MLEでインポート名を解決できません
anonymous PL/SQLブロックの実行時には、次のようなすばらしいテキストが表示されます:
SQL> l
1 declare
2 l_ctx dbms_mle.context_handle_t;
3 l_source_code clob;
4 begin
5 -- Create execution context for MLE execution _providing an environment_
6 l_ctx := dbms_mle.create_context(
7 environment => 'FAKERJS_ENV'
8 );
9
10 -- using q-quotes to avoid problems with unwanted string termination
11 l_source_code :=
12 q'~
13 (async() => {
14 const { faker } = await import ("fakerjs");
15
16 console.log(
17 faker.lorem.paragraphs(5)
18 )
19 })();
20 ~';
21 dbms_mle.eval(
22 context_handle => l_ctx,
23 language_id => 'JAVASCRIPT',
24 source => l_source_code,
25 source_name => 'example02'
26 );
27
28 dbms_mle.drop_context(l_ctx);
29 exception
30 when others then
31 dbms_mle.drop_context(l_ctx);
32 raise;
33* end;
SQL> /
Validus concido officiis. Causa artificiose cognatus volutabrum. Aurum depraedor
conscendo arcesso tonsor ustulo stultus demonstro absens.
Tergiversatio civis tendo cavus ubi tubineus amplexus corrumpo. Alius venio
voveo vorax ver cunabula cito suggero. Timidus conqueror autem acies aedificium.
Sodalitas eaque deprimo acer. Decens doloribus verumtamen capio cariosus
despecto abbas ultio curto. Decretum vulariter in.
Viridis bestia pax conor temporibus verumtamen explicabo aegre cum coepi.
Cohaero tener canto coniuratio tantum thema adopto tepesco vereor. Compello
denego tendo.
Absorbeo amor sollers ars aptus eveniet universe. Temporibus complectus expedita
terminatio approbo adstringo crepusculum vociferor incidunt. Summa modi solum
architecto arbor vereor.
PL/SQL procedure successfully completed.
データベース・サーバー上のファイルにJavaScriptコードを保存し、ドキュメントの説明に従ってdbms_lob.loadclobfromfile()を使用してコードをロードすることで、このゲームを一段上のレベルに引き上げることができます。
以上でテストは終了です!
