node-oracledbとmle-js-oracledbの間のAPIの相違点

接続管理や型マッピングを処理する方法など、node-oracledbmle-js-oracledbの間にはいくつかの相違点があります。

関連項目:

JavaScript組込みモジュールの詳細は、サーバー側JavaScript APIのドキュメントを参照してください

トピック

同期APIとエラー処理

node-oracledbと比較して、mle-js-oracledbドライバは同期モードで動作し、例外が発生すると例外をスローします。非同期動作が必要な場合は、mle-js-oracledbへのコールを非同期ファンクションにラップします。

同期操作中は、結果またはエラーが戻されるまでAPIコールがブロックされます。SQL実行によって発生したエラーはJavaScript例外として報告され、それ以外の場合は、node-oracledbErrorオブジェクトと同じプロパティが戻されます。

次のメソッドは、promiseを戻さず、コールバック・パラメータを使用しません。結果を戻すか、例外をスローします。
  • connection.execute
  • connection.executeMany
  • connection.getStatementInfo
  • connection.getSodaDatabase
  • connection.commit
  • connection.rollback
  • resultset.close
  • resultset.getRow
  • resultset.getRows
次のメソッドは同期方式では実装できず、MLE JavaScriptドライバでは除外されます。
  • connection.break
node-oracledbには、LOB型へのストリーミング・アクセスを提供するLOB (ラージ・オブジェクト)クラスが用意されています。このLOBクラスは非同期Node.jsストリームAPIを実装し、同期MLE JavaScript環境ではサポートできません。ラージ・オブジェクトは、MLE JavaScriptドライバの代替APIを使用してサポートされます。これらの理由により、LOB関連の次の機能はサポートされていません。
  • connection.createLob
  • property oracledb.lobPrefetchSize
  • constant oracledb.BLOB
  • constant oracledb.CLOB
node-oracledbは、Node.jsストリームAPIに基づく別の機能である、問合せ結果の非同期ストリーミングも実装しています。MLE JavaScriptドライバで使用される同期インタフェースではストリーミングAPIを表現できないため、次の機能は使用できません。
  • connection.queryStream()
  • resultSet.toQueryStream()

接続処理

MLE JavaScriptドライバでの接続処理の方法について説明します。

サーバー側のMLE JavaScriptドライバを介して実行されるSQL文はすべて、JavaScriptプログラムを実行している現行のセッションで実行されます。SQL文は、JavaScriptコードの実行を代理される元のユーザーの権限で実行されます。node-oracledb APIと同様に、MLE JavaScriptドライバを使用するJavaScriptコードは、SQL文を実行するために接続オブジェクトを取得する必要があります。ただし、使用可能な接続は、現行のデータベース・セッションへの暗黙的な接続のみです。

JavaScriptコードは、MLE固有のoracledb.defaultConnection()メソッドを使用して、現行のセッションへの接続を取得する必要があります。起動のたびに、セッション接続を表す接続オブジェクトが戻されます。node-oracledboracledb.createConnectionメソッドを使用した接続の作成は、MLE JavaScriptドライバではサポートされていません。また、接続プールの作成もサポートされていません。接続オブジェクトは暗黙的にクローズされるため、MLE JavaScriptドライバでは、connection.close()へのコールを使用できません。

また、MLE JavaScriptドライバには文カーソル・キャッシュがないため、stmtCacheSizeプロパティはありません。

Real Application Cluster (RAC)オプションでは、アプリケーションの可用性を高めるように設計された追加機能が提供されます。これには高速アプリケーション通知(FAN)およびランタイム・ロード・バランシング(RLB)が含まれますが、これらはいずれもMLE JavaScriptドライバではサポートされていません。

トランザクション管理

トランザクション管理に関しては、サーバー側のMLE JavaScriptコードはPL/SQLプロシージャおよびファンクションとまったく同様に動作します。

JavaScriptプログラムは、コール元のSQLまたはPL/SQL文の現行のトランザクション・コンテキストで実行されます。進行中のトランザクションを制御するには、COMMITSAVEPOINTまたはROLLBACKコマンドを実行します。または、メソッドconnection.commit()およびconnection.rollback()を使用することもできます。

