136 DBMS_PIPE

DBMS_PIPEパッケージによって、同じインスタンスにある複数のセッションの通信を行います。Oracleパイプは、UNIXで使用するパイプと概念は似ていますが、オペレーティング・システムのパイプ・メカニズムを使用して実装されていません。

この章のトピックは、次のとおりです:

136.1 DBMS_PIPEの概要

パイプ機能には、複数の潜在的なアプリケーション(外部サービス・インタフェース、独立したトランザクション、アラート(トランザクション以外)、デバッグおよびコンセントレータ)があります。

  • 外部サービス・インタフェース: RDBMS外部にあるユーザー記述のサービスと通信できます。これは、共有サーバー・プロセスで効果的に行うことができるため、サービスの複数インスタンスが同時に実行されます。さらに、サービスは非同期で使用できます。サービスのリクエスタは、待機応答をブロックする必要がありません。リクエスタは、(タイムアウトに関係なく)後でチェックできます。このサービスは、Oracleがサポートする任意の3GL言語で記述できます。

  • 独立したトランザクション: パイプは、独立したトランザクション(トリガーで検出されたセキュリティ違反のロギングなど)内で操作を実行できる別のセッションと通信できます。

  • アラート(トランザクション以外): ポーリングするための待機プロセスを要求せずに、別のプロセスを転送できます。アプリケーションにアラートを通知するAFTER行またはAFTER文トリガーがある場合、アプリケーションは、このアラートをデータが変更された可能性を示すためのアラートとして処理します。アプリケーションはそのデータを読み込み、現行の値を取得します。これはAFTERトリガーなので、アプリケーションは、SELECT FOR UPDATEを行って正しいデータを読み込んだことを確認しようとします。

  • デバッグ: トリガーおよびストアド・プロシージャは、デバッグ情報をパイプに送信できます。別のセッションは、パイプからの読込みを続行し、その内容をスクリーンに表示したりファイルに書き込むことができます。

  • コンセントレータ: これは、少数のネットワーク接続に対して多数のユーザーがいる場合のユーザーの多重化や、複数のユーザー・トランザクションを1つのDBMSトランザクションに集中化する場合のパフォーマンス改善に役立ちます。

136.2 DBMS_PIPEのセキュリティ・モデル

DBMS_PIPEとそのサブプログラムを使用するには、そのパッケージに対するEXECUTE権限が必要になります。セキュリティは、CREATE_PIPEファンクションのprivateパラメータを使用してパイプを作成し、特定のユーザーやロールに特定の機能やパイプ名のみを公開する共通パッケージを記述することで強固なものになります。

セキュリティ要件に応じて、パブリック・パイプまたはプライベート・パイプのいずれかを選択できます(「DBMS_PIPEの操作上のノート」を参照)。

DBMS_PIPEパッケージは、実行者の権限を使用します。つまり、メッセージの送受信操作は実行者のスキーマで実行されることになります。

クラウド・オブジェクト・ストアでDBMS_PIPEメッセージを使用するには、DBMS_PIPEパッケージ、DBMS_CLOUDパッケージおよび資格証明オブジェクト(オブジェクト・ストアURIにアクセスするため)に対するEXECUTE権限が必要になります。

参照:

  • そのパッケージの詳細とクラウド・サービス資格証明の操作の詳細は、「DBMS_CLOUD」を参照してください

136.3 DBMS_PIPEの定数

メッセージの送受信を行うための最大待機時間です。

maxwait   constant integer := 86400000; /* 1000 days */ 

136.4 DBMS_PIPEの操作上のノート

Oracleパイプを介して送信する情報は、システム・グローバル領域(SGA)にバッファリングされます。パイプ内のすべての情報は、インスタンスがシャットダウンすると失われます。

警告:

パイプはトランザクションから独立しています。トランザクション制御に影響を与える可能性がある場合は、注意してパイプを使用してください。

オプションとして、永続メッセージ・ストレージにはクラウド・オブジェクト・ストアを使用できます。パイプからのメッセージを送受信するためのプロセスは、ローカル・ストレージとクラウド・ストレージのどちらを使用しても大きな違いはありませんが、クラウド・ストレージ、資格証明オブジェクトおよび関連するクラウドURIを指定する必要がある点で異なります。DBMS_PIPEは、オブジェクト・ストレージとの統合にDBMS_CLOUDパッケージを使用します。つまり、DBMS_PIPEは、DBMS_CLOUDで許容されるすべてのオブジェクト・ストアと資格証明タイプをサポートしていることになります。

オブジェクト・ストレージにパイプ・メッセージを格納すると、同じリージョンまたは異なるリージョンの2つ以上のデータベースがDBMS_PIPEメッセージを使用して通信できるようになり、パイプに格納できるメッセージの最大数の制限がなくなります。つまり、あるReal Application Cluster (RAC)インスタンスでオープンしているデータベース・インスタンスは、異なるクラスタ・インスタンスで実行しているプロセス間の通信にDBMS_PIPEを確実に使用できるということです。

ロック・メカニズムは、クラウド・オブジェクト・ストア内で一度に1つの送信操作または受信操作のみが動作可能になるように実装されています。ロック・ファイルはプロセスがクラウド・ストアの使用を開始したときに作成され、操作が完了すると削除されます。ロックが存在していない場合にのみ、プロセスはクラウド・ストアの操作を開始できます。プロセスは、指定された最大待機時間に達するまで再試行します。すでに動作していない不明なプロセスによってロックが残された場合、そのロックは削除され、現在のプロセスが15分後にクラウド・ストアへのアクセスを試行すると再作成されます。

ノート:

クラウド・オブジェクト・ストアを使用して異なるデータベース間でDBMS_PIPEにアクセスする場合は、プライベート・パイプまたはパブリック・パイプに必要なアクセス権限付きでパイプが作成されるように、メッセージの送受信前にCREATE_PIPE関数を使用することをお薦めします。

参照:

DBMS_PIPEの操作は、次のトピックに関して行われます。

  • パブリック・パイプ

  • パイプへの書込みおよび読込み

  • プライベート・パイプ

  • シングルトン・パイプ

パブリック・パイプ

パブリック・パイプは、暗黙的または明示的に作成できます。暗黙的なパブリック・パイプの場合、パイプは最初の参照時に自動的に作成され、データがなくなると消去されます。パイプ記述子はSGAに格納されるため、空のパイプがキャッシュから削除されるまで、スペースを使用するオーバーヘッドが若干あります。

privateフラグをFALSEに設定し、CREATE_PIPEファンクションをコールして、明示的なパブリック・パイプを作成します。明示的に作成したパイプは、REMOVE_PIPEファンクションをコールして割当て解除する必要があります。

パブリック・パイプのドメインは、明示的または暗黙的にパイプが作成されたスキーマです。

パイプの読取りおよび書込み

各パブリック・パイプは非同期に動作します。スキーマ・ユーザーがDBMS_PIPEパッケージに対するEXECUTE許可を持ち、パブリック・パイプ名を知っている場合にかぎり、任意の数のスキーマ・ユーザーがパブリック・パイプへの書込みを行うことができます。ただし、バッファに入っている情報を1人のユーザーが読み込むと、その情報はバッファから消去されるため、同じパイプの他のユーザーは読み込むことができません。

