ヘッダーをスキップ
Pro*C/C++プログラマーズ・ガイド
11gリリース2(11.2)
B61343-01
  ドキュメント・ライブラリへ
ライブラリ
製品リストへ
製品
目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

20 ユーザー・イグジット

この章では、Oracleツール・アプリケーション用のユーザー・イグジットの作成方法を説明します。C言語のサブルーチンを使用すると、SQL*FormsおよびOracle Formsよりも迅速で、しかも簡単に特定の作業を実行できることがわかります。この章の項目は、次のとおりです。

この章の内容は補足説明です。ユーザー・イグジットの詳細は、Oracle Formsのオンライン・ヘルプおよび各システム固有のOracleマニュアルを参照してください。

ユーザー・イグジット

ユーザー・イグジットとは、特別な目的の処理を実行するために作成するC言語のサブルーチンを指します。このサブルーチンはOracle Formsによってコールされます。ユーザー・イグジットにSQL文およびPL/SQLブロックを組み込み、その後ホスト・プログラムの場合と同様にこれをプリコンパイルできます。

Oracle Formsバージョン3のトリガーからユーザー・イグジットをコールすると、ユーザー・イグジットが実行され、その後ステータス・コードがOracle Formsに戻されます。ユーザー・イグジットでは、Oracle Formsステータス行へのメッセージ表示、フィールド値の取得と設定、高速計算と表参照およびOracleデータの操作ができます。

ユーザー・イグジットを作成する理由

SQL*Formsでは、トリガー内でPL/SQLブロックを使用できます。したがって、ほとんどの場合は、ユーザー・イグジットをコールするかわりにPL/SQLのプロシージャ機能を使用できます。ユーザー・イグジットが必要になったときは、USER_EXIT関数を使用するとPL/SQLブロックからユーザー・イグジットをコールできます。SQL、PL/SQLまたはSQL*Formsコマンドに比べて、ユーザー・イグジットは記述方法も実装の方法も複雑です。したがって、ユーザー・イグジットの使用は、SQL、PL/SQLおよびSQL*Formsの範囲を超える処理の実行に限定するのが一般的です。通常は次のような処理に使用します。

ユーザー・イグジットの開発

この項ではSQL*Formsユーザー・イグジットの開発方法の概要を示します。詳細はこの後の項で説明します。


関連項目

Oracle Formsバージョン4で使用可能なEXEC TOOLSオプションの詳細は、「EXEC TOOLS文」 を参照してください。

ユーザー・イグジットをフォームに取り込むには、次の手順に従います。

ユーザー・イグジットの作成

次の種類の文を使用すると、SQL*Formsユーザー・イグジットを記述できます。

この項では、SQL*Formsとユーザー・イグジットの間での値の引渡しを可能にするEXEC TOOLS文を中心に説明します。

変数の要件

EXEC TOOLS文で使用される変数は、フォーム定義で使用されるフィールド名に対応している必要があります。

EXEC TOOLS文

EXEC TOOLS文は、ユーザー・イグジットからの読込み、設定および例外コールバックを処理する包括的な方法を提供することにより、基本的なOracle Toolsetをサポートします。次の説明はOracle Formsが中心になっていますが、Oracle Reportについても概念は同じです。

Toolsetユーザー・イグジットの作成

EXEC SQL、EXEC ORACLEおよびホスト言語文の他にも、次のEXEC TOOLS文を使用してOracle Formsユーザー・イグジットを記述できます。

  • SET

  • GET

  • SET CONTEXT

  • GET CONTEXT

  • MESSAGE

EXEC TOOLS GET文およびEXEC TOOLS SET文は、Oracle Formsの以前のバージョンで使用されていたEXEC IAF GET文およびEXEC IAF PUT文に相当します。ただし、IAF GETおよびIAF PUTとは異なり、TOOLS GETおよびTOOLS SETは標識変数を受け付けます。EXEC TOOLS MESSAGE文は、メッセージ処理関数sqliemに相当します。次に、すべてのEXEC TOOLS文について簡単に説明します。詳細は、Oracle Formsのオンライン・ヘルプおよび各システム固有のOracleマニュアルを参照してください。

EXEC TOOLS SET

EXEC TOOLS SET文はユーザー・イグジットからOracle Formsに値を渡します。この文は、特にホスト変数および定数の値をOracle Forms変数および項目に割り当てます。フォーム項目に渡された値は、ユーザー・イグジットで制御がフォームに戻った後に表示されます。EXEC TOOLS SET文を記述するには、次の構文を使用します。

