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);
}