送信側セッションでは、PACK_MESSAGEプロシージャに1つ以上コールを行ってメッセージを作成します。このプロシージャは、セッションのローカル・メッセージ・バッファにメッセージを追加します。このバッファ内の情報は、メッセージ送信に使用するパイプ名を指定したSEND_MESSAGEファンクションをコールして送信されます。SEND_MESSAGEをコールすると、ローカル・バッファにスタックされたすべてのメッセージが送信されます。

メッセージを受信するプロセスは、メッセージを受信するパイプ名を指定したRECEIVE_MESSAGEファンクションをコールします。次に、UNPACK_MESSAGEプロシージャをコールして、メッセージ内の各項目にアクセスします。

プライベート・パイプ

CREATE_PIPEファンクションをコールして、プライベート・パイプを明示的に作成します。プライベート・パイプは、一度作成されると、REMOVE_PIPEファンクションをコールして明示的に割当て解除するまで共有メモリーに存続します。プライベート・パイプは、データベース・インスタンスがシャットダウンしたときにも割当て解除されます。

メモリーに暗黙的なパイプが存在し、そのパイプと作成しようとするプライベート・パイプが同じ名前の場合、プライベート・パイプは作成できません。この場合は、CREATE_PIPEからエラーが戻されます。

プライベート・パイプへのアクセスは、次のように限定されます。

  • パイプ作成者と同じユーザーIDで実行中のセッション

  • パイプ作成者と同じユーザーID権限ドメインで実行中のストアド・サブプログラム

  • SYSDBAとして接続したユーザー

これ以外のユーザーがパイプ上のメッセージの送受信やパイプの削除を試みると、即時にエラーが発生します。別のユーザーが同じ名前のパイプを作成しようとしても、エラーが発生します。

パブリック・パイプと同様に、SEND_MESSAGEをコールする前にPACK_MESSAGEへのコールを使用して、最初にメッセージを作成する必要があります。同様に、RECEIVE_MESSAGEをコールしてメッセージを取り出してから、UNPACK_MESSAGEをコールしてメッセージ内の項目にアクセスする必要があります。

シングルトン・パイプ

シングルトン・パイプは、現在のデータベース・インスタンスの共有メモリーに単一のメッセージをキャッシュする機能を提供し、データベース・セッション間のメッセージの高スループット同時読取りが可能になります。RACデータベースでは、パイプはデータベース・インスタンス間で同期されません。それぞれのデータベース・インスタンスには独自のパイプがあり、データベース・インスタンスのメモリーに対してプライベートです。

シングルトン・パイプには、単一のメッセージをキャッシュできます。このパイプは、メッセージの合計サイズ32,767バイトまでの複数のフィールドで構成できます。DBMS_PIPEは、PACK_MESSAGEプロシージャを使用することで、メッセージ内に複数の属性をパックする機能をサポートしています。

シングルトン・パイプは、パブリックまたはプライベートにすることも、暗黙的または明示的にすることもできます。プライベート・シングルトン・パイプを使用すると、メッセージはパイプの作成者と同じユーザーのセッションのみが受信できるようになります。パブリック・シングルトン・パイプ内のメッセージは、DBMS_PIPEパッケージに対するEXECUTE権限がある任意のデータベース・セッションで受信できます。

シングルトン・パイプは、無効化されるかパージされるまでパイプにメッセージをキャッシュします。パイプのパージによる明示的な無効化は、PURGEプロシージャを使用するか、SEND_MESSAGEファンクションを使用したメッセージの上書きによって実施します。自動的な無効化は、CREATE_PIPEファンクションとSEND_MESSAGEファンクションの一部として指定されたshelflife時間が経過すると発生します。

ユーザー定義のキャッシュ・ファンクションは、シングルトン・パイプにメッセージを自動的に移入するために使用できます。これは、RECEIVE_MESSAGEファンクションを使用してメッセージを読み取るときに指定できます。キャッシュ内にメッセージがない場合やメッセージのshelflife時間が経過していた場合は、シングルトン・パイプによって新しいメッセージがパイプに自動的に移入されます。キャッシュ・ファンクションは、空のパイプからメッセージを受信できなかったときの条件ロジックを回避することで、パイプの使用を簡素化します。また、シングルトン・パイプからのメッセージの読取り時にキャッシュ・ミスがなくなります。

ノート:

RECEIVE_MESSAGEにキャッシュ・ファンクションを使用する場合、そのキャッシュ・ファンクションの実行にかかった時間は、メッセージの受信に指定された全体的なタイムアウトには含まれません。

シングルトン・パイプは、Oracle Databaseのメモリーから削除されないため、最大のキャッシュ・ヒットが保証されます。明示的なシングルトン・パイプは、REMOVE_PIPEプロシージャを使用して削除するか、データベースの再起動まで、データベース・メモリーに存在します。暗黙的なシングルトン・パイプは、パイプにキャッシュされたメッセージが1つになるまでデータベース・メモリーに存在します。

136.5 DBMS_PIPEの例外

DBMS_PIPEパッケージ・サブプログラムは、次の表に示すエラーを戻すことができます。

表136-1 DBMS_PIPEのエラー

エラー 説明

ORA-23321:

パイプ名はNULLにできません。このエラーは、CREATE_PIPEファンクションまたはパイプ名をパラメータとして使用しているサブプログラムによって戻されます。

ORA-23322:

パイプへのアクセス権限が不十分です。このエラーは、パラメータ・リストにあるプライベート・パイプを参照するサブプログラムによって戻されます。

136.6 DBMS_PIPEの例

次の例は、PL/SQLのデバッグ、Pro*Cのデバッグ、システム・コマンドの実行、および外部サービス・インタフェースでのDBMS_PIPEの使用例を示します。

例1: デバッグ - PL/SQL

この例は、デバッグ情報をパイプに設定するために、PL/SQLプログラムがコールできるプロシージャを示しています。

CREATE OR REPLACE PROCEDURE debug (msg VARCHAR2) AS
    status  NUMBER;
BEGIN
  DBMS_PIPE.PACK_MESSAGE(LENGTH(msg));
  DBMS_PIPE.PACK_MESSAGE(msg);
  status := DBMS_PIPE.SEND_MESSAGE('plsql_debug');
  IF status != 0 THEN
    raise_application_error(-20099, 'Debug error');
  END IF;
END debug;

例2: デバッグ - Pro*C

次のPro*Cコードでは、前述の例のPLSQL_DEBUGパイプから受信したメッセージが表示されます。Pro*Cセッションが別のウィンドウで実行されている場合、このセッションは、別のセッションで実行中のPL/SQLプログラムからデバッグ・プロシージャに送信されるメッセージの表示に使用できます。

#include <stdio.h> 
#include <string.h> 
 
EXEC SQL BEGIN DECLARE SECTION; 
   VARCHAR username[20]; 
   int     status; 
   int     msg_length;
   char    retval[2000];
EXEC SQL END DECLARE SECTION; 
 
EXEC SQL INCLUDE SQLCA; 
 
void sql_error(); 
 
