★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

36.17. 内部 #

本節では内部的な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コマンドがこの方法で扱われるわけではないことに注意してください。 例えば、以下のカーソルを開く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"

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