MLE JavaScript SQLドライバの接続を明示的にクローズすることはできません。node-oracledbの、接続をクローズすると、トランザクションのロールバックが行われる動作に依存するアプリケーションでは、調整が必要になります。MLE JavaScript SQLドライバでは、トランザクションの暗黙的なコミットもロールバックも行われません。

node-oracledbドライバにはauto-commitフラグが用意されており、デフォルトではfalseに設定されています。MLE JavaScript SQLドライバには、この機能は実装されていません。指定した場合、connection.execute()ファンクションはこのパラメータを無視します。

型マッピング

MLE JavaScriptドライバは、PL/SQL型とJavaScript型の間の変換に関して、node-oracledbの動作に準拠しています。

デフォルトでは、PL/SQL型はネイティブのJavaScript型にマップされます(BLOBとCLOBを除きます)。問合せ結果からフェッチされた値は暗黙的に変換されます。MLEの型マッピングの詳細は、「MLEの型変換」を参照してください。

node-oracledbと同様に、文字以外のデータ型からの変換およびその逆の変換は、NLSセッション・パラメータの影響を直接受けます。MLEのランタイム・ロケールは、これらの変換には影響しません。

ネイティブのJavaScript型とPL/SQLデータ型の間の変換時に精度が損なわれないように、MLE JavaScriptドライバでは新しいラッパー型が導入されています。
  • oracledb.ORACLE_NUMBER
  • oracledb.ORACLE_CLOB
  • oracledb.ORACLE_BLOB
  • oracledb.ORACLE_TIMESTAMP
  • oracledb.ORACLE_TIMESTAMP_TZ
  • oracledb.ORACLE_DATE
  • oracledb.ORACLE_INTERVAL_YM
  • oracledb.ORACLE_INTERVAL_DS

node-oracledbと同様に、connection.execute()fetchInfoプロパティを使用して、JavaScript型へのデフォルト・マッピングを状況に応じてオーバーライドできます。暗黙的な変換や精度の損失を回避するために、oracledb.ORACLE_NUMBERのような型定数を使用して、特定のNUMBER列の型マッピングをオーバーライドできます。

また、JavaScript MLE SQLドライバには、PL/SQL型のデフォルト・マッピングをグローバルに変更する方法も用意されています。対応する型定数がoracledb.fetchAsPlsqlWrapperプロパティに含まれている場合、Oracle値は前述のSQLラッパー型としてフェッチされます。既存のプロパティoracledb.fetchAsStringと同様に、この動作は、fetchInfoおよびoracledb.DEFAULTを使用してオーバーライドできます。MLE JavaScriptはBufferクラスをサポートしておらず、かわりにUint8Arrayを使用するため、node-oracledbのプロパティoracledb.fetchAsBuffermle-js-oracledbには存在せず、かわりにoracledb.fetchAsUint8Arrayを使用します。

デフォルトでJavaScript SQLラッパー型をフェッチするように型マッピングを変更することは、次のシナリオに有用です:
  • Oracle値が主に問合せとDML文の間で移動されるため、PL/SQL型とJavaScript型の間の型変換が不要なオーバーヘッドとなっている
  • データ損失を避けることが非常に重要である

例7-19 JavaScriptのネイティブ・データ型の使用とラッパー型の使用

この例では、計算にJavaScriptのネイティブ・データ型を使用した場合の効果を示します。また、JavaScriptのネイティブ型を使用した場合とラッパー型を使用した場合の精度の損失を比較します。

CREATE OR REPLACE MLE MODULE js_v_wrapper_mod
LANGUAGE JAVASCRIPT AS

/**
 *There is a potential loss of precision when using native
 *JavaScript types to perform certain calculations. This
 *is caused by the underlying implementation as a floating
 *point number
*/

