30.13. 内部

本節では、内部的なECPGの動作を説明します。 この情報はECPGの使用方法を理解する手助けとして有用なことがあります。

ecpgによって出力に書き込まれる最初の4行は固定されています。 2行はコメントで、残り2行はライブラリとのインタフェースのために必要なインクルード行です。 その後、プリプロセッサはファイル全体を読みとり、出力に書き出します。 通常は、単にすべてそのまま出力に書き出します。

EXEC SQLを検出すると、間に入り、それを変更します。 このコマンドはEXEC SQL で始まり、;で終ります。 この間のすべてはSQL文として扱われ、変数の置換のために解析されます。

変数置換は、シンボルがコロン(:)から始まる場合に発生します。 その名前の変数が、EXEC SQL DECLAREセクションで事前に宣言された変数の中から検索されます。

ライブラリ内で最も重要な関数はECPGdoです。 これが、ほとんどのコマンドの実行を管理します。 引数の変数番号をとります。 すべてのプラットフォームで問題にならないことを祈っていますが、これは50程度の引数まで簡単に追加できます。

引数を以下に示します。

行番号

元の行の行番号です。 エラーメッセージ内でのみ使用されます。

文字列

発行すべきSQLコマンドです。 入力変数、つまり、コンパイル時に未知だったがそのコマンド内に与えるべき変数によって変更されます。 変数が文字列内に挿入される所は?となっています。

入力変数

すべての入力変数は 10 個の引数を受けます。(後述)

ECPGt_EOIT

入力変数がもうないことを表す enum です。

出力変数

すべての出力変数は 10 個の引数を受けます。(後述) これらの変数は関数で埋められています。

ECPGt_EORT

変数がもうないことを表す enum です。

SQLコマンドの一部となるすべての変数用に、この関数は以下の10個の引数を受けとります。

  1. 特別シンボルとしての型。

  2. 値へのポインタ、もしくは、ポインタのポインタ。

  3. 変数が charvarchar の場合はそのサイズ。

  4. 配列の要素数 (配列取り出し用)。

  5. 配列の次の要素のオフセット (配列取り出し用)。

  6. 特別シンボルとしての指示子変数の型。

  7. 指示子変数へのポインタ。

  8. 0

  9. 指示子配列内の要素数(配列取り出し用)。

  10. 指示子配列内の次要素へのオフセット(配列取り出し用)。

すべてのSQLコマンドがこの方法で扱われるわけではないことに注意してください。 例えば、以下のカーソルを開く文は出力にコピーされません。

EXEC SQL OPEN cursor;

その代わりにカーソルのDECLAREコマンドがOPENコマンドの場所で使用されます。 実際にこのコマンドがカーソルを開くからです。

以下に、foo.pgcファイルに対するプリプロセッサの出力を完全に説明する例を示します。 (プロプロセッサのバージョンによって詳細が異なっているかもしれません。)

EXEC SQL BEGIN DECLARE SECTION;
int index;
int result;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;

これは以下に翻訳されます。

/* Processed by ecpg (2.6.0) */
/* These two include files are added by the preprocessor */
#include <ecpgtype.h>;
#include <ecpglib.h>;

/* exec sql begin declare section */

#line 1 "foo.pgc"

 int index;
 int result;
/* exec sql end declare section */
...
ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ?     ",
        ECPGt_int,&(index),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
        ECPGt_int,&(result),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc"

ここで可読性のためにインデントをつけています。 プリプロセッサが行ったものではありません。