EXEC TOOLS SET form_variable[, ...] 
     VALUES ({:host_variable :indicator | constant}[, ...]); 

form_variableは、Oracle Formsフィールド、block.field、システム変数、グローバル変数、またはこれらの項目のうち1つの値を含むホスト変数(先頭コロン付き)です。次の例では、ユーザー・イグジットによって従業員名をOracle Formsに渡します。

char ename[20];
short ename_ind;

...

    strcpy(ename, "MILLER");
    ename_ind = 0;
    EXEC TOOLS SET emp.ename VALUES (:ename :ename_ind);

この例で、emp.enameはOracle Formsのblock.fieldの1つです。

EXEC TOOLS GET

EXEC TOOLS GET文は、Oracle Formsからユーザー・イグジットに値を渡します。この文は、特にOracle Forms変数および項目の値をホスト変数に割り当てます。値が渡されるとすぐに、ユーザー・イグジットでそれらの値を任意の目的に使用できます。EXEC TOOLS GET文を記述するときは次の構文を使用してください。

EXEC TOOLS GET form_variable[, ...] 
    INTO :host_variable:indicator[, ...]; 

form_variableは、Oracle Formsフィールド、block.field、システム変数、グローバル変数、またはこれらの項目のうち1つの値を含むホスト変数(先頭コロン付き)です。次の例では、Oracle Formsはブロックからユーザー・イグジットに項目名を渡します。

...
char     name_buff[20];
VARCHAR  name_fld[20];
 
strcpy(name_fld.arr, "EMP.NAME");
name_fld.len = strlen(name_fld.arr);
EXEC TOOLS GET :name_fld INTO :name_buff;

EXEC TOOLS SET CONTEXT

EXEC TOOLS SET CONTEXT文は、後で別のユーザー・イグジットで使用するために、ユーザー・イグジットからのコンテキスト情報を保存します。ポインタ変数は、コンテキスト情報が格納されているメモリーのブロックを指します。SET CONTEXT文と併用するときは、情報を保持するためのグローバル変数を宣言する必要はありません。EXEC TOOLS SET CONTEXT文を記述するには、次の構文を使用します。

EXEC TOOLS SET CONTEXT :host_pointer_variable 
    IDENTIFIED BY context_name; 

context_nameは、未宣言の識別子またはコンテキスト領域を命名する文字ホスト変数(先頭コロン付き)です。

... 
char  *context_ptr; 
char  context[20]; 
 
strcpy(context, "context1") 
EXEC TOOLS SET CONTEXT :context IDENTIFIED BY application1; 

EXEC TOOLS GET CONTEXT

EXEC TOOLS GET CONTEXT文は、(SET CONTEXTによって保存されている)コンテキスト情報をユーザー・イグジットに取り出します。ホスト言語ポインタ変数は、コンテキスト情報が格納されているメモリーのブロックを指します。EXEC TOOLS GET CONTEXT文を記述するには、次の構文を使用します。

EXEC TOOLS GET CONTEXT context_name 
    INTO :host_pointer_variable; 

context_nameは、未宣言の識別子またはコンテキスト領域を命名する文字ホスト変数(先頭コロン付き)です。次の例では、ユーザー・イグジットは前に保管されたコンテキスト情報を取り出します。

... 
char  *context_ptr; 
 
EXEC TOOLS GET CONTEXT application1 INTO :context_ptr;  

EXEC TOOLS MESSAGE

EXEC TOOLS MESSAGE文は、ユーザー・イグジットからOracle Formsにメッセージを渡します。ユーザー・イグジットによりフォームに制御が戻った後に、メッセージがOracle Formsのメッセージ行に表示されます。EXEC TOOLS MESSAGE文を記述するには、次の構文を使用します。

EXEC TOOLS MESSAGE message_text [severity_code]; 

message_textは引用文字列または文字ホスト変数(先頭コロン付き)で、オプションのseverity_codeは整数定数または整数ホスト変数(先頭コロン付き)です。MESSAGE文に標識変数は指定できません。次の例では、ユーザー・イグジットからエラー・メッセージがOracle Formsに渡されます。

EXEC TOOLS MESSAGE 'Bad field name! Please reenter.'; 

ユーザー・イグジットのコール