export function precisionLoss(){
    
    let summand1 = session
        .execute(`SELECT 0.1 summand1`)
        .rows[0].SUMMAND1;

    let summand2 = session
        .execute(`SELECT 0.2 summand2`)
        .rows[0].SUMMAND2;

    const result = summand1 + summand2;

    console.log(`precisionLoss() result: ${result}`);
}

/**
 *Use an Oracle data type to preserve precision. The above
 *example can be rewritten using the OracleNumber type as
 *follows
*/
export function preservePrecision(){
    
    //instruct the JavaScript SQL driver to return results as
    //Oracle Number. This could have been done for individual
    //statements using the fetchInfo property - the global
    //change applies to this and all future calls
    oracledb.fetchAsPlsqlWrapper = [oracledb.NUMBER];
    let summand1 = session
        .execute(`SELECT 0.1 S1`)
        .rows[0].S1;
    
    let summand2 = session
        .execute(`SELECT 0.2 S2`)
        .rows[0].S2;

    const result = summand1 + summand2;

    console.log(`preservePrecision() result: ${result}`);
}
/

前述のファンクションを実行すると、精度の違いが即座に明らかになります。

precisionLoss() result: 0.30000000000000004
preservePrecsion() result: .3

グローバルなoracledb.fetchAsPlsqlWrapperプロパティを設定するかわりに、connection.execute()の起動ごとにこの設定をオーバーライドできます。例7-20に、精度をインラインで設定することでprecisionPreservedGlobal()を書き換える方法を示します。

OracleNumber型で使用できるファンクションの詳細は、サーバー側のJavaScript APIドキュメントを参照してください。

例7-20 グローバルなoracledb.fetchAsPlsqlWrapperプロパティのオーバーライド

この例は、精度をインラインで保持することでprecisionPreservedGlobal()を書き換える方法を示すことにより、例7-19を拡張したものです。これは、グローバルなoracledb.fetchAsPlsqlWrapperプロパティを設定するかわりに、connection.execute()の起動ごとにこの設定をオーバーライドできることを示しています。

CREATE OR REPLACE PROCEDURE fetch_info_example
AS MLE LANGUAGE JAVASCRIPT
{{
    let summand1 = session
        .execute(
            `SELECT 0.1 S1`,
            [],
            {
                fetchInfo:{
                    S1:{type: oracledb.ORACLE_NUMBER}
                }
            }
        )
        .rows[0].S1;
    
    let summand2 = session
        .execute(
            `SELECT 0.2 S2`,
            [],
            {
                fetchInfo:{
                    S2:{type: oracledb.ORACLE_NUMBER}
                }
            }
        )
        .rows[0].S2;

    const result = summand1 + summand2;

    console.log(`
    preservePrecision():
    summand1: ${summand1}
    summand2: ${summand2}
    result: ${result}
    `);
}};
/

結果:

preservePrecision():
summand1: .1
summand2: .2
result: .3

サポートされていないデータ型

MLE JavaScriptドライバでは現在、次のデータ型はサポートされていません:
  • LONG
  • LONG RAW
  • XMLType
  • BFILE
  • REF CURSOR

MLE JavaScript SQLドライバで使用できないその他の機能

MLE JavaScriptドライバで使用できる機能とnode-oracledbで使用できる機能の間の違いについて説明します。

MLE JavaScriptドライバにおけるエラー処理は、node-oracledbのようにコールバック/promiseを使用するのではなく、JavaScript例外フレームワークに依存します。MLE JavaScript SQLドライバによってスローされるエラーは、node-oracledbで使用可能なErrorオブジェクトと同じです。

node-oracledbで使用可能なその他のいくつかのクライアント側機能が、サーバー側のMLE環境ではサポートされていません。MLE JavaScriptドライバでは、これらの機能のAPIは除外されます。

現在、次の機能は使用できません:
  • 連続問合せ通知(CQN)
  • アドバンスト・キューイングはネイティブにサポートされず、PL/SQL APIを回避策として使用できます
  • Connection.subscribe()
  • Connection.unsubscribe()
  • oracledbクラス内のすべての連続問合せ通知定数
  • oracledbクラス内のすべてのサブスクリプション定数