main() 
{ 

-- Prepare username:
   strcpy(username.arr, "HR/<password>"); 
   username.len = strlen(username.arr); 
 
   EXEC SQL WHENEVER SQLERROR DO sql_error(); 
   EXEC SQL CONNECT :username; 
 
   printf("connected\n"); 
 
-- Start an endless loop to look for and print messages on the pipe:
   FOR (;;) 
   { 
      EXEC SQL EXECUTE 
         DECLARE 
            len INTEGER;
            typ INTEGER;
            sta INTEGER; 
            chr VARCHAR2(2000); 
         BEGIN 
            chr := ''; 
            sta := dbms_pipe.receive_message('plsql_debug'); 
            IF sta = 0 THEN 
               DBMS_PIPE.UNPACK_MESSAGE(len);
               DBMS_PIPE.UNPACK_MESSAGE(chr); 
            END IF; 
            :status := sta; 
            :retval := chr; 
            IF len IS NOT NULL THEN
               :msg_length := len;
            ELSE
               :msg_length := 2000;
            END IF;
         END; 
      END-EXEC; 
      IF (status == 0) 
         printf("\n%.*s\n", msg_length, retval);
      ELSE 
         printf("abnormal status, value is %d\n", status); 
   }
}

void sql_error() 
{ 
   char msg[1024]; 
   int rlen, len; 
   len = sizeof(msg); 
   sqlglm(msg, &len, &rlen); 
   printf("ORACLE ERROR\n"); 
   printf("%.*s\n", rlen, msg); 
   exit(1); 
} 

例3: システム・コマンドの実行

この例は、PL/SQLとPro*Cコードによって、PL/SQLストアド・プロシージャ(または無名ブロック)がPL/SQLプロシージャをコールし、コマンドをリスニングしているPro*Cプログラムにパイプを介してそのコマンドを送信する処理を示します。

Pro*Cプログラムはスリープして、名前付きパイプにメッセージが着信するのを待ちます。メッセージが着信すると、Pro*Cプログラムはこれを処理し、system()コールを使用したUNIXコマンドの実行、埋込みSQLを使用したSQLコマンドの実行など、必要なアクションを行います。

DAEMON.SQLは、PL/SQLパッケージ用のソース・コードです。このパッケージには、DBMS_PIPEパッケージを使用してPro*Cデーモンに対してメッセージを送受信するプロシージャが含まれています。完全なハンドシェイクが使用されていることに注意してください。このデーモンは、常にメッセージをパッケージに返信します(STOPコマンドの場合は除きます)。これによって、PL/SQLプロシージャはPro*Cデーモンが動作していることを確認できるため、デーモンのこの機能は重要です。

SQL*PlusまたはEnterprise Managerを使用して、無名PL/SQLブロックからDAEMONパッケージ・プロシージャをコールできます。たとえば:

SQLPLUS> variable rv number
SQLPLUS> execute :rv := DAEMON.EXECUTE_SYSTEM('ls -la');

これにより、UNIXシステムでは、Pro*Cデーモンによってコマンドsystem("ls -la")が実行されます。

最初にデーモンを実行する必要があることに留意してください。デーモンは、バックグラウンドで実行したり、デーモンをコールしたSQL*PlusまたはEnterprise Managerセッションの近くにある別のウィンドウで実行できます。

また、DAEMON.SQLは、DBMS_OUTPUTパッケージを使用して結果を表示します。この例を動作させるには、このパッケージに対するEXECUTE権限が必要です。

DAEMON.SQLの例。次の例は、PL/SQL DAEMONパッケージのコード例です。

CREATE OR REPLACE PACKAGE daemon AS
  FUNCTION execute_sql(command VARCHAR2, 
                       timeout NUMBER DEFAULT 10)
    RETURN NUMBER;

  FUNCTION execute_system(command VARCHAR2,
                          timeout NUMBER DEFAULT 10)
    RETURN NUMBER;

  PROCEDURE stop(timeout NUMBER DEFAULT 10);
