20 ユーザー・イグジット
この章では、Oracleツール・アプリケーション用のユーザー・イグジットの作成方法を説明します。C言語のサブルーチンを使用すると、SQL*FormsおよびOracle Formsよりも迅速で、しかも簡単に特定の作業を実行できることがわかります。この章のトピックは、次のとおりです:
この章の内容は補足説明です。ユーザー・イグジットの詳細は、SQL*Forms開発者リファレンス、Oracle Formsリファレンス・マニュアル、Vol. 2および各システム固有のOracleドキュメントを参照してください。
20.1 ユーザー・イグジット
ユーザー・イグジットとは、特別な目的の処理を実行するために作成するC言語のサブルーチンを指します。このサブルーチンはOracle Formsによってコールされます。ユーザー・イグジットにSQL文およびPL/SQLブロックを組み込み、その後ホスト・プログラムの場合と同様にこれをプリコンパイルできます。
Oracle Formsバージョン3のトリガーからユーザー・イグジットをコールすると、ユーザー・イグジットが実行され、その後ステータス・コードがOracle Formsに戻されます。ユーザー・イグジットでは、Oracle Formsステータス行へのメッセージ表示、フィールド値の取得と設定、高速計算と表参照およびOracleデータの操作ができます。
20.2 ユーザー・イグジットを作成する理由
SQL*Formsでは、トリガー内でPL/SQLブロックを使用できます。したがって、ほとんどの場合、ユーザー・イグジットをコールするかわりに、PL/SQLのプロシージャ機能を使用できます。ユーザー・イグジットが必要になったときは、USER_EXIT関数を使用するとPL/SQLブロックからユーザー・イグジットをコールできます。SQL、PL/SQLまたはSQL*Formsのコマンドに比べて、ユーザー・イグジットは記述も実装も複雑です。したがって、SQL、PL/SQLおよびSQL*Formsの範囲を超える処理を実行する場合にかぎり、ユーザー・イグジットを使用することになります。通常は次のような処理に使用します。
-
C言語などの第3世代の言語内で実行すると迅速かつ簡単になる演算(数値積分など)
-
リアルタイム・デバイスや処理の制御(プリンタまたはグラフィックス・デバイスへの命令の発行など)
-
拡張プロシージャ機能が必要なデータ操作(再帰ソートなど)
-
特殊なファイルI/O操作
20.3 ユーザー・イグジットの開発について
この項ではSQL*Formsユーザー・イグジットの開発方法の概要を示します。詳細はこの後の項で説明します。
ユーザー・イグジットをフォームに組み込むには、次の手順に従います。
-
Pro*Cでユーザー・イグジットを記述します。
-
ソース・コードをプリコンパイルします。
-
手順2で生成された.cファイルをコンパイルします。
-
GENXTBユーティリティを使用してデータベース表IAPXTBを作成します。
-
SQL*FormsのGENXTBフォームを使用して、ユーザー・イグジット情報を表に挿入します。
-
GENXTBユーティリティを使用して表から情報を読み込み、IAPXITソース・コード・モジュールを作成します。次に、ソース・コード・モジュールをコンパイルします。
-
標準SQL*Formsモジュール、ユーザー・イグジットのオブジェクト、手順6で作成したIAPXITオブジェクトをリンクして、新しいSQL*Forms実行可能プログラムを作成します。
-
このフォーム内に、ユーザー・イグジットをコールするためのトリガーを定義します。
-
オペレータがフォームを実行する場合、新しいIAPを使用するように通知してください。新しいIAPが標準のものに置き換わる場合、これは不要です。詳細は、各システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドを参照してください。
関連項目
20.4 ユーザー・イグジットの作成について
次の種類の文を使用すると、SQL*Formsユーザー・イグジットを記述できます。
-
C言語のコード
-
EXEC SQL
-
EXEC ORACLE
-
EXEC TOOLS
この項では、SQL*Formsとユーザー・イグジットの間での値の引渡しを可能にするEXEC TOOLS文を中心に説明します。
20.5 EXEC TOOLS文
EXEC TOOLS文は、ユーザー・イグジットからの読込み、設定および例外コールバックを処理する包括的な方法を提供することにより、基本的なOracle Toolsetをサポートします。次の説明はOracle Formsが中心になっていますが、Oracle Reportについても概念は同じです。
20.5.1 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リファレンス・マニュアル、Vol. 2を参照してください。
20.5.2 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です。
20.5.3 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;
20.5.4 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;
20.5.5 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;
20.5.6 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.';
20.6 ユーザー・イグジットのコールについて
SQL*Formsトリガーからユーザー・イグジットをコールするには、USER_EXIT(SQL*Formsで提供されます)という名前のパッケージ・プロシージャを使用します。次の構文を使用します。
USER_EXIT(user_exit_string [, error_string]);
user_exit_stringには、ユーザー・イグジットの名前とオプションのパラメータを指定し、error_stringには、ユーザー・イグジットが異常終了したときにSQL*Formsにより発行されるエラー・メッセージを指定します。たとえば、次のトリガー・コマンドは、LOOKUPという名前のユーザー・イグジットをコールします。
USER_EXIT('LOOKUP');
ユーザー・イグジットの文字列は、一重(二重ではない)引用符で囲まれていることに注意してください。
20.7 ユーザー・イグジットへのパラメータの引渡しについて
ユーザー・イグジットをコールすると、SQL*Formsは自動的に次のパラメータをユーザー・イグジットに渡します。
パラメータ | 説明 |
---|---|
コマンドライン |
ユーザー・イグジット文字列。 |
コマンドラインの長さ |
ユーザー・イグジット文字列の長さ(文字数)。 |
エラー・メッセージ |
定義済の場合、エラー文字列(障害メッセージ)。 |
エラー・メッセージの長さ |
エラー文字列の長さ。 |
問合せモード |
ブール値。ユーザー・イグジットのコールが通常モードと問合せモードのどちらで行われたかを示します。 |
しかし、ユーザー・イグジット文字列を使用すると、追加パラメータをユーザー・イグジットに渡せます。たとえば次のトリガー・コマンドを使用すると、2つのパラメータと1つのエラー・メッセージがユーザー・イグジットLOOKUPに渡されます。
ユーザー・イグジットの文字列は、一重(二重ではない)引用符で囲まれていることに注意してください。
USER_EXIT('LOOKUP 2025 A', 'Lookup failed');
この機能を使用すれば、次の例のように、フィールド名をユーザー・イグジットに渡せます。
USER_EXIT('CONCAT firstname, lastname, address');
ただし、ユーザー・イグジット文字列を解析は、SQL*Formsではなく、ユーザー・イグジットに依存します。
20.8 フォームへの値の返却について
ユーザー・イグジットでは、SQL*Formsに制御が戻るとき、成功したか、失敗したかまたは致命的エラーが発生したかのいずれの状態かを示すコードも必ず戻します。このリターン・コードはSQL*Formsによって定義される整数定数です(次の項を参照)。この3種類の結果はの意味は次のとおりです。
20.9 ユーザー・イグジットの使用例
次の例では、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;
20.10 ユーザー・イグジットのプリコンパイルおよびコンパイルについて
ユーザー・イグジットは、スタンドアロン型のホスト・プログラムと同様にプリコンパイルされます。ユーザー・イグジットのコンパイル方法については、システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドを参照してください。
関連項目
20.11 サンプル・プログラム: ユーザー・イグジット
次の例にユーザー・イグジットを示します。
/************************************************************** 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. */ }
20.12 GENXTBユーティリティの使用について
IAPXITモジュール内のIAPプログラム表IAPXTBには、IAP内にリンクされているそれぞれのユーザー・イグジット用のエントリが格納されています。IAPXTBはIAPに各ユーザー・イグジットの名前、位置およびホスト言語を指示します。新しいユーザー・イグジットをIAPに追加するときは、対応するエントリをIAPXTBに追加する必要があります。IAPXTBは、IAPXTBという同じ名前のデータベース表から導出されます。次のように、オペレーティング・システムのコマンドラインでGENXTBフォームを実行することで、データベースの表を修正できます。
RUNFORM GENXTB username/password
定義するそれぞれのユーザー・イグジットについて、次の情報を入力できるフォームが表示されます。
-
イグジット名
-
C言語コード
-
作成日
-
最終変更日
-
コメント
IAPXTBデータベース表を変更してから、GENXTBユーティリティを使用して表を読み取り、IAPXITモジュールとそれに含まれるIAPXTBプログラム表を定義するアセンブラまたはC言語のソース・プログラムを作成します。使用するソース言語は、オペレーティング・システムによって異なります。GENXTBユーティリティを実行するための構文は次のとおりです。
GENXTB username/password outfile
関連項目
20.13 SQL*Formsへのユーザー・イグジットのリンクについて
ユーザー・イグジットをコールするフォームの実行前に、フォームを実行するSQL*FormsのコンポーネントであるIAPにこのユーザー・イグジットをリンクする必要があります。ユーザー・イグジットは標準的なバージョンのIAPにリンクしたり、そのイグジットをコールするフォーム用の特別なバージョンのIAPにリンクしたりできます。
IAPの実行可能コピーを新規に作成するには、OracleライブラリおよびC言語のリンク・ライブラリからユーザー・イグジット・オブジェクト・モジュール、標準IAPモジュール、IAPXITモジュール、その他必要なモジュールをすべてリンクします。
リンク方法はシステムによって異なります。システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドで確認してください。
20.14 ガイドライン
この項では、一般的な問題を回避するためのガイドラインを示します。
20.14.1 イグジットの命名について
ユーザー・イグジットの名前をOracleの予約語にしないでください。また、SQL*Formsコマンド、関数コード、SQL*Formsで使用される外部定義の名前と競合する名前も使用しないでください。ソース・コード内のユーザー・イグジット・エントリ・ポイントの名前は、ユーザー・イグジット自体の名前になります。このイグジット名は有効なC言語の関数名であり、同時に使用しているオペレーティング・システムの規則に従った有効なファイル名である必要があります。
SQL*Formsでは、ユーザー・イグジットの検索前に、その名前が大文字に変換されます。したがって、イグジット名はソース・コード内では大文字になっている必要があります。
20.14.2 Oracleへの接続について
ユーザー・イグジットでは、SQL*Formsにより確立された接続を使用してOracleと通信します。ただし、ユーザー・イグジットでOracle Net Servicesを使用して任意のデータベースに追加の接続を確立できます。
関連項目
20.14.4 ホスト変数の使用方法について
スタンドアロン型のプログラムでの変数の使用に対する制限事項は、ユーザー・イグジットにも適用されます。EXEC SQLおよびEXEC TOOLS文内では、ホスト変数の前にコロン(:)が必要です。ただし、EXEC TOOLS文では、ホスト配列は使用できません。
20.14.5 表の更新について
一般に、ユーザー・イグジットではフォームに対応付けられたデータベースの表をUPDATEしないでください。たとえば、SQL*Forms作業領域でオペレータがレコードを更新した後で、対応付けられたデータベース表内の対応する行をUPDATEしたとします。このときトランザクションがCOMMITされると、SQL*Forms作業領域内のレコードがその表に適用され、ユーザー・イグジットのUPDATEは上書きされます。