SQLCAが標準的なSQL通信を処理するのに対し、ORACAはOracle通信を処理します。ランタイム・エラーおよび状態の変化について、SQLCAで提供されるより詳しい情報が必要な場合は、ORACAを使用してください。これには、豊富な診断ツールが用意されています。ただし、ORACAの使用はランタイム・オーバーヘッドを増加させるため、あくまでもオプションです。
ORACAは問題の診断に役立つ上に、プログラムによるOracleリソース(SQL文エグゼキュータやカーソル・キャッシュなど)の利用を監視できます。
プログラムでは複数のORACAを使用できます。たとえば、1つのグローバルORACAと複数のローカルORACAを設定できます。ローカルORACAへのアクセスは、プログラム内のその有効範囲によって制限されます。Oracleでは適用範囲内のORACAにのみ情報が戻されます。
ORACAを宣言するには、次に示すように、INCLUDE文または#includeプリプロセッサ・ディレクティブを使用してORACAを自分のプログラムにコピーします。
EXEC SQL INCLUDE ORACA;
または
#include <oraca.h>
ORACAがextern記憶域クラスであることが必要な場合は、プログラムに次のようにORACA_STORAGE_CLASSを定義します。
#define ORACA_STORAGE_CLASS extern
プログラムで宣言部を使用するときは、ORACAを宣言部の外側で定義する必要があります。
ORACAを有効にするには、コマンドラインに次のようにORACAオプションを指定する必要があります。
ORACA=YES
またはインラインで次のように指定します。
EXEC ORACLE OPTION (ORACA=YES);
その後、ORACA内のフラグを設定することによって、適切なランタイム・オプションを選択する必要があります。
ORACAには、次のように、オプションの設定、システムの統計および高度な診断情報が保存されています。
SQL文のテキスト(テキストの保存時に指定できます)
エラーが発生したファイルの名称(サブルーチンの使用時に便利です)
ファイル内のエラーの位置
カーソル・キャッシュのエラーおよび統計情報
oraca.h
の一部を次に示します。
/* NAME ORACA : Oracle Communications Area. If the symbol ORACA_NONE is defined, then there will be no ORACA *variable*, although there will still be a struct defined. This macro should not normally be defined in application code. If the symbol ORACA_INIT is defined, then the ORACA will be statically initialized. Although this is not necessary in order to use the ORACA, it is a good pgming practice not to have unitialized variables. However, some C compilers/operating systems don't allow automatic variables to be init'd in this manner. Therefore, if you are INCLUDE'ing the ORACA in a place where it would be an automatic AND your C compiler/operating system doesn't allow this style of initialization, then ORACA_INIT should be left undefined -- all others can define ORACA_INIT if they wish. */ #ifndef ORACA #define ORACA 1 struct oraca { char oracaid[8]; /* Reserved */ long oracabc; /* Reserved */ /* Flags which are setable by User. */ long oracchf; /* <> 0 if "check cur cache consistncy"*/ long oradbgf; /* <> 0 if "do DEBUG mode checking" */ long orahchf; /* <> 0 if "do Heap consistency check" */ long orastxtf; /* SQL stmt text flag */ #define ORASTFNON 0 /* = don't save text of SQL stmt */ #define ORASTFERR 1 /* = only save on SQLERROR */ #define ORASTFWRN 2 /* = only save on SQLWARNING/SQLERROR */ #define ORASTFANY 3 /* = always save */ struct { unsigned short orastxtl; char orastxtc[70]; } orastxt; /* text of last SQL stmt */ struct { unsigned short orasfnml; char orasfnmc[70]; } orasfnm; /* name of file containing SQL stmt */ long oraslnr; /* line nr-within-file of SQL stmt */ long orahoc; /* highest max open OraCurs requested */ long oramoc; /* max open OraCursors required */ long oracoc; /* current OraCursors open */ long oranor; /* nr of OraCursor re-assignments */ long oranpr; /* nr of parses */ long oranex; /* nr of executes */ }; #ifndef ORACA_NONE #ifdef ORACA_STORAGE_CLASS ORACA_STORAGE_CLASS struct oraca oraca #else struct oraca oraca #endif #ifdef ORACA_INIT = { {'O','R','A','C','A',' ',' ',' '}, sizeof(struct oraca), 0,0,0,0, {0,{0}}, {0,{0}}, 0, 0,0,0,0,0,0 } #endif ; #endif #endif /* end oraca.h */
この項では、ORACAの構造体とそのコンポーネントおよび格納できる値について説明します。
マスターDEBUGフラグ(oradbgf)が設定されていると、このフラグによってカーソル・キャッシュの統計情報の収集と、各カーソル操作前のカーソル・キャッシュの一貫性チェックができます。
Oracleランタイム・ライブラリでは一貫性チェックが行われ、エラー・メッセージが発行されることがあります(エラー・メッセージについては、『Oracle Databaseエラー・メッセージ』を参照してください)。これらは、Oracleエラー・メッセージと同様にSQLCAに戻されます。
このフラグは次のいずれかを設定します。
キャッシュ一貫性チェックを使用禁止にします(デフォルト)。
キャッシュ一貫性チェックを使用可能にします。
このマスター・フラグを使用すると、DEBUGオプションをすべて選択できます。これには次の設定があります。
すべてのDEBUG処理を使用禁止にします(デフォルト)。
すべてのDEBUG処理を有効にします。
マスターDEBUGフラグ(oradbgf)が設定されていると、プリコンパイラによって動的にメモリーが割り当てまたは解放されるたびに、Oracleランタイム・ライブラリでヒープの一貫性がチェックされます。これはメモリー障害を起こすプログラムの不具合を検出するのに役立ちます。
このフラグはCONNECTコマンドを発行する前に設定する必要があります。また、このフラグは一度設定すると解除できなくなります。つまり、設定後にこのフラグの変更要求があっても無視されます。これには次の設定があります。
ヒープ一貫性チェックを無効にします(デフォルト)。
ヒープ一貫性チェックを有効にします。
このフラグを使用すると、現行のSQL文のテキストを保存するタイミングを指定できます。これには次の設定があります。
SQL文のテキストを保存しません(デフォルト)。
SQLERRORのSQL文のテキストのみ保存します。
SQLERRORまたはSQLWARNINGのSQL文のテキストのみ保存します。
常にSQL文のテキストを保存します。
SQL文のテキストは、orastxtという名前のORACA埋込み構造体に保存されます。
この埋込み構造体は、問題のあるSQL文を見つけるために使用します。Oracleで解析された最後のSQL文のテキストを保存できます。これには次の2つのコンポーネントが格納されています。
コンポーネント | 説明 |
---|---|
orastxtl |
この整数コンポーネントにはカレントSQL文の長さが格納されます。 |
orastxtc |
この文字列コンポーネントにはカレントSQL文のテキストが格納されます。先頭から最大70文字までのテキストが保存されます。文字列はヌル文字で終了しません。文字列を印刷するときは、oratxtl長さコンポーネントを使用します。 |
プリコンパイラによって解析された文(CONNECT、FETCHおよびCOMMITなど)は、ORACAには保存されません。
この埋込み構造体は、カレントSQL文が含まれているファイルを識別します。このため、1つのアプリケーション用に複数のファイルをプリコンパイルするときにエラーを検出できます。これには次の2つのコンポーネントが格納されています。
コンポーネント | 説明 |
---|---|
orasfnml |
この整数コンポーネントには、orasfnmcに保存されているファイル名の長さが格納されます。 |
orasfnmc |
この文字列コンポーネントにはファイル名が格納されます。先頭から最大70文字が格納されます。 |
この整数コンポーネントには、プログラムの要求によってオープンされたOracleカーソルの最大数が記録されます。MAXOPENCURSORSに設定されている値が小さすぎて、その結果プリコンパイラによってカーソル・キャッシュが拡張されると、この数はorahocより大きくなることがあります。
この整数コンポーネントには、プログラムの要求によって再度割り当てられたカーソル・キャッシュの数が記録されます。この数値は、カーソル・キャッシュのスラッシングの程度を示すもので、できるだけ小さく保つ必要があります。
次のプログラムは部門番号の入力を要求し、その部内の各従業員の名前および給与を2つの表のどちらかに挿入してから、ORACAからの診断情報を表示します。このプログラムはoraca.pc
としてdemo
ディレクトリにあり、オンラインで利用できます。
/* oraca.pc * This sample program demonstrates how to * use the ORACA to determine various performance * parameters at runtime. */ #include <stdio.h> #include <string.h> #include <sqlca.h> #include <oraca.h> EXEC SQL BEGIN DECLARE SECTION; char *userid = "SCOTT/TIGER"; char emp_name[21]; int dept_number; float salary; char SQLSTATE[6]; EXEC SQL END DECLARE SECTION; void sql_error(); main() { char temp_buf[32]; EXEC SQL WHENEVER SQLERROR DO sql_error("Oracle error"); EXEC SQL CONNECT :userid; EXEC ORACLE OPTION (ORACA=YES); oraca.oradbgf = 1; /* enable debug operations */ oraca.oracchf = 1; /* gather cursor cache statistics */ oraca.orastxtf = 3; /* always save the SQL statement */ printf("Enter department number: "); gets(temp_buf); dept_number = atoi(temp_buf); EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, sal + NVL(comm,0) AS sal_comm FROM emp WHERE deptno = :dept_number ORDER BY sal_comm DESC; EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND DO sql_error("End of data"); for (;;) { EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; printf("%.10s\n", emp_name); if (salary < 2500) EXEC SQL INSERT INTO pay1 VALUES (:emp_name, :salary); else EXEC SQL INSERT INTO pay2 VALUES (:emp_name, :salary); } } void sql_error(errmsg) char *errmsg; { char buf[6]; strcpy(buf, SQLSTATE); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL COMMIT WORK RELEASE; if (strncmp(errmsg, "Oracle error", 12) == 0) printf("\n%s, sqlstate is %s\n\n", errmsg, buf); else printf("\n%s\n\n", errmsg); printf("Last SQL statement: %.*s\n", oraca.orastxt.orastxtl, oraca.orastxt.orastxtc); printf("\nAt or near line number %d\n", oraca.oraslnr); printf ("\nCursor Cache Statistics\n------------------------\n"); printf ("Maximum value of MAXOPENCURSORS: %d\n", oraca.orahoc); printf ("Maximum open cursors required: %d\n", oraca.oramoc); printf ("Current number of open cursors: %d\n", oraca.oracoc); printf ("Number of cache reassignments: %d\n", oraca.oranor); printf ("Number of SQL statement parses: %d\n", oraca.oranpr); printf ("Number of SQL statement executions: %d\n", oraca.oranex); exit(1); }