SQL*Formsトリガーからユーザー・イグジットをコールするには、USER_EXIT(SQL*Formsで提供されます)という名前のパッケージ・プロシージャを使用します。使用する構文は次のとおりです。

USER_EXIT(user_exit_string [, error_string]);  

ここで、user_exit_stringにはユーザー・イグジットの名前とオプションのパラメータを指定して、error_stringにはユーザー・イグジットが異常終了したときにSQL*Formsにより発行されるエラー・メッセージを指定します。たとえば、次のトリガー・コマンドは、LOOKUPという名前のユーザー・イグジットをコールします。

USER_EXIT('LOOKUP'); 

ユーザー・イグジット文字列は引用符(二重引用符は不可)で囲んでください。

ユーザー・イグジットへのパラメータの引渡し

ユーザー・イグジットをコールすると、SQL*Formsは自動的に次のパラメータをユーザー・イグジットに渡します。

パラメータ 説明
コマンドライン ユーザー・イグジット文字列。
コマンドラインの長さ ユーザー・イグジット文字列の長さ(文字数)。
エラー・メッセージ 定義済の場合、エラー文字列(障害メッセージ)。
エラー・メッセージの長さ エラー文字列の長さ。
問合せモード ブール値。ユーザー・イグジットのコールが通常モードと問合せモードのどちらで行われたかを示します。

しかし、ユーザー・イグジット文字列を使用すると、追加パラメータをユーザー・イグジットに渡せます。たとえば次のトリガー・コマンドを使用すると、2つのパラメータと1つのエラー・メッセージがユーザー・イグジットLOOKUPに渡されます。

ユーザー・イグジット文字列は引用符(二重引用符は不可)で囲んでください。

USER_EXIT('LOOKUP 2025 A', 'Lookup failed');
 

次の例のように、この機能を使用してフィールド名をユーザー・イグジットに渡せます。

USER_EXIT('CONCAT firstname, lastname, address');
 

ただし、ユーザー・イグジット文字列の解析は、SQL*Formsではなくユーザー・イグジットによって実行されます。

フォームへの値のリターン

ユーザー・イグジットでは、SQL*Formsに制御が戻るときに必ずコードが戻されます。このコードはユーザー・イグジットが成功したか、失敗したか、致命的エラーが発生したかを示します。このリターン・コードはSQL*Formsによって定義されるintegerの整数定数です(次の項を参照)。この3種類の結果は次の意味を持ちます。

結果 意味
成功 ユーザー・イグジットでエラーが発生しませんでした。コール元のトリガー・ステップで逆戻りコード・スイッチが設定されていなければ、SQL*Formsは成功ラベルまたは次のステップに進みます。
失敗 ユーザー・イグジットで、フィールド内の無効値などのエラーが検出されました。このイグジットによって渡された任意指定のメッセージが、SQL*Forms画面下部のメッセージ行およびエラー表示画面に表示されます。SQL*Formsは行に影響を与えないSQL文に対するときと同様に応答します。
致命的エラー ユーザー・イグジットで、SQL文中の実行エラーなど、それ以上処理を続行できない条件が検出されました。このイグジットによって渡された任意指定のエラー・メッセージが、SQL*Formsエラー表示画面に表示されます。SQL*FormsはSQL文内の致命的エラーに対するときと同様に応答します。ユーザー・イグジットでフィールドの値が変更された後で失敗または致命的エラー・コードが戻ったときは、SQL*Formsはこの変更を破棄しません。また、逆戻りコード・スイッチが設定されているときに成功コードが戻されたときにも、SQL*Formsは変更を破棄しません。

IAP定数

リターン・コードとして使用する3つの記号定数がSQL*Formsによって定義されます。ホスト言語に応じて、これらの定数には文字IAPまたはSQLという接頭辞が付きます。たとえばIAPSUCC、IAPFAIL、IAPFTLなどと定義されます。

WHENEVERの使用方法

イグジット内でWHENEVER文を指定すると、不当なデータ型の変換(SQLERROR)、フォーム・フィールドにPUTされた値の切捨て(SQLWARNING)および行を戻さない問合せ(NOT FOUND)を検出できます。

次の例では、EXEC TOOLS GETルーチンとEXEC TOOLS PUTルーチン、およびEXEC TOOLS MESSAGE関数を使用するユーザー・イグジットの記述方法を示します。

