このセクションは ecpg インターフェースの開発をしたい方へのもので, それぞれがどのように動作するのかを説明します. 内部構造を見てみたい方のために道具を用意することがこのセクションへの思いです. 一般的な疑問に対しては,すべて「ecpg の使い方」のセクションで十分なはずです. ですからこのセクションは ecpg の内部を見てみる前に読んで下さい. 実際にどのような動作をしているのかということが問題でなければ, このセクションは読み飛ばしても構いません.
現バージョンのプリプロセッサには少し不備な点があります:
to_date などが存在しません.しかし Postgres 自体すぐれた変換ルーチンを持っていますから,まず困ることはないでしょう.
構造体と共用体を宣言セクションで定義しなければなりません.
今も以下の構文が実装されていません.
exec sql insert/select from 文における "no data" エラーメッセージは 100 でなければなりません.
sqlwarn[6] は SET DESCRIPTOR 文で指定された PRECISION,または SCALE の値が無視された場合 'W' であるべきですがそうなっていません.
出力に書き込まれる最初の四行は ecpg が付け加え,常に一定の内容です. ここは二行のコメントと,ライブラリとの連携に必要な二行の #include になっています.
プリプロセッサは入力ファイルを読み込み, 出力ファイルに書き出す1パスだけで動作します. 通常は後先を見ずに単に(そのまま)すべてを出力します.
プリプロセッサが EXEC SQL 文にたどり着くと入出力の間に入り, 文の内容に従って変更を加えます.
宣言セクションは
exec sql begin declare section;で始まり,
exec sql end declare section;で終わります. このセクションで許されているのは変数の宣言だけです. セクション内で宣言された個々の変数は同時に変数リストに加えられます. リストは変数の名前をインデックスにしており,対応する変数の型も一緒に持ちます.
特に構造体と共用体の定義も宣言セクションの内部に並べなくてはなりません. さもないと ecpg はその定義について何も知らないことになるので, これらの型を扱うことができなくなります.
宣言も変数を通常の C の変数にしてファイルに出力します.
特別な型,VARCHAR と VARCHAR2 は変数ごとに名前のついた構造体に変換されます. 宣言は以下のようになります:
VARCHAR var[180];そしてこれは,
struct varchar_var { int len; char arr[180]; } var;と変換されます.
include 文は以下のようになります:
exec sql include filename;これは
#include <filename.h>とは違うものです.
指定されたファイルは ecpg がかわりに解析します. したがって指定されたファイルの内容は,処理結果の C のコードの中に含められます. この方法ではインクルードするファイルの中に EXEC SQL コマンドを指定することができます.
connect 文は以下のようになります:
exec sql connect to 接続先;これは指定されたデータベースへ接続します.
接続先 は次のような方法でも指定できます.
ユーザ名を指定するにも複数の方法があります:
最後にユーザ ID とパスワード. それぞれは(ソース)テキスト,文字列定数,あるいは文字列のいずれかで指定します.
disconnect 文は以下のようになります:
exec sql disconnect [接続先];指定されたデータベースとの接続を閉じます.
接続先 は以下のように指定します:
open cursor 文は以下のようになります:
exec sql open カーソル;これは無視され,出力からコピーもされません.
commit 文は以下のようになります:
exec sql commit;これは次のように変換されます:
ECPGcommit(__LINE__);
rollback 文は以下のようになります:
exec sql rollback;これは次のように変換されます:
ECPGrollback(__LINE__);
その他の SQL 文は exec sql で始まり, セミコロン(;)で終わる文です. 両者の間にあるものはすべて SQL 文として扱われ, 変数を置換するための構文解析がおこなわれます.
変数の置換はシンボルがコロン(:)で始まる場合に起きます. まず既に宣言セクションで宣言した変数の中からこの名前を持つ変数が探し出されます. そして変数が入力用/出力用のどちらであるかに従って変数へのポインタが出力ファイルに書き込まれ, 関数からのアクセスが可能になるのです.
関数はさらに,SQL のリクエストの一部となる変数それぞれに対して十個の引数を取ります.
専用のシンボルで表した変数の型 |
値へのポインタ,またはそのポインタへのポインタ |
変数のサイズ(char または varchar の場合) |
配列の要素数(配列へのフェッチ用) |
配列内の次の要素へのオフセット(配列へのフェッチ用) |
専用のシンボルで表した標識変数 [2] の型 |
標識変数へのポインタ,またはそのポインタへのポインタ |
0 |
標識変数配列の要素数(配列へのフェッチ用) |
標識変数配列内の次の要素へのオフセット(配列へのフェッチ用) |
ここに挙げた完成例は,ファイル 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"(なお,このマニュアルでは読みやすいようにインデントしましたが, プリプロセッサ自体はインデントをしません)
ライブラリの中で最も重要な関数は ECPGdo です. この関数が取る引数の数は可変ですが, 幸いなことにこのような関数が受け取る変数の数に制限があるようなマシンに行き当たることはないでしょう. 50 やそこらの引数くらいまでなら平気です.
引数は以下の通り:
これは元ファイルの行番号でエラーメッセージにだけ使われます.
これは発行される SQL リクエストです. このリクエストは入力変数,すなわち「コンパイル時には居所がわからないが, リクエストの中に加えられる予定の変数」によって加工されます. 変数が納められるのは ";" [3] を含む文字列です.
プリプロセッサに関するセクションで説明した通り, 個々の入力変数は十個の引数を取ります.
これ以上入力変数がないことを示す列挙型の値です.
プリプロセッサに関するセクションで説明した通り, 個々の出力変数は十個の引数を取ります. これらの変数は関数によって値が格納されます.
これ以上変数がないことを示す列挙型の値です.
commit transaction を発行しない限り, SQL 文はすべて単一のトランザクション内で実行されます. この自動トランザクション実行を実現するために,最初の文, または commit/rollback の後の最初の文は常にトランザクションを開始します. デフォルトによるこの機能を禁止するにはコマンドラインで '-t' オプションを使います.
他の事項の説明項目は未完です.
[1] | 訳注:原文では Open cursor 文から Rollback 文までの説明が既に古くなっているとの コメントが入っています. |
[2] | 訳注:フィールドの値とは別に,フィールドが NULL かどうかを, あるいはフィールドの文字列がそれを格納する変数の領域より長いために, 切り捨てられた場合の情報を示すための変数 (indicator variable) です. |
[3] | 訳注:文意からすると ';' ではなく,'?' と思えます. |