この章では、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の範囲を超える処理の実行に限定するのが一般的です。通常は次のような処理に使用します。
C言語などの第3世代の言語内で実行すると迅速かつ簡単になる演算(数値積分など)
リアルタイム・デバイスや処理の制御(プリンタまたはグラフィックス・デバイスへの命令の発行など)
拡張プロシージャ機能が必要なデータ操作(再帰ソートなど)
特殊なファイルI/O処理
この項ではSQL*Formsユーザー・イグジットの開発方法の概要を示します。詳細はこの後の項で説明します。
ユーザー・イグジットをフォームに取り込むには、次の手順に従います。
Pro*Cでユーザー・イグジットを記述します。
ソース・コードをプリコンパイルします。
手順2で生成された.cファイルをコンパイルします。
GENXTBユーティリティを使用してデータベース表IAPXTBを作成します。
SQL*FormsのGENXTBフォームを使用して、ユーザー・イグジット情報を表に挿入します。
GENXTBユーティリティを使用して表から情報を読み込み、IAPXITソース・コード・モジュールを作成します。次に、ソース・コード・モジュールをコンパイルします。
標準SQL*Formsモジュール、ユーザー・イグジットのオブジェクト、手順6で作成したIAPXITオブジェクトをリンクして、新しいSQL*Forms実行可能プログラムを作成します。
このフォーム内に、ユーザー・イグジットをコールするためのトリガーを定義します。
オペレータがフォームを実行する場合、新しいIAPを使用するように通知してください。標準フォームをこの新しいIAPで置き換えるときは、この通知は必要ありません。詳細は、各システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドを参照してください。
次の種類の文を使用すると、SQL*Formsユーザー・イグジットを記述できます。
C言語のコード
EXEC SQL
EXEC ORACLE
EXEC TOOLS
この項では、SQL*Formsとユーザー・イグジットの間での値の引渡しを可能にするEXEC TOOLS文を中心に説明します。
EXEC TOOLS文は、ユーザー・イグジットからの読込み、設定および例外コールバックを処理する包括的な方法を提供することにより、基本的なOracle Toolsetをサポートします。次の説明はOracle Formsが中心になっていますが、Oracle Reportについても概念は同じです。
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文はユーザー・イグジットから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文は、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文は、後で別のユーザー・イグジットで使用するために、ユーザー・イグジットからのコンテキスト情報を保存します。ポインタ変数は、コンテキスト情報が格納されているメモリーのブロックを指します。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文は、(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文は、ユーザー・イグジットから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種類の結果は次の意味を持ちます。
次の例では、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. */ }
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
ユーザー・イグジットをコールするフォームの実行前に、フォームを実行するSQL*FormsのコンポーネントであるIAPにこのユーザー・イグジットをリンクする必要があります。ユーザー・イグジットは標準的なバージョンのIAPにリンクしたり、そのイグジットをコールするフォーム用の特別なバージョンのIAPにリンクしたりできます。
IAPの実行可能コピーを新規に作成するには、OracleライブラリおよびC言語のリンク・ライブラリからユーザー・イグジット・オブジェクト・モジュール、標準IAPモジュール、IAPXITモジュール、その他必要なモジュールをすべてリンクします。
リンク方法はシステムによって異なります。システム固有のOracleインストレーション・ガイドまたはユーザーズ・ガイドで確認してください。
この項では、一般的な問題を回避するためのガイドラインを示します。
ユーザー・イグジットの名前をOracleの予約語にしないでください。また、SQL*Formsコマンド名、関数コード名、SQL*Formsに使用される外部定義済の名前と競合を起こす名前は使用しないでください。ソース・コード内のユーザー・イグジットのエントリ・ポイントの名前は、ユーザー・イグジット自体の名前となります。このイグジット名は有効なC言語の関数名であり、同時に使用しているオペレーティング・システムの規則に従った有効なファイル名である必要があります。
SQL*Formsでは、検索前にそのユーザー・イグジットの名前が大文字に変換されます。したがって、イグジット名はソース・コード内では大文字になっている必要があります。
ユーザー・イグジットでは、SQL*Formsにより確立された接続を使用してOracleと通信します。ただし、ユーザー・イグジットでSQL*Netを使用して任意のデータベースに追加の接続を確立できます。
スタンドアロン型のプログラムに適用されるホスト変数の制限事項は、ユーザー・イグジットにも適用されます。EXEC SQLおよびEXEC TOOLS文内では、ホスト変数の前にコロン(:)が必要です。ただし、EXEC TOOLS文では、ホスト配列は使用できません。