int
myexit()
{
    char field1[20], field2[20], value1[20], value2[20];
    char result_value[20];
    char errmsg[80];
    int errlen;

    #include sqlca.h
    EXEC SQL WHENEVER SQLERROR GOTO sql_error;
    /* get field values into form */
    EXEC TOOLS GET :field1, :field2 INTO :value1, :value2;
    /* manipulate the values to obtain result_val */
    ...
    /* put result_val into form field result */
    EXEC TOOLS PUT result VALUES (:result_val);
    return IAPSUCC;   /* trigger step succeeded */

sql_error:
    strcpy(errmsg, CONCAT("MYEXIT", sqlca.sqlerrm.sqlerrmc);
    errlen = strlen(errmsg);
    EXEC TOOLS MESSAGE :errmsg ; /* send error msg to Forms */
    return IAPFAIL;

ユーザー・イグジットのプリコンパイルおよびコンパイル

ユーザー・イグジットは、スタンドアロン型のホスト・プログラムと同じ方法でプリコンパイルされます。ユーザー・イグジットのコンパイル方法については、システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドを参照してください。

サンプル・プログラム: ユーザー・イグジット

次の例にユーザー・イグジットを示します。

/**************************************************************
Sample Program 5:  SQL*Forms User Exit

This user exit concatenates form fields.  To call the user 
exit from a SQL*Forms trigger, use the syntax

   user_exit('CONCAT field1, field2, ..., result_field');

where user_exit is a packaged procedure supplied with SQL*Forms
and CONCAT is the name of the user exit.  A sample form named
CONCAT invokes the user exit.
**************************************************************/

#define min(a, b) ((a < b) ? a : b)
#include <stdio.h>
#include <string.h>

/* Include the SQL Communications Area, a structure through which
 * Oracle makes runtime status information such as error
 * codes, warning flags, and diagnostic text available to the
 * program.
 */
#include <sqlca.h>

/* All host variables used in embedded SQL in this example
 * appear in the Declare Section.
 */
EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR   field[81];
    VARCHAR   value[81];
    VARCHAR   result[241];
EXEC SQL END DECLARE SECTION;


/* Define the user exit, called "concat". */
int concat(cmd, cmdlen, msg, msglen, query)
char *cmd;     /* command line in trigger step ("CONCAT...") */
int  *cmdlen;  /* length of command line */
char *msg;     /* trigger step failure message from form */
int  *msglen;  /* length of failure message */
int  *query;   /* TRUE if invoked by post-query trigger,
                  FALSE otherwise */
{
    char *cp = cmd + 7;    /* pointer to field list in
                              cmd string; 7 characters
                              are needed for "CONCAT " */
    char *fp = (char*)&field.arr[0];  /* pointer to a field name in
                                         cmd string */
    char  errmsg[81];      /* message returned to SQL*Forms
                              on error */
    int   errlen;          /* length of message returned
                              to SQL*Forms */

/* Branch to label sqlerror if an ORACLE error occurs. */
    EXEC SQL WHENEVER SQLERROR GOTO sqlerror;

    result.arr[0] = '\0';

/* Parse field names from cmd string. */
    for (; *cp != '\0'; cp++)
    {
       if (*cp != ',' && *cp != ' ')
           /* Copy a field name into field.arr from cmd. */
       {
           *fp = *cp;
           fp++;
       }
       else
           if (*cp == ' ')
           {   /* Have whole field name now. */
               *fp = '\0';
               field.len = strlen((char *) field.arr);
               /* Get field value from form. */
               EXEC TOOLS GET :field INTO :value;
               value.arr[value.len] = '\0';
               strcat((char *) result.arr, (char *) value.arr);
               fp = (char *)&field.arr[0];  /* Reset field pointer. */
           }
    }

/* Have last field name now. */
    *fp = '\0';
    field.len = strlen((char *) field.arr);
    result.len = strlen((char *) result.arr);

/* Put result into form. */
    EXEC TOOLS PUT :field VALUES (:result);

/* Trigger step succeeded. */
    return(IAPSUCC);

sqlerror:
    strcpy(errmsg, "CONCAT: ");
    strncat(errmsg, sqlca.sqlerrm.sqlerrmc, min(72,
        sqlca.sqlerrm.sqlerrml));
    errlen = strlen(errmsg);
/* Pass error message to SQL*Forms status line. */
     EXEC TOOLS MESSAGE :errmsg ;
    return(IAPFAIL);  /* Trigger step failed. */
}

GENXTBユーティリティの使用方法

IAPXITモジュール内のIAPプログラム表IAPXTBには、IAP内にリンクされているそれぞれのユーザー・イグジット用のエントリが格納されています。IAPXTBはIAPに各ユーザー・イグジットの名前、位置およびホスト言語を指示します。新しいユーザー・イグジットをIAPに追加するときは、対応するエントリをIAPXTBに追加する必要があります。IAPXTBは、IAPXTBという同じ名前のデータベース表から導出されます。次のように、オペレーティング・システムのコマンドラインでGENXTBフォームを実行することで、データベースの表を修正できます。

RUNFORM GENXTB username/password 

定義するそれぞれのユーザー・イグジットについて、次の情報を入力できるフォームが表示されます。

IAPXTBデータベース表を変更してから、GENXTBユーティリティを使用してその表を読み込み、IAPXITモジュールとそれに含まれるIAPXTBプログラム表を定義するアセンブラまたはC言語のソース・プログラムを作成します。使用するソース言語は、オペレーティング・システムによって異なります。GENXTBユーティリティの構文は次のとおりです。

GENXTB username/password outfile 

outfileは、GENXTBが作成するアセンブラまたはC言語のソース・プログラムに指定する名前です。

SQL*Formsへのユーザー・イグジットのリンク

ユーザー・イグジットをコールするフォームの実行前に、フォームを実行するSQL*FormsのコンポーネントであるIAPにこのユーザー・イグジットをリンクする必要があります。ユーザー・イグジットは標準的なバージョンのIAPにリンクしたり、そのイグジットをコールするフォーム用の特別なバージョンのIAPにリンクしたりできます。

IAPの実行可能コピーを新規に作成するには、OracleライブラリおよびC言語のリンク・ライブラリからユーザー・イグジット・オブジェクト・モジュール、標準IAPモジュール、IAPXITモジュール、その他必要なモジュールをすべてリンクします。

リンク方法はシステムによって異なります。システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドで確認してください。

ガイドライン

この項では、一般的な問題を回避するためのガイドラインを示します。

イグジットの命名

ユーザー・イグジットの名前をOracleの予約語にしないでください。また、SQL*Formsコマンド名、関数コード名、SQL*Formsに使用される外部定義済の名前と競合を起こす名前は使用しないでください。ソース・コード内のユーザー・イグジットのエントリ・ポイントの名前は、ユーザー・イグジット自体の名前となります。このイグジット名は有効なC言語の関数名であり、同時に使用しているオペレーティング・システムの規則に従った有効なファイル名である必要があります。

SQL*Formsでは、検索前にそのユーザー・イグジットの名前が大文字に変換されます。したがって、イグジット名はソース・コード内では大文字になっている必要があります。

Oracleへの接続

ユーザー・イグジットでは、SQL*Formsにより確立された接続を使用してOracleと通信します。ただし、ユーザー・イグジットでSQL*Netを使用して任意のデータベースに追加の接続を確立できます。

I/Oコールの発行

ファイルI/Oはサポートされていますが、画面I/Oはサポートされていません。

ホスト変数の使用方法

スタンドアロン型のプログラムに適用されるホスト変数の制限事項は、ユーザー・イグジットにも適用されます。EXEC SQLおよびEXEC TOOLS文内では、ホスト変数の前にコロン(:)が必要です。ただし、EXEC TOOLS文では、ホスト配列は使用できません。

表の更新

一般に、ユーザー・イグジットではフォームに対応付けられたデータベースの表をUPDATEしないでください。たとえば、SQL*Forms作業領域でオペレータがレコードを更新した後で、対応付けられたデータベース表内の対応する行をUPDATEしたとします。このときトランザクションがCOMMITされると、SQL*Forms作業領域内のレコードがその表に適用され、ユーザー・イグジットのUPDATEは上書きされます。

コマンドの発行

Oracleでは、ユーザー・イグジットで実行された処理に限らず、SQL*Formsのオペレータが開始した作業もコミットまたはロールバックされるため、ユーザー・イグジットからはCOMMITまたはROLLBACKコマンドを発行しないでください。かわりに、SQL*FormsトリガーからCOMMITまたはROLLBACKコマンドを発行してください。データ定義コマンド(ALTER、CREATE、GRANTなど)についても同様です。それらのコマンドも実行の前後に暗黙的にCOMMITを発行するためです。