11 ユーザー・イグジットの作成
この章は、次の項で構成されています。
この章では、SQL*FormsおよびOracle Formsアプリケーション用のユーザー・イグジットの作成について重点的に説明します。まず、SQL*Formsアプリケーションをユーザー・イグジットとのインタフェースにするEXEC IAF文について学習します。次に、SQL*Formsユーザー・イグジットの作成方法とリンクの方法を学びます。また、EXEC TOOLS文をOracle Formsで使用する方法についても説明します。(SQL*FormsではEXEC TOOLSはサポートされていません。)このようにして、EXEC IAF文を使用することで、既存のアプリケーションやEXEC TOOLS文を強化し、新しいアプリケーションを作成できるようになります。内容は次のとおりです。
-
ユーザー・イグジットの一般的な使用方法
-
ユーザー・イグジットの作成
-
SQL*Formsとユーザー・イグジット間の値の受渡し
-
ユーザー・イグジットの実装
-
ユーザー・イグジットのコール
-
SQL*Formsユーザー・イグジットのガイドライン
-
Oracle FormsでのEXEC TOOLS文の使用方法
この章の内容は補足説明です。ユーザー・イグジットの詳細は、Oracle Formsリファレンス・マニュアル、Vol. 2の「SQL*Forms開発者リファレンス」および各システム固有のOracleマニュアルを参照してください。
11.1 ユーザー・イグジット
ユーザー・イグジットとは、特別な目的の処理を実行するために作成するホスト言語のサブルーチンのことで、SQL*Formsによってコールされます。ユーザー・イグジットにSQLコマンドやPL/SQLブロックを埋め込み、ホスト・プログラムの場合と同様にこれをプリコンパイルできます。
SQL*Formsトリガーからコールすると、ユーザー・イグジットが実行され、SQL*Formsにステータス・コードが戻されます(図11-1を参照)。ユーザー・イグジットでは、SQL*Formsステータス行へのメッセージの表示、フィールド値の取得と設定、Oracleデータの操作、高速計算および表参照、さらには別のデータベースへの接続もできます。
11.2 ユーザー・イグジットを作成する理由
SQL*Formsバージョン3では、トリガーでPL/SQLブロックを使用できます。したがって、ほとんどの場合、ユーザー・イグジットをコールするかわりに、PL/SQLのプロシージャ機能を使用できます。ユーザー・イグジットが必要になった場合は、USER_EXIT
関数を使用してPL/SQLブロックからコールできます。
SQL、PL/SQLまたはSQL*Formsのコマンドに比べて、ユーザー・イグジットは記述も実装も複雑です。したがって、SQL、PL/SQLおよびSQL*Formsの範囲を超える処理を実行する場合にかぎり、ユーザー・イグジットを使用することになります。一般的に次のような場合に使用します。
-
CやFORTRANなどの第3世代の言語で実行するとより迅速または簡単になる演算(数値積分など)
-
リアルタイムのデバイスまたは処理の制御(プリンタまたはグラフィックス・デバイスへの一連の命令の発行など)
-
拡張プロシージャ機能が必要なデータ操作(再帰ソートなど)
-
特殊なファイルI/O操作
11.3 ユーザー・イグジットの開発
この項ではSQL*Formsユーザー・イグジットの開発方法の概要を示します。詳細はこの後の項で説明します。Oracle Formsで利用できるEXEC TOOLS文の詳細は、「EXEC TOOLS文」を参照してください。
ユーザー・イグジットをフォームに組み込むには、次の手順に従います。
1. サポートされているホスト言語でユーザー・イグジットを記述します。
2. ソース・コードをプリコンパイルします。
3. プリコンパイルしたソース・コードをコンパイルします。
4. GENXTBユーティリティを使用してデータベース表IAPXTBを作成します。
5. SQL*FormsのGENXTBフォームを使用して、ユーザー・イグジット情報をデータベース表に挿入します。
6. GENXTBユーティリティを使用して表から情報を読み取り、IAPXITソース・モジュールを作成します。次に、ソース・モジュールをコンパイルします。
7. 標準IAPオブジェクト・モジュール、ユーザー・イグジット・オブジェクト・モジュール、手順6で作成したIAPXITオブジェクト・モジュールをリンクして、新しいIAP(フォームを実行するSQL*Formsコンポーネント)を作成します。
8. このフォームで、ユーザー・イグジットをコールするトリガーを定義します。
9. オペレータがフォームを実行する際には、新しいIAPを使用するように指示します。新しいIAPが標準のものに置き換わる場合、これは不要です。詳細は、各システム固有のOracleマニュアルを参照してください。
11.4 ユーザー・イグジットの作成
-
ホスト言語
-
EXEC SQL
-
EXEC ORACLE
-
EXEC IAF GET
-
EXEC IAF PUT
この項では、SQL*Formsとユーザー・イグジット間での値の受渡しを可能にするEXEC IAF GET
文およびEXEC IAF EXEC IAF PUT
文を中心に説明します。
11.4.2 IAF GET文
この文を使用すると、ユーザー・イグジットでフォーム上のフィールドから値を取得し、ホスト変数に割り当てることができます。ユーザー・イグジットでは、それらの値を計算、データ操作、更新などに使用できます。GET
文の構文は次のとおりです。
EXEC IAF GET field_name1, field_name2, ... INTO :host_variable1, :host_variable2, ...;
field_nameには、次のSQL*Forms変数のどれを指定してもかまいません。
-
フィールド
-
block.field
-
システム変数
-
グローバル変数
-
フィールド、block.field、システム変数またはグローバル変数の値を含むホスト変数(前にコロンが付く)
field_nameは修飾されていない場合、一意であることが必要です。
次の例は、ユーザー・イグジットでどのようにフィールド値をGETし、ホスト変数に割り当てるかを示しています。
EXEC IAF GET employee.job INTO :new_job;
フィールド値はすべて文字列です。値を取得すると、GET
文はフィールド値を対応するホスト変数のデータ型に変換します。無効またはサポートされていないデータ型への変換が試みられると、エラーが発生します。
前の例では、block.fieldの指定に定数が使用されています。ブロック名およびフィールド名の指定には、次のようにホスト文字列も使用できます。
set blkfld = 'employee.job'; EXEC IAF GET :blkfld INTO :new_job;
フィールドが一意でない場合、ホスト文字列には間にピリオドの入った完全なblock.field参照が含まれている必要があります。たとえば、次の使用方法は無効です。
set blk = 'employee'; set fld = 'job'; EXEC IAF GET :blk.:fld INTO :new_job;
1つのGET
文のフィールド・リストに明示的フィールド名とストアド・フィールド名を混在させることはできますが、1つのフィールド参照ではできません。たとえば、次の使用方法は無効です。
set fld = 'job'; EXEC IAF GET employee.:fld INTO :new_job;
11.4.3 IAF PUT文
この文を使用すると、ユーザー・イグジットで定数およびホスト変数の値をフォームのフィールドに指定できます。このようにして、ユーザー・イグジットによりSQL*Formsの画面に任意の値やメッセージを表示できます。PUT
文の構文は次のとおりです。
EXEC IAF PUT field_name1, field_name2, ... VALUES (:host_variable1, :host_variable2, ...);
field_nameには、次のSQL*Forms変数のどれを指定してもかまいません。
-
フィールド
-
block.field
-
システム変数
-
グローバル変数
-
フィールド、block.field、システム変数またはグローバル変数の値を含むホスト変数(前にコロンが付く)
次の例では、ユーザー・イグジットでどのように数字の定数、文字列定数およびホスト変数をフォームのフィールドにPUTするかを示しています。
EXEC IAF PUT employee.number, employee.name, employee.job VALUES (7934, 'MILLER', :new_job);
GET
と同様に、PUT
でもホスト文字列を使用して、次のようにブロックやフィールドの名前を指定できます。
set blkfld = 'employee.job'; EXEC IAF PUT :blkfld VALUES (:new_job);
キャラクタモードの端末では、フィールドにPUT
された値は、フィールドが現在の表示ページ上にある場合、割り当てられたときではなく、ユーザー・イグジットから戻されたときに表示されます。ブロックモードの端末では、次回デバイスからフィールドが読み取られたときに値が表示されます。
ユーザー・イグジットで1つのフィールドの値が数回変更された場合、最後の変更のみが有効です。
11.5 ユーザー・イグジットのコール
SQL*Formsトリガーからユーザー・イグジットをコールするには、USER_EXIT
(SQL*Forms付属)というパッケージ・プロシージャを使用します。次の構文を使用します。
USER_EXIT(user_exit_string [, error_string]);
user_exit_stringには、ユーザー・イグジットの名前とオプションのパラメータを指定し、error_stringには、ユーザー・イグジットが異常終了したときにSQL*Formsにより発行されるエラー・メッセージを指定します。たとえば、次のトリガー・コマンドは、LOOKUP
という名前のユーザー・イグジットをコールします。
USER_EXIT('LOOKUP');
ユーザー・イグジットの文字列は、一重(二重ではない)引用符で囲まれていることに注意してください。
11.6 ユーザー・イグジットへのパラメータの引渡し
ユーザー・イグジットをコールすると、SQL*Formsでは自動的に次のパラメータをユーザー・イグジットに渡します。
-
コマンドラインは、ユーザー・イグジット文字列です。
-
コマンドラインの長さは、ユーザー・イグジット文字列の長さ(文字数)です。
-
エラー・メッセージは、定義されている場合、エラー文字列(障害メッセージ)です。
-
エラー・メッセージの長さは、エラー文字列の長さです。
-
問合せモードは、ユーザー・イグジットのコールが通常モードと問合せモードのどちらで行われたかを示すブール値です。
ただし、ユーザー・イグジット文字列を使用すると、追加のパラメータをユーザー・イグジットに渡せます。たとえば、次のトリガー・コマンドでは、2つのパラメータと1つのエラー・メッセージがユーザー・イグジットLOOKUP
に渡されます。
USER_EXIT('LOOKUP 2025 A', 'Lookup failed');
この機能を使用すれば、次の例のように、フィールド名をユーザー・イグジットに渡せます。
USER_EXIT('CONCAT firstname, lastname, address');
ただし、ユーザー・イグジット文字列を解析は、SQL*Formsではなく、ユーザー・イグジットに依存します。
11.7 フォームへの値の返却
ユーザー・イグジットでは、SQL*Formsに制御が戻るとき、成功したか、失敗したかまたは致命的エラーが発生したかのいずれの状態かを示すコードも必ず戻します。このリターン・コーは、プリコンパイラによって生成される整数の定数です(この項の「例」を参照)。この3種類の結果はの意味は次のとおりです。
成功: ユーザー・イグジットでエラーが発生しませんでした。コール元の逆戻りリターン・コード・スイッチが設定されていなければ、SQL*Formsは成功ラベルまたは次のステップに進みます。
失敗: ユーザー・イグジットで、フィールド内の無効値などのエラーが検出されました。このイグジットによって渡されたオプションのメッセージが、SQL*Forms画面の下部のメッセージ行およびエラー表示画面に表示されます。SQL*Formsでは、行に影響を与えないSQL文に対する場合と同様に応答します。
致命的エラー: ユーザー・イグジットで、SQL文中の実行エラーなど、それ以上処理を続行できない状態が検出されました。イグジットによって渡されたオプションのエラー・メッセージが、SQL*Formsのエラー表示画面に表示されます。SQL*Formsでは、致命的なSQLエラーに対するときと同様に応答します。
ユーザー・イグジットでフィールドの値が変更された後で、失敗または致命的エラーのコードが戻された場合、SQL*Formsはこの変更を廃棄しません。また、逆戻りリターン・コード・スイッチが設定されていて、成功コードが戻されたときにも、SQL*Formsは変更を廃棄しません。
11.7.1 IAP定数
プリコンパイラでは、リターン・コードとして使用する3つの記号定数が生成されます。これらにはIAPの接頭辞が付きます。たとえば、3つの定数はIAPSUCC、IAPFAIL、IAPFTLのようになります。
11.7.2 SQLIEM関数
関数SQLIEMをコールすると、トリガー手順が、失敗するか、表示画面で回復不能のエラーを引き起こした場合に、SQL*Formsがメッセージ行に表示するエラー・メッセージをユーザー・イグジットで指定できます。指定したメッセージは、その手順のために定義されたいかなるメッセージよりも優先されます。
SQLIEM関数コールの構文は次のとおりです。
SQLIEM (error_message, message_length);
ここで、error_messageとmessage_lengthは、それぞれ文字変数と整数の変数です。Oracle Precompilersでは、適切な外部関数宣言が生成されます。どちらのパラメータも参照によって渡します。つまり、値でなくアドレスを渡します。SQLIEMはSQL*Forms関数です。他のOracleツールからはコールできません。
11.8 例
次の例では、一般的なユーザー・イグジットの記述方法を示します。ホスト・プログラムと同様、ユーザー・イグジットにも宣言部とSQLCAがあることに注意してください。
-- subroutine MYEXIT EXEC SQL BEGIN DECLARE SECTION; field1 CHARACTER(20); field2 CHARACTER(20); value1 CHARACTER(20); value2 CHARACTER(20); result_val CHARACTER(20); EXEC SQL END DECLARE SECTION; errmsg CHARACTER(80); errlen INTEGER; EXEC SQL INCLUDE SQLCA; EXEC SQL WHENEVER SQLERROR GOTO sqlerror; -- get field values from form EXEC IAF GET :field1, :field2 INTO :value1, :value2; -- manipulate values to obtain result_val -- put result_val into form field EXEC IAF PUT result VALUES (:result_val); return(IAPSUCC); -- trigger step succeeded sqlerror: set errmsg = CONCAT('MYEXIT: ', sqlca.sqlerrm.sqlerrmc); set errlen = LENGTH(errmsg); sqliem(errmsg, errlen); -- pass error message to SQL*Forms return(IAPFAIL); -- trigger step failed
使用するホスト言語の完全な例は、各ホスト言語の補足資料を参照してください。
11.9 ユーザー・イグジットのプリコンパイルおよびコンパイルについて
ユーザー・イグジットは、スタンドアロン型のホスト・プログラムと同様にプリコンパイルされます。Oracleプリコンパイラの実行を参照してください。
ユーザー・イグジットのコンパイルの手順は、システム固有のOracleマニュアルを参照してください。
11.10 GENXTBユーティリティの使用について
IAPXITモジュール内のIAPプログラム表IAPXTBには、IAPにリンクされているユーザー・イグジットごとに1つのエントリが格納されています。IAPXTBはIAPに各ユーザー・イグジットの名前、位置およびホスト言語を指示します。新しいユーザー・イグジットをIAPに追加するときは、対応するエントリをIAPXTBに追加する必要があります。
IAPXTBは、IAPXTBという同じ名前のデータベース表から導出されます。次のように、オペレーティング・システムのコマンドラインでGENXTBフォームを実行することで、データベース表を変更できます。
RUNFORM GENXTB username/password
定義するユーザー・イグジットごとに次の情報を入力できるフォームが表示されます。
-
イグジット名
-
ホスト言語コード(
COB
、FOR
、PAS
またはPLI
) -
作成日
-
最終変更日
-
コメント
IAPXTBデータベース表を変更してから、GENXTBユーティリティを使用して表を読み取り、IAPXITモジュールとそれに含まれるIAPXTBプログラム表を定義するアセンブラまたはC言語のソース・プログラムを作成します。使用するソース言語は、オペレーティング・システムによって異なります。GENXTBユーティリティを実行するための構文は次のとおりです。
GENXTB username/password outfile
outfileは、GENXTBが作成するアセンブラまたはソース・プログラムに指定する名前です。
11.12 SQL*Formsユーザー・イグジットのガイドライン
11.12.1 イグジットの命名
ユーザー・イグジットの名前にはOracleの予約語を指定しないでください。また、SQL*Formsコマンド、関数コード、SQL*Formsで使用される外部定義の名前と競合する名前も使用しないでください。
SQL*Formsでは、ユーザー・イグジットの検索前に、その名前が大文字に変換されます。したがって、イグジット名は、大文字と小文字を区別するホスト言語の場合、ソース・コードで大文字になっている必要があります。
ソース・コード内のユーザー・イグジット・エントリ・ポイントの名前は、ユーザー・イグジット自体の名前になります。このイグジット名は、ホスト言語とオペレーティング・システムにとって有効なファイル名であることが必要です。
11.12.2 Oracleへの接続
ユーザー・イグジットでは、SQL*Formsによって確立された接続を使用してOracleと通信します。ただし、ユーザー・イグジットでSQL*Netを使用して任意のデータベースに追加の接続を確立できます。詳細は、「同時接続」を参照してください。
11.12.3 I/Oコールの発行
SQL*Forms I/Oルーチンは、ホスト言語のプリンタI/Oルーチンと競合する可能性があります。その場合、ユーザー・イグジットではプリンタI/Oコールを発行できません。ファイルI/Oはサポートされていますが、画面I/Oはサポートされていません。
11.12.4 ホスト変数の使用
スタンドアロン型のプログラムでの変数の使用に対する制限事項は、ユーザー・イグジットにも適用されます。EXEC SQL文およびEXEC IAF文では、ホスト変数はユーザー・イグジットの宣言部で名前を指定し、前にコロンを付ける必要があります。ただし、EXEC IAF文では、ホスト配列は使用できません。
11.12.5 表の更新
一般に、ユーザー・イグジットでは、フォームに関連付けられたデータベース表をUPDATE
しないでください。たとえば、SQL*Forms作業領域でオペレータがレコードを更新した後で、ユーザー・イグジットが関連付けられたデータベース表内の対応する行をUPDATE
したとします。このときトランザクションがCOMMIT
されると、SQL*Forms作業領域内のレコードがその表に適用され、ユーザー・イグジットのUPDATE
は上書きされます。
11.13 EXEC TOOLS文
EXEC TOOLS
文では、ユーザー・イグジットからの取得、設定および例外コールバックを処理する包括的な方法を提供することにより、基本的なOracle Toolset(Oracle Forms、Oracle ReportsおよびOracle Graphics)をサポートします。この後の説明はOracle Formsが中心になっていますが、Oracle ReportsおよびOracle Graphicsについても概念は同じです。
EXEC SQL、EXEC ORACLEおよびホスト言語文の他にも、次のEXEC TOOLS文を使用してOracle Formsユーザー・イグジットを記述できます。
-
SET
-
GET
-
SET CONTEXT
-
GET CONTEXT
-
MESSAGE
EXEC TOOLS
GET
文およびEXEC TOOLS SET
文は、SQL*Formsで使用されるEXEC IAF GET
文およびEXEC IAF PUT
文に相当します。IAF GETおよびIAF PUT
とは異なり、TOOLS
GET
およびTOOLS SET
はインジケータ変数を受け入れます。EXEC TOOLS
MESSAGE
文は、メッセージ処理関数のSQLIEMに相当します。EXEC TOOLS
SET
CONTEXT
文およびEXEC TOOLS GET
CONTEXT
文は新しく、SQL*Formsバージョン3にはありません。
注意:
COBOLおよびFORTRANにはポインタ・データ型がないため、Pro*COBOLまたはPro*FORTRANのプログラムでは、SET
CONTEXT
文およびGET
CONTEXT
文は使用できません。
11.13.1 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のフィールド、パラメータ、システム変数、グローバル変数、またはこれらのうちの1つの名前を含むホスト変数(接頭辞としてコロンが付く)です。
次のPro*Cの例では、ユーザー・イグジットによって従業員名(オプションのインジケータ付き)がOracle Formsに渡されます。
EXEC SQL BEGIN DECLARE SECTION; ... char ename[20]; short ename_ind; EXEC SQL END DECLARE SECTION; ... strcpy(ename, "MILLER"); ename_ind = 0; EXEC TOOLS SET emp.ename VALUES (:ename:ename_ind);
この例で、emp.enameはOracle Formsのblock.fieldです。
11.13.2 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のフィールド、パラメータ、システム変数、グローバル変数、またはこれらのうちの1つの名前を含むホスト変数です。
次の例では、Oracle Formsがblock.fieldのemp.enameからユーザー・イグジットに従業員名を渡します。
EXEC SQL BEGIN DECLARE SECTION; ... char ename[20]; EXEC SQL END DECLARE SECTION; ... EXEC TOOLS GET emp.ename INTO :ename;
11.13.3 EXEC TOOLS SET CONTEXT
EXEC TOOLS
SET
CONTEXT
文を使用すると、あるユーザー・イグジット・コールのコンテキスト情報を、別のユーザー・イグジット・コールのために保存できます。SET
CONTEXT
は、EXEC TOOLS
GET
CONTEXT
文で後から参照できるホスト言語のポインタ変数の名前を指定します。ポインタ変数は、コンテキスト情報が格納されているメモリーのブロックを指します。SET
CONTEXT
文を使用すれば、情報を保存するためにグローバル変数を宣言する必要はありません。
EXEC TOOLS
SET
CONTEXT
文を記述するには、次の構文を使用します。
EXEC TOOLS SET CONTEXT :host_pointer_variable [IDENTIFIED] BY context_name;
オプションのIDENTIFIEDキーワードは読みやすさを改善するために使用でき、context_nameは未宣言の識別子、またはコンテキスト領域を命名する文字ホスト変数です。
次の例では、ユーザー・イグジットで、後から使用するためのコンテキスト情報を保存します。
EXEC SQL BEGIN DECLARE SECTION; ... char context1[30]; EXEC SQL END DECLARE SECTION; ... strcpy(context1, "This is context1"); EXEC TOOLS SET CONTEXT :context1 BY my_app1;
この例では、コンテキスト名my_app1は未宣言の識別子です。C言語の場合、引数としてCHAR型の配列が使用されているとき、配列名はその配列に対するポインタと同じになります。
11.13.4 EXEC TOOLS GET CONTEXT
EXEC TOOLS
GET
CONTEXT
文は、ホスト言語のポインタ変数の値を取得して、ユーザー・イグジットに渡します。ポインタ変数は、コンテキスト情報が格納されているメモリーのブロックを指します。
EXEC TOOLS
GET
CONTEXT
文を記述するには、次の構文を使用します。
EXEC TOOLS GET CONTEXT context_name INTO :host_pointer_variable;
context_nameは、未宣言の識別子、またはコンテキスト領域を命名する文字ホスト変数です。
次のPro*Cの例では、ユーザー・イグジットは、前に保存されたコンテキスト情報に対するポインタを取得します。
EXEC SQL BEGIN DECLARE SECTION; ... char *ctx_ptr; EXEC SQL END DECLARE SECTION; ... EXEC TOOLS GET CONTEXT my_app1 INTO :ctx_ptr;
この例では、コンテキスト名my_app1は未宣言の識別子です。
11.13.5 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
文では、インジケータ変数は受け入れられません。
次のPro*Cの例では、ユーザー・イグジットからOracle Formsに、エラー・メッセージと重大度コードが渡されます。
EXEC TOOLS MESSAGE 'Bad field name! Please reenter.' 15;