END daemon;
/
CREATE OR REPLACE PACKAGE BODY daemon AS

  FUNCTION execute_system(command VARCHAR2,
                          timeout NUMBER DEFAULT 10)
  RETURN NUMBER IS

    status       NUMBER;
    result       VARCHAR2(20);
    command_code NUMBER;
    pipe_name    VARCHAR2(30);
  BEGIN
    pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME;

    DBMS_PIPE.PACK_MESSAGE('SYSTEM');
    DBMS_PIPE.PACK_MESSAGE(pipe_name);
    DBMS_PIPE.PACK_MESSAGE(command);
    status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout);
    IF status <> 0 THEN
      RAISE_APPLICATION_ERROR(-20010,
        'Execute_system: Error while sending.  Status = ' ||
         status);
    END IF;

    status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout);
    IF status <> 0 THEN
      RAISE_APPLICATION_ERROR(-20011,
        'Execute_system: Error while receiving. 
         Status = ' || status);
    END IF;

    DBMS_PIPE.UNPACK_MESSAGE(result);
    IF result <> 'done' THEN
      RAISE_APPLICATION_ERROR(-20012,
        'Execute_system: Done not received.');
    END IF;

    DBMS_PIPE.UNPACK_MESSAGE(command_code);
    DBMS_OUTPUT.PUT_LINE('System command executed.  result = ' ||
                         command_code);
    RETURN command_code;
  END execute_system;

  FUNCTION execute_sql(command VARCHAR2,
                       timeout NUMBER DEFAULT 10)
  RETURN NUMBER IS

    status       NUMBER;
    result       VARCHAR2(20);
    command_code NUMBER;
    pipe_name    VARCHAR2(30);

  BEGIN
    pipe_name := DBMS_PIPE.UNIQUE_SESSION_NAME;

    DBMS_PIPE.PACK_MESSAGE('SQL');
    DBMS_PIPE.PACK_MESSAGE(pipe_name);
    DBMS_PIPE.PACK_MESSAGE(command);
    status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout);
    IF status <> 0 THEN
      RAISE_APPLICATION_ERROR(-20020,
        'Execute_sql: Error while sending.  Status = ' || status);
    END IF;

    status := DBMS_PIPE.RECEIVE_MESSAGE(pipe_name, timeout);

    IF status <> 0 THEN
      RAISE_APPLICATION_ERROR(-20021,
        'execute_sql: Error while receiving.  
         Status = ' || status);
    END IF;

    DBMS_PIPE.UNPACK_MESSAGE(result);
    IF result <> 'done' THEN
      RAISE_APPLICATION_ERROR(-20022,
        'execute_sql: done not received.');
    END IF;

    DBMS_PIPE.UNPACK_MESSAGE(command_code);
    DBMS_OUTPUT.PUT_LINE
        ('SQL command executed.  sqlcode = ' || command_code);
    RETURN command_code;
  END execute_sql;

  PROCEDURE stop(timeout NUMBER DEFAULT 10) IS
    status NUMBER;
  BEGIN
    DBMS_PIPE.PACK_MESSAGE('STOP');
    status := DBMS_PIPE.SEND_MESSAGE('daemon', timeout);
    IF status <> 0 THEN
      RAISE_APPLICATION_ERROR(-20030,
        'stop: error while sending.  status = ' || status);
    END IF;
  END stop;
END daemon;

DAEMON.PCの例。次の例は、Pro*Cデーモンのコード例です。バージョン1.5.x以降のPro*Cプリコンパイラを使用して、このコードをプリコンパイルする必要があります。この例には埋込みPL/SQLコードが含まれているため、USERIDおよびSQLCHECKオプションも指定する必要があります。

ノート:

PL/SQLブロックでVARCHAR出力ホスト変数を使用するには、そのブロックの入力前に長さの要素を初期化する必要があります。

proc iname=daemon userid=HR/<password> sqlcheck=semantics

次に、通常の方法で、Cコンパイルしてリンクします。

#include <stdio.h>
#include <string.h>

EXEC SQL INCLUDE SQLCA;

EXEC SQL BEGIN DECLARE SECTION;
  char *uid = "HR/<password>";
  int status;
  VARCHAR command[20];
  VARCHAR value[2000];
  VARCHAR return_name[30];
EXEC SQL END DECLARE SECTION;

void
connect_error()
{
  char msg_buffer[512];
  int msg_length;
  int buffer_size = 512;

  EXEC SQL WHENEVER SQLERROR CONTINUE;
  sqlglm(msg_buffer, &buffer_size, &msg_length);
  printf("Daemon error while connecting:\n");
  printf("%.*s\n", msg_length, msg_buffer);
  printf("Daemon quitting.\n");
  exit(1);
}

void
sql_error()
{
  char msg_buffer[512];
  int msg_length;
  int buffer_size = 512;

  EXEC SQL WHENEVER SQLERROR CONTINUE;
  sqlglm(msg_buffer, &buffer_size, &msg_length);
  printf("Daemon error while executing:\n");
  printf("%.*s\n", msg_length, msg_buffer);
  printf("Daemon continuing.\n");
}
main()
{
command.len = 20; /*initialize length components*/ 
value.len = 2000; 
return_name.len  = 30; 
  EXEC SQL WHENEVER SQLERROR DO connect_error();
  EXEC SQL CONNECT :uid;
  printf("Daemon connected.\n");

  EXEC SQL WHENEVER SQLERROR DO sql_error();
  printf("Daemon waiting...\n");
  while (1) {
    EXEC SQL EXECUTE
      BEGIN
        :status := DBMS_PIPE.RECEIVE_MESSAGE('daemon');
        IF :status = 0 THEN
          DBMS_PIPE.UNPACK_MESSAGE(:command);
        END IF;
      END;
    END-EXEC;
    IF (status == 0)
    {
      command.arr[command.len] = '\0';
      IF (!strcmp((char *) command.arr, "STOP"))
      {
        printf("Daemon exiting.\n");
        break;
      }

      ELSE IF (!strcmp((char *) command.arr, "SYSTEM"))
      {
        EXEC SQL EXECUTE
          BEGIN
            DBMS_PIPE.UNPACK_MESSAGE(:return_name);
            DBMS_PIPE.UNPACK_MESSAGE(:value);
          END;
        END-EXEC;
        value.arr[value.len] = '\0';
        printf("Will execute system command '%s'\n", value.arr);

        status = system(value.arr);
        EXEC SQL EXECUTE
          BEGIN
            DBMS_PIPE.PACK_MESSAGE('done');
            DBMS_PIPE.PACK_MESSAGE(:status);
            :status := DBMS_PIPE.SEND_MESSAGE(:return_name);
          END;
        END-EXEC;

        IF (status)
        {
          printf
           ("Daemon error while responding to system command.");
          printf("  status: %d\n", status);
        }
      }
      ELSE IF (!strcmp((char *) command.arr, "SQL")) {
        EXEC SQL EXECUTE
          BEGIN
            DBMS_PIPE.UNPACK_MESSAGE(:return_name);
            DBMS_PIPE.UNPACK_MESSAGE(:value);
          END;
        END-EXEC;
        value.arr[value.len] = '\0';
        printf("Will execute sql command '%s'\n", value.arr);

        EXEC SQL WHENEVER SQLERROR CONTINUE;
        EXEC SQL EXECUTE IMMEDIATE :value;
        status = sqlca.sqlcode;

        EXEC SQL WHENEVER SQLERROR DO sql_error();
        EXEC SQL EXECUTE
          BEGIN
            DBMS_PIPE.PACK_MESSAGE('done');
            DBMS_PIPE.PACK_MESSAGE(:status);
            :status := DBMS_PIPE.SEND_MESSAGE(:return_name);
          END;
        END-EXEC;

        IF (status)
        {
          printf("Daemon error while responding to sql command.");
          printf("  status: %d\n", status);
        }
      }
      ELSE
      {
        printf
          ("Daemon error: invalid command '%s' received.\n",
            command.arr);
      }
    }
    ELSE
    {
      printf("Daemon error while waiting for signal.");
      printf("  status = %d\n", status);
    }
  }
  EXEC SQL COMMIT WORK RELEASE;
  exit(0);

例4: 外部サービス・インタフェース

ユーザー作成の3GLコードを、OCIまたはプリコンパイラ・プログラムに設定します。プログラムは、データベースに接続してPL/SQLコードを実行し、パイプから要求を読み込み、結果を計算してから、PL/SQLコードを実行して、パイプ上の結果をリクエスタに返信します。

次に、株式サービス要求の例を示します。すべてのサービス・リクエストについてパイプに渡す引数の推奨する順序を次に示します。

      protocol_version      VARCHAR2        - '1', 10 bytes or less
      returnpipe            VARCHAR2        - 30 bytes or less
      service               VARCHAR2        - 30 bytes or less
      arg1                  VARCHAR2/NUMBER/DATE
         ...
      argn                  VARCHAR2/NUMBER/DATE

結果を戻すための推奨する書式を次に示します。

      success               VARCHAR2        - 'SUCCESS' if OK,
                                              otherwise error message
      arg1                  VARCHAR2/NUMBER/DATE
         ...
      argn                  VARCHAR2/NUMBER/DATE

OCIまたはPRO*(疑似コードで)を使用して、株価要求サーバーを次のように設定します。

    <loop forever>
      BEGIN dbms_stock_server.get_request(:stocksymbol); END;
      <figure out price based on stocksymbol (probably from some radio
            signal), set error if can't find such a stock>
      BEGIN dbms_stock_server.return_price(:error, :price); END;

クライアントは次のように設定します。

    BEGIN :price := stock_request('YOURCOMPANY'); end;

前述の株価要求サーバーでコールしたストアド・プロシージャdbms_stock_serverは、次のように設定します。

    CREATE OR REPLACE PACKAGE dbms_stock_server IS
      PROCEDURE get_request(symbol OUT VARCHAR2);
      PROCEDURE return_price(errormsg IN VARCHAR2, price IN VARCHAR2);
    END;
  
    CREATE OR REPLACE PACKAGE BODY dbms_stock_server IS
      returnpipe    VARCHAR2(30);
  
      PROCEDURE returnerror(reason VARCHAR2) IS
        s INTEGER;
      BEGIN
        dbms_pipe.pack_message(reason);
        s := dbms_pipe.send_message(returnpipe);
        IF s <> 0 THEN
          raise_application_error(-20000, 'Error:' || to_char(s) ||
            ' sending on pipe');
        END IF;
      END;
  
      PROCEDURE get_request(symbol OUT VARCHAR2) IS
        protocol_version VARCHAR2(10);
        s                INTEGER;
        service          VARCHAR2(30);
      BEGIN
        s := dbms_pipe.receive_message('stock_service');
        IF s <> 0 THEN
          raise_application_error(-20000, 'Error:' || to_char(s) ||
            'reading pipe');
        END IF;
        dbms_pipe.unpack_message(protocol_version);
        IF protocol_version <> '1' THEN
          raise_application_error(-20000, 'Bad protocol: ' || 
            protocol_version);
        END IF;
        dbms_pipe.unpack_message(returnpipe);
        dbms_pipe.unpack_message(service);
        IF service != 'getprice' THEN
          returnerror('Service ' || service || ' not supported');
        END IF;
        dbms_pipe.unpack_message(symbol);
      END;
  
      PROCEDURE return_price(errormsg in VARCHAR2, price in VARCHAR2) IS
        s INTEGER;
      BEGIN
        IF errormsg is NULL THEN
          dbms_pipe.pack_message('SUCCESS');
          dbms_pipe.pack_message(price);
        ELSE
          dbms_pipe.pack_message(errormsg);
        END IF;
        s := dbms_pipe.send_message(returnpipe);
        IF s <> 0 THEN
          raise_application_error(-20000, 'Error:'||to_char(s)||
            ' sending on pipe');
        END IF;
      END;
    END;
  

クライアントがコールするプロシージャは、次のように設定します。

    CREATE OR REPLACE FUNCTION stock_request (symbol VARCHAR2) 
        RETURN VARCHAR2 IS
      s        INTEGER;
      price    VARCHAR2(20);
      errormsg VARCHAR2(512);
    BEGIN
      dbms_pipe.pack_message('1');  -- protocol version
      dbms_pipe.pack_message(dbms_pipe.unique_session_name); -- return pipe
      dbms_pipe.pack_message('getprice');
      dbms_pipe.pack_message(symbol);
      s := dbms_pipe.send_message('stock_service');
      IF s <> 0 THEN
        raise_application_error(-20000, 'Error:'||to_char(s)||
          ' sending on pipe');
      END IF;
      s := dbms_pipe.receive_message(dbms_pipe.unique_session_name);
      IF s <> 0 THEN
        raise_application_error(-20000, 'Error:'||to_char(s)||
          ' receiving on pipe');
      END IF;
      dbms_pipe.unpack_message(errormsg);
      IF errormsg <> 'SUCCESS' THEN
        raise_application_error(-20000, errormsg);
      END IF;
      dbms_pipe.unpack_message(price);
      RETURN price;
    END;

一般的に、株式サービス・アプリケーション・サーバーに対してのみDBMS_STOCK_SERVICEGRANT EXECUTEを実行し、このサービスを利用できるユーザーに対してのみstock_requestGRANT EXECUTEを実行します。

参照:

DBMS_ALERT

136.7 DBMS_PIPEサブプログラムの要約

この表は、DBMS_PIPEサブプログラムを示し、簡単に説明しています。

表136-2 DBMS_PIPEパッケージのサブプログラム

サブプログラム 説明

CREATE_PIPEファンクション

パイプを作成します(プライベート・パイプの場合は必須です)。

GET_CREDENTIAL_NAMEファンクション

グローバルに設定されたcredential_name変数を返します

GET_LOCATION_URIファンクション

グローバルに設定されたlocation_uri変数を返します

NEXT_ITEM_TYPEファンクション

バッファにある次の項目のデータ・タイプを戻します。

PACK_MESSAGEプロシージャ

ローカル・バッファにメッセージを作成します。

PURGEプロシージャ

名前付きパイプの内容をパージします。

RECEIVE_MESSAGEファンクション

名前付きパイプからローカル・バッファにメッセージをコピーします。

REMOVE_PIPEファンクション

名前付きパイプを削除します。

RESET_BUFFERプロシージャ

ローカル・バッファの内容をパージします。

SEND_MESSAGEファンクション

メッセージを名前付きパイプに送信します。名前付きパイプが存在しない場合は、パブリック・パイプが暗黙的に作成されます。

SET_CREDENTIAL_NAMEプロシージャ

グローバルcredential_name変数を設定します

SET_LOCATION_URIプロシージャ

グローバルlocation_uri変数を設定します

UNIQUE_SESSION_NAMEファンクション

一意のセッション名を戻します。

UNPACK_MESSAGEプロシージャ

バッファにある次の項目にアクセスします。

136.7.1 CREATE_PIPEファンクション

このファンクションは、パブリック・パイプまたはプライベート・パイプを明示的に作成します。privateフラグがTRUEの場合、パイプ作成者がそのプライベート・パイプの所有者として割り当てられます。

明示的に作成されたパイプは、REMOVE_PIPEをコールするか、またはインスタンスをシャットダウンすることによってのみ削除できます。

構文

DBMS_PIPE.CREATE_PIPE (
   pipename     IN VARCHAR2,
   maxpipesize  IN INTEGER DEFAULT 65536,
   private      IN BOOLEAN DEFAULT TRUE,
   singleton    IN BOOLEAN DEFAULT FALSE,
   shelflife    IN INTEGER DEFAULT 0)
RETURN INTEGER;

プラグマ

pragma restrict_references(create_pipe,WNDS,RNDS); 

パラメータ

表136-3 CREATE_PIPEファンクションのパラメータ

パラメータ 説明

pipename

作成するパイプの名前。

SEND_MESSAGEおよびRECEIVE_MESSAGEをコールするときは、この名前を使用する必要があります。この名前は、インスタンス間で一意である必要があります。

注意: ORA$で始まるパイプ名を使用しないでください。これは、オラクル社が提供する製品用に予約されています。パイプ名は128バイト以下で指定し、大/小文字区別がありません。現時点では、名前にグローバリゼーション・サポート文字を含めることはできません。

maxpipesize

パイプの最大サイズ(バイト単位)。

パイプ上のすべてのメッセージの合計サイズは、この数を超えることはできません。この最大値を超えると、そのメッセージはブロックされます。デフォルトのmaxpipesizeは65536バイトです。

パイプのmaxpipesizeはパイプ特性の一部となり、パイプが存続するかぎり有効です。これより大きいパイプ・サイズでSEND_MESSAGEをコールすると、maxpipesizeの値が大きくなります。これより小さいサイズでコールした場合は、より大きい既存の値を使用します。

private

デフォルトのTRUEを使用して、プライベート・パイプを作成します。

パブリック・パイプは、SEND_MESSAGEをコールして、暗黙的に作成できます。

singleton

TRUEは、シングルトン・パイプとしてパイプを作成する必要があることを示すために使用します。

singletonのデフォルト値は、FALSEです。

shelflife

オプションで、シングルトン・パイプにキャッシュされるメッセージの有効期限を秒単位で設定するために使用します。shelflife時間が経過すると、メッセージはパイプからアクセスできなくなります。shelflifeは、シングルトン・パイプ内のメッセージの暗黙的な無効化に使用できます。

デフォルト値の0は、メッセージが期限切れにならないことを示します。

シングルトン・パイプのメッセージのshelflifeは、メッセージの送信時にも指定できます。「SEND_MESSAGEファンクション」を参照してください。

戻り値

表136-4 CREATE_PIPEファンクションの戻り値

戻り値 説明

0

成功。

パイプが存在し、パイプを作成するユーザーにそのパイプの使用が認可されている場合、Oracleは0(ゼロ)を戻して成功であることを示し、パイプ内のデータはそのまま残ります。

SYSDBA/SYSOPERとして接続したユーザーがパイプを再作成した場合、Oracleはステータス0を戻しますが、そのパイプの所有者は変更されないままです。

6

既存のパイプをシングルトン・パイプに変換できませんでした。

複数の既存のメッセージがある暗黙的パイプは、シングルトン・パイプに変換できません。

シングルトン・パイプではない明示的なパイプの場合、SEND_MESSAGEではsingletonパラメータをTRUEに設定したメッセージを送信できません。

7

shelflifeに0以外の値が指定されていて、パイプはシングルトン・パイプではありません。

ORA-23322

命名競合のために失敗。

同じ名前のパイプが存在し、別のユーザーがそのパイプを作成した場合、OracleではエラーORA-23322を通知して命名競合であることを示しています。

例外

表136-5 CREATE_PIPEファンクションの例外

例外 説明

パイプ名がNULL

アクセス権エラー: 同名のパイプが存在するため使用できません。

136.7.2 GET_CREDENTIAL_NAMEファンクション

このファンクションでは、デフォルトの資格証明としてクラウドで使用されるグローバルcredential_name変数を取得します。

構文

DBMS_PIPE.GET_CREDENTIAL_NAME ()
RETURN VARCHAR2;

戻り値

このファンクションは、グローバルに設定されたcredential_name変数を返します。この変数は、デフォルトでNULLに設定されます。

136.7.3 GET_LOCATION_URIファンクション

このファンクションでは、デフォルトの場所URIとしてクラウドで使用されるグローバルlocation_uri変数を取得します。

構文

DBMS_PIPE.GET_LOCATION_URI ()
RETURN VARCHAR2;

戻り値

このファンクションは、グローバルに設定されたlocation_uri変数を返します。この変数は、デフォルトでNULLに設定されます。

136.7.4 NEXT_ITEM_TYPEファンクション

このファンクションは、ローカル・メッセージ・バッファにある次の項目のタイプを判別します。

RECEIVE_MESSAGEをコールして、ローカル・バッファにパイプ情報を設定した後、NEXT_ITEM_TYPEをコールします。

構文

DBMS_PIPE.NEXT_ITEM_TYPE 
  RETURN INTEGER; 

プラグマ

pragma restrict_references(next_item_type,WNDS,RNDS);  

戻り値

表136-6 NEXT_ITEM_TYPEファンクションの戻り値

戻り値 説明

0

次の項目がありません。

6

NUMBER

9

VARCHAR2

11

ROWID

12

DATE

23

RAW

136.7.5 PACK_MESSAGEプロシージャ

このプロシージャは、ユーザーのメッセージをローカル・メッセージ・バッファに作成します。

メッセージを送信するためには、最初にPACK_MESSAGEを1回以上コールします。次に、SEND_MESSAGEをコールして、ローカル・バッファにあるメッセージを名前付きパイプに送信します。

このプロシージャは、VARCHAR2NCHARNUMBERDATERAWおよびROWIDタイプの項目を受け入れるためにオーバーロードされます。バッファ内の各項目には、データ・バイトの他に、項目のタイプを示すための1バイト、および長さを格納するための2バイトが必要です。メッセージを終了するには、さらに1バイトが必要で、VARCHAR以外のすべてのタイプのオーバーヘッドは4バイトです。

構文

DBMS_PIPE.PACK_MESSAGE (
   item  IN  VARCHAR2);

DBMS_PIPE.PACK_MESSAGE (
   item  IN  NCHAR);

DBMS_PIPE.PACK_MESSAGE (
   item  IN  NUMBER);

DBMS_PIPE.PACK_MESSAGE (
   item  IN  DATE);

DBMS_PIPE.PACK_MESSAGE_RAW (
   item  IN  RAW);

DBMS_PIPE.PACK_MESSAGE_ROWID (
   item  IN  ROWID);

プラグマ

pragma restrict_references(pack_message,WNDS,RNDS);
pragma restrict_references(pack_message_raw,WNDS,RNDS);  
pragma restrict_references(pack_message_rowid,WNDS,RNDS); 

パラメータ

表136-7 PACK_MESSAGEプロシージャのパラメータ

パラメータ 説明

item

ローカル・メッセージ・バッファにパックする項目。

使用上のノート

Oracle Databaseのバージョン8.xでは、文字セットID(2バイト)および文字セット・フォーム(1バイト)が各データ項目に格納されています。そのため、Oracle Databaseのバージョン8.x使用時のオーバーヘッドは7バイトになります。

SEND_MESSAGEをコールしてメッセージを送信するときは、メッセージを送信するパイプの名前を示す必要があります。パイプがすでに存在する場合は、そのパイプにアクセスするための十分な権限が必要です。パイプが存在しない場合は、自動的に作成されます。

例外

メッセージ・バッファ(現在は4096バイト)がオーバーフローした場合は、ORA-06558が発生します。バッファ内の各項目には、実際のデータに加えて、タイプを示すために1バイト、長さを示すために2バイトが必要です。さらに、メッセージを終了するために1バイトが必要です。

136.7.6 PURGEプロシージャ

このプロシージャは、名前付きパイプの内容を空にします。

暗黙的に作成された空のパイプは、LRUアルゴリズムに従って、共有グローバル領域から削除されます。したがって、PURGEをコールすると、暗黙的に作成したパイプに関連するメモリーを空にできます。

構文

DBMS_PIPE.PURGE (
   pipename  IN  VARCHAR2);

プラグマ

pragma restrict_references(purge,WNDS,RNDS); 

パラメータ

表136-8 PURGEプロシージャのパラメータ

パラメータ 説明

pipename

すべてのメッセージを削除するパイプの名前。

メッセージが廃棄されると、ローカル・バッファがそのメッセージで上書きされる場合があります。パイプ名は128バイト以下で指定し、大/小文字は区別されません。

使用上のノート

PURGEプロシージャはRECEIVE_MESSAGEをコールするため、メッセージがパイプからパージされるとき、ローカル・バッファはそのメッセージで上書きされる場合があります。また、不十分なアクセス権でパイプをパージしようとすると、ORA-23322エラー(不十分な権限)を受け取ります。

例外

パイプを別のユーザーが所有している場合は、アクセス権エラーが発生します。

136.7.7 RECEIVE_MESSAGEファンクション

このファンクションは、メッセージをローカル・メッセージ・バッファにコピーします。

構文

DBMS_PIPE.RECEIVE_MESSAGE (
   pipename     IN VARCHAR2,
   timeout      IN INTEGER      DEFAULT maxwait,
   cache_func   IN VARCHAR2     DEFAULT NULL)
RETURN INTEGER;
DBMS_PIPE.RECEIVE_MESSAGE (
   pipename           IN VARCHAR2,
   timeout            IN INTEGER      DEFAULT maxwait,
   credential_name    IN VARCHAR2     DEFAULT NULL,
   location_uri       IN VARCHAR2     DEFAULT NULL)
RETURN INTEGER;

プラグマ

pragma restrict_references(receive_message,WNDS,RNDS);  

パラメータ

表136-9 RECEIVE_MESSAGEファンクションのパラメータ

パラメータ 説明

pipename

メッセージを受信するパイプ名。

ORA$で始まる名前は、オラクル社で使用するために予約されています。

timeout

メッセージを待つ時間(秒単位)。

デフォルト値は定数MAXWAITで、86400000(1000日)に定義されています。タイムアウトを0(ゼロ)に指定すると、ブロックされずに読み込むことができます。

cache_func

シングルトン・パイプに自動的にメッセージをキャッシュするために使用されるキャッシュ・ファンクション名で、PL/SQLファンクションまたはPL/SQLパッケージの埋込みファンクションとして作成できます。

指定した場合、そのキャッシュ・ファンクションは、RECEIVE_MESSAGEファンクションを呼び出している現在のセッション・ユーザーとして呼び出されるため、現在のユーザーには、そのファンクションに対する権限が必要になります。

ファンクションの名前は、所有者スキーマで完全修飾されている必要があります:
  • OWNER.FUNCTION_NAME

  • OWNER.PACKAGE.FUNCTION_NAME

キャッシュ・ファンクションの実行にかかった時間は、メッセージの受信に指定された全体的なタイムアウトには含まれません。

credential_name

メッセージの格納に使用するクラウド・ストアの資格証明名。

デフォルト値はNULLです。渡したパラメータは、パッケージ引数の値よりも優先されます。資格証明には、EXECUTE権限とREAD/WRITE権限が必要です。

location_uri

メッセージの格納に使用しているクラウド・ストアの場所URL。

location_uriパラメータはグローバル変数で、デフォルトの値はNULLです。渡したパラメータは、グローバル変数の値よりも優先されます。

資格証明名を指定する場合は、location_uriの指定も必要になります。

戻り値

表136-10 RECEIVE_MESSAGEファンクションの戻り値

戻り値 説明

0

成功。

1

タイムアウトしました。暗黙的に作成されたパイプが空の場合、そのパイプは削除されます。

2

パイプにあるレコードが、バッファに対して大きすぎます。(これは起りえないことです。)

3

割込みが発生しました。

8

シングルトン以外のパイプにキャッシュ・ファンクションが指定されました。

ORA-23322

パイプから読み込むための十分な権限がユーザーにありません。

使用上のノート

パイプからメッセージを受信するには、最初にRECEIVE_MESSAGEをコールします。メッセージを受信すると、パイプからメッセージが削除されるため、メッセージは1回しか受信できません(シングルトン・パイプを使用していない場合)。暗黙的に作成されたパイプは、最後のレコードがそのパイプから削除された後で削除されます。暗黙的なシングルトン・パイプは、パイプにキャッシュされたメッセージが1つになるまでデータベース・メモリーに存在します。

RECEIVE_MESSAGEのコール時に指定したパイプがすでに存在しない場合、Oracleはパイプを暗黙的に作成してメッセージの受信を待ちます。メッセージが指定したタイムアウト時間内に着信しなかった場合、そのコールは戻され、パイプは削除されます。

メッセージの受信後、1つ以上のUNPACK_MESSAGEをコールして、メッセージ内の個別の項目にアクセスする必要があります。UNPACK_MESSAGEプロシージャは、DATENUMBERVARCHAR2タイプの項目をアンパックするためにオーバーロードされ、さらに、RAWおよびROWID項目をアンパックするための2つのプロシージャがあります。アンパックするデータのタイプが不明の場合は、NEXT_ITEM_TYPEをコールして、バッファ内にある次の項目のタイプを判別します。

シングルトン・パイプにキャッシュ・ファンクション・パラメータを指定すると、次の2つのいずれかのシナリオで、シングルトン・パイプに自動的にメッセージを移入できます:
  • シングルトン・パイプが空

  • shelflife時間が経過したため、シングルトン・パイプ内のメッセージが無効

キャッシュ・ファンクションは、空のパイプからメッセージを受信できなかったときの条件ロジックを回避することでシングルトン・パイプの使用を簡素化し、キャッシュ・ミスが発生しないようにします。

ノート:

データベース間メッセージングを実行する場合は、新しいデータベースで初めてのメッセージを受信する前に、CREATE_PIPEファンクションをコールする必要があります。このパイプの名前とそのプロパティは、別のデータベースでメッセージが送信されたパイプと同じになっている必要があります。

例外

表136-11 RECEIVE_MESSAGEファンクションの例外

例外 説明

パイプ名がNULL

アクセス権エラー。パイプからレコードを削除するための権限が不十分です。パイプは別のユーザーが所有しています。

136.7.8 RESET_BUFFERプロシージャ

このプロシージャは、PACK_MESSAGEおよびUNPACK_MESSAGEの位置設定インジケータを0(ゼロ)にリセットします。

すべてのパイプが1つのバッファを共有しているため、新規パイプを使用する前にバッファをリセットすると効果的です。これにより、初めてメッセージをパイプに送信するとき、バッファ内に残っていた期限切れのメッセージを誤って送信することがなくなります。

構文

DBMS_PIPE.RESET_BUFFER; 

プラグマ

pragma restrict_references(reset_buffer,WNDS,RNDS);  

136.7.9 REMOVE_PIPEファンクション

このファンクションは、明示的に作成されたパイプを削除します。

SEND_MESSAGEで暗黙的に作成されたパイプは、空になると自動的に削除されます。ただし、CREATE_PIPEで明示的に作成されたパイプは、REMOVE_PIPEをコールするか、またはインスタンスをシャットダウンした場合にのみ削除されます。パイプ内の未使用のレコードは、パイプが削除される前にすべて削除されます。

これは、暗黙的に作成されたパイプでPURGEをコールするのに似ています。

構文

DBMS_PIPE.REMOVE_PIPE (
   pipename  IN  VARCHAR2)
RETURN INTEGER;

プラグマ

pragma restrict_references(remove_pipe,WNDS,RNDS); 

パラメータ

表136-12 REMOVE_PIPEファンクションのパラメータ

パラメータ 説明

pipename

削除するパイプ名。

戻り値

表136-13 REMOVE_PIPEファンクションの戻り値

戻り値 説明

0

成功。

パイプが存在しない場合、またはパイプがすでに存在し、パイプを削除しようとするユーザーに削除が認可されている場合、Oracleは0(ゼロ)を戻して成功であることを示し、パイプ内に残っているデータが削除されます。

ORA-23322

権限が不十分です。

パイプが存在しても、ユーザーにそのパイプへのアクセス権がない場合、OracleはエラーORA-23322を通知して権限が不十分であることを示します。

例外

表136-14 REMOVE_PIPEファンクションの例外

例外 説明

パイプ名がNULL

アクセス権エラー: パイプを削除する権限が不十分です。パイプは作成されていて、別のユーザーが所有しています。

136.7.10 SEND_MESSAGEファンクション

このファンクションは、メッセージを名前付きパイプに送信します。

PACK_MESSAGEへのコールで入力されたメッセージは、ローカル・メッセージ・バッファに格納されます。CREATE_PIPEを使用するとパイプを明示的に作成でき、それ以外の場合は暗黙的に作成されます。

構文

DBMS_PIPE.SEND_MESSAGE (
    pipename     IN VARCHAR2,
    timeout      IN INTEGER DEFAULT MAXWAIT,
    maxpipesize  IN INTEGER DEFAULT 65536,
    singleton    IN BOOLEAN DEFAULT FALSE,
    shelflife    IN INTEGER DEFAULT 0)
  RETURN INTEGER;
DBMS_PIPE.SEND_MESSAGE (
    pipename         IN VARCHAR2,
    timeout          IN INTEGER DEFAULT MAXWAIT,
    credential_name  IN VARCHAR2 DEFAULT NULL,
    location_uri     IN VARCHAR2 DEFAULT NULL)
  RETURN INTEGER;

プラグマ

pragma restrict_references(send_message,WNDS,RNDS);  

パラメータ

表136-15 SEND_MESSAGEファンクションのパラメータ

パラメータ 説明

pipename

メッセージを設定するパイプの名前。

明示的なパイプを使用している場合、この名前は、CREATE_PIPEをコールしたときに指定した名前です。

注意: ORA$で始まるパイプ名を使用しないでください。これは、オラクル社が提供する製品用に予約されています。パイプ名は128バイト以下で指定し、大/小文字は区別されません。現時点では、名前にグローバリゼーション・サポート文字を含めることはできません。

timeout

パイプにメッセージを設定する間の待機時間(秒単位)。

デフォルト値は定数MAXWAITで、86400000(1000日)に定義されています。

maxpipesize

パイプの最大サイズ(バイト単位)。

パイプ上のすべてのメッセージの合計サイズは、この数を超えることはできません。この最大値を超えると、そのメッセージはブロックされます。デフォルトは65536バイトです。

パイプのmaxpipesizeはパイプ特性の一部となり、パイプが存続するかぎり有効です。これより大きいパイプ・サイズでSEND_MESSAGEをコールすると、maxpipesizeの値が大きくなります。これより小さいサイズでコールした場合は、より大きい既存の値を使用します。

SEND_MESSAGEプロシージャの一部としてmaxpipesizeを指定すると、別のコールでパイプをオープンする必要がなくなります。明示的にパイプを作成した場合は、オプションのmaxpipesizeパラメータを使用して、作成したパイプのサイズを上書きできます。

singleton

singletonにTRUEを指定することで、暗黙的なパイプをシングルトン・パイプとして作成する必要があることを示します。この引数は、CREATE_PIPEファンクションを使用して、シングルトン・パイプとして明示的にパイプが作成されている場合は不要です。

singletonのデフォルト値は、FALSEです。

shelflife

オプションで、暗黙的または明示的シングルトン・パイプにキャッシュされるメッセージの有効期限を秒単位で設定するために使用します。shelflife時間が経過すると、メッセージはパイプからアクセスできなくなります。shelflifeは、シングルトン・パイプ内のメッセージの暗黙的な無効化に使用できます。

デフォルト値の0は、メッセージが期限切れにならないことを示します。

SEND_MESSAGEプロシージャの一部としてshelflifeを指定すると、明示的シングルトン・パイプにCREATE_PIPEを使用して指定したshelflife値が上書きされ、シングルトン・パイプにキャッシュされる新しいメッセージのデフォルトになります。

credential_name

メッセージの格納に使用するクラウド・ストアの資格証明名。

デフォルト値はNULLです。渡したパラメータは、パッケージ引数の値よりも優先されます。資格証明には、EXECUTE権限とREAD/WRITE権限が必要です。

location_uri

メッセージの格納に使用しているクラウド・ストアの場所URL。

location_uriパラメータはグローバル変数で、デフォルトの値はNULLです。渡したパラメータは、グローバル変数の値よりも優先されます。

資格証明名を指定する場合は、location_uriの指定も必要になります。

戻り値

表136-16 SEND_MESSAGEファンクションの戻り値

戻り値 説明

0

成功。

パイプが存在し、パイプを作成するユーザーにそのパイプの使用が認可されている場合、Oracleは0(ゼロ)を戻して成功であることを示し、パイプ内のデータはそのまま残ります。

SYSDBS/SYSOPERとして接続したユーザーがパイプを再作成した場合、Oracleはステータス0(ゼロ)を戻しますが、そのパイプの所有者は変更されないままです。

1

タイムアウトしました。

このプロシージャは、パイプでロックが取得できないか、またはパイプがいっぱいで使用できない理由でタイムアウトできます。暗黙的に作成されたパイプが空の場合、そのパイプは削除されます。

3

割込みが発生しました。

暗黙的に作成されたパイプが空の場合、そのパイプは削除されます。

6

既存のパイプをシングルトン・パイプに変換できませんでした。

複数の既存のメッセージがある暗黙的パイプは、シングルトン・パイプに変換できません。

シングルトン・パイプではない明示的なパイプの場合、SEND_MESSAGEではsingletonパラメータをTRUEに設定したメッセージを送信できません。

7

shelflifeに0以外の値が指定されていて、パイプはシングルトン・パイプではありません。

ORA-23322

権限が不十分です。

同じ名前のパイプが存在し、別のユーザーがそのパイプを作成した場合、OracleではエラーORA-23322を通知して命名競合であることを示しています。

例外

表136-17 SEND_MESSAGEファンクションの例外

例外 説明

パイプ名がNULL

アクセス権エラー。パイプに書込みを行うための権限が不十分です。パイプはプライベートで、別のユーザーが所有しています。

136.7.11 SET_CREDENTIAL_NAMEプロシージャ

このプロシージャでは、デフォルトの資格証明としてクラウドで使用されるグローバルcredential_name変数を設定します。

構文

DBMS_PIPE.SET_CREDENTIAL_NAME (
   credential_name   IN VARCHAR2);

パラメータ

表136-18 SET_CREDENTIAL_NAMEプロシージャのパラメータ

パラメータ 説明

credential_name

メッセージの格納に使用するクラウド・ストアの資格証明名。

136.7.12 SET_LOCATION_URIプロシージャ

このプロシージャでは、デフォルトの場所URIとしてクラウドで使用されるグローバルset_location_uri変数を設定します。

構文

DBMS_PIPE.SET_LOCATION_URI (
   location_uri   IN VARCHAR2);

パラメータ

表136-19 SET_LOCATION_URIプロシージャ

パラメータ 説明

location_uri

メッセージの格納に使用されるクラウド・ストアの場所URI。

136.7.13 UNIQUE_SESSION_NAMEファンクション

このファンクションは、現在データベースに接続しているすべてのセッション間での一意の名前を受け取ります。

同じセッションからこのファンクションを複数回コールしても、常に同じ値が戻されます。このファンクションは、SEND_MESSAGEおよびRECEIVE_MESSAGEのコールにPIPENAMEパラメータを提供するのに役立ちます。

構文

DBMS_PIPE.UNIQUE_SESSION_NAME 
  RETURN VARCHAR2;

プラグマ

pragma restrict_references(unique_session_name,WNDS,RNDS,WNPS);

戻り値

このファンクションは、一意の名前を戻します。戻される名前は、最大30バイトです。

136.7.14 UNPACK_MESSAGEプロシージャ

このプロシージャは、バッファから項目を取り出します。

RECEIVE_MESSAGEをコールして、ローカル・バッファにパイプ情報を設定した後、UNPACK_MESSAGEをコールします。

ノート:

UNPACK_MESSAGEプロシージャは、VARCHAR2NCHARNUMBERまたはDATEタイプの項目を戻すためにオーバーロードされています。さらに、RAWおよびROWID項目をアンパックするための2つのプロシージャがあります。

構文

DBMS_PIPE.UNPACK_MESSAGE (
   item  OUT VARCHAR2);

DBMS_PIPE.UNPACK_MESSAGE (
   item  OUT NCHAR);

DBMS_PIPE.UNPACK_MESSAGE (
   item  OUT NUMBER);

DBMS_PIPE.UNPACK_MESSAGE (
   item  OUT DATE);

DBMS_PIPE.UNPACK_MESSAGE_RAW (
   item  OUT RAW);

DBMS_PIPE.UNPACK_MESSAGE_ROWID (
   item  OUT ROWID);

プラグマ

pragma restrict_references(unpack_message,WNDS,RNDS);  
pragma restrict_references(unpack_message_raw,WNDS,RNDS);  
pragma restrict_references(unpack_message_rowid,WNDS,RNDS);  

パラメータ

表136-20 UNPACK_MESSAGEプロシージャのパラメータ

パラメータ 説明

item

アンパックされた次の項目をローカル・メッセージ・バッファから受け取るための引数。

例外

バッファに次の項目がない場合、または項目が要求されたタイプでない場合は、ORA-06556または06559が生成されます。