ECOBPGアプリケーションがPostgreSQLバックエンドとCOBOLアプリケーションの間で値をやり取りする際、例えばサーバからクエリの結果を受け取る、または入力パラメータとともにSQL文を実行する場合、それらの値はPostgreSQLのデータ型とホスト言語の変数の型(具体的にはCOBOLのデータ型)の間で変換される必要があります。 ECOBPGの重要な点のひとつは、ほとんどの場合においてECOBPGがこれらを自動的に扱うということです。
この点において、2つのデータ型があります: いくつかの単純なPostgreSQLのデータ型、integer や text などは、アプリケーションから直接読んだり書いたりすることができます。 その他のPostgreSQLのデータ型、timestamp や date などは、文字列を通してアクセスすることしかできません。特別なライブラリの関数は、ecobpgには存在していません。(pgtypesはecpgには存在しますが、ecobpgには存在しません。)
“表D.1 PostgreSQLデータ型とCOBOL変数型の対応”には、PostgreSQLのどのデータ型がCOBOLのデータ型に対応するかを示されています。 与えられたPostgreSQLのデータ型へ値を書き込みまたは読み込みしたい場合には、対応するCOBOLのデータ型の変数を宣言セクションにおいて宣言しなければなりません。
PostgreSQL data type | COBOL Host variable type |
|---|---|
smallint | PIC S9([1-4]) {BINARY|COMP|COMP-5} |
integer | PIC S9([5-9]) {BINARY|COMP|COMP-5} |
bigint | PIC S9([10-18]) {BINARY|COMP|COMP-5} |
decimal | PIC S9(m)V9(n) PACKED-DECIMAL PIC 9(m)V9(n) DISPLAY (*1) PIC S9(m)V9(n) DISPLAY PIC S9(m)V9(n) DISPLAY SIGN TRAILING [SEPARATE] PIC S9(m)V9(n) DISPLAY SIGN LEADING [SEPARATE] |
numeric | decimalと同じ |
real | COMP-1 |
double precision | COMP-2 |
small serial | PIC S9([1-4]) {BINARY|COMP|COMP-5} |
serial | PIC S9([5-9]) {BINARY|COMP|COMP-5} |
bigserial | PIC S9([10-18]) {BINARY|COMP|COMP-5} |
oid | PIC 9(9) {BINARY|COMP|COMP-5} |
character(n), varchar(n), text | PIC X(n), PIC X(n) VARYING PIC N(n), PIC N(n) VARYING |
name | PIC X(NAMEDATALEN) |
boolean | BOOL(*2) |
other types (例:timestamp) | PIC X(n), PIC X(n) VARYING PIC N(n), PIC N(n) VARYING |
*1 : USAGE句を指定しない場合、ホスト変数は、DISPLAYとみなされます。 | |
文字列の処理
varcharやtextのような文字列のデータ型を扱うためのホスト変数を宣言する方法があります。
ECOBPGによって提供される特殊なデータ型 PIC X(n) VARYING(以下、VARCHAR型と呼びます) を使う方法です。
VARCHAR の定義は、すべての変数が名前の付いた集団項目に変換されます。以下のような宣言は:
01 VAR PIC X(180) VARYING.
次のように変換されます:
01 VAR. 49 LEN PIC S9(4) COMP-5. 49 ARR PIC X(180).
--varchar-with-named-memberオプションを使用すると、以下のように変換されます。
01 VAR. 49 VAR-LEN PIC S9(4) COMP-5. 49 VAR-ARR PIC X(180).
VHARCHAR型のレベル番号には、1から48を使用することができます。VARCHAR型の変数の直後にレベル番号49をもつ変数を使用しないでください。
SQL文への入力用にVARCHAR型のホスト変数を利用する場合、LENにはARRに含まれる文字列の長さを格納する必要があります。
SQL文からの出力用にVARCHAR型のホスト変数を利用する場合、十分な長さのホスト変数を宣言する必要があります。不足している場合、バッファオーバーランの原因となります。
PIC X(n) と VARCHAR ホスト変数は、他のSQLのデータ型の値を文字列表現として保持することもできます。
特殊なデータ型へのアクセス
ECOBPGでは、date型、timestamp型、interval型に対して、特別なサポートはしていません。(ECPGにはpgtypesがありますが、ECOBPGにはありません。)
PIC X(n)やVARCHARホスト変数を利用して文字列表現のデータを入出力に使用することが可能です。 データの文字列表現については“PostgreSQL Documentation”の“ Data Types”を参照してください。
非プリミティブ型のホスト変数
ホスト変数として、配列、TYPEDEF、集団項目も使うことができます。
COBOLで提供されているOCCURRENCE構文を使用して、配列型の変数を作成、使用することができます。
カーソルを用いずに複数行を返却するクエリ結果を受け取るために使います。 配列を使わない場合、複数行からなるクエリの実行結果を処理するには、カーソルと FETCH コマンドを使用する必要があります。 しかし、配列のホスト変数を使うと、複数行を一括して受け取ることができます。 配列の長さはすべての行を受け入れられるように定義されなければなりません。でなければバッファーオーバーランが発生するでしょう。
以下の例は pg_database システムテーブルをスキャンし、利用可能なデータベースのすべてのOIDとデータベース名を表示します:
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 GROUP-ITEM.
05 DBID PIC S9(9) COMP OCCURS 8.
05 DBNAME PIC X(16) OCCURS 8.
01 I PIC S9(9) COMP.
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL CONNECT TO testdb END-EXEC.
* Retrieve multiple rows into arrays at once.
EXEC SQL SELECT oid,datname INTO :DBID, :DBNAME FROM pg_database END-EXEC.
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 8
DISPLAY "oid=" DBID(I) ", dbname=" DBNAME(I)
END-PERFORM.
EXEC SQL COMMIT END-EXEC.
EXEC SQL DISCONNECT ALL END-EXEC.配列のサブスクリプトを特定することにより、配列のメンバを、単純なホスト変数として使用することができます。サブスクリプトを特定するために、COBOLの形式である“(1)”ではなく、Cの形式である“[1]”を使用してください。したし、サブスクリプトは、COBOLの文法に従い、1から開始します。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 GROUP-ITEM.
05 DBID PIC S9(9) COMP OCCURS 8.
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL CONNECT TO testdb END-EXEC.
EXEC SQL SELECT oid INTO :DBID[1] FROM pg_database WHERE oid=1 END-EXEC.
DISPLAY "oid=" DBID(1)
EXEC SQL COMMIT END-EXEC.
EXEC SQL DISCONNECT ALL END-EXEC.従属項目の名前がクエリ結果のカラム名に合致する集団項目は、複数のカラムを一括して受け取るために利用することができます。 集団項目は複数のカラムの値を単一のホスト変数で扱うことを可能にします。
以下の例は、pg_database システムテーブルおよび pg_database_size() 関数を使って、利用可能なデータベースのOID、名前、サイズを取得します。 この例では、メンバー変数の名前が SELECT 結果の各カラムに合致する集団項目 DBINFO_T が、複数のホスト変数に格納することなく FETCH 文の一行の結果を受け取るために使用されています。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 DBINFO-T TYPEDEF.
02 OID PIC S9(9) COMP.
02 DATNAME PIC X(65).
02 DBSIZE PIC S9(18) COMP.
01 DBVAL TYPE DBINFO-T.
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size
FROM pg_database END-EXEC.
EXEC SQL OPEN cur1 END-EXEC.
* when end of result set reached, break out of loop
EXEC SQL WHENEVER NOT FOUND GOTO END-FETCH END-EXEC.
PERFORM NO LIMIT
* Fetch multiple columns into one structure.
EXEC SQL FETCH FROM cur1 INTO :DBVAL END-EXEC
* Print members of the structure.
DISPLAY "oid=" OID ", datname=" DATNAME ", size=" DBSIZE
END-PERFORM.
END-FETCH.
EXEC SQL CLOSE cur1 END-EXEC.集団項目のホスト変数は、多数のカラムを集団項目の従属項目として“吸収”します。 追加のカラムは他のホスト変数に割り当てることができます。 例えば、上記のプログラムは集団項目に含まれない size 変数を使って以下のように書き換えることができます。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 DBINFO-T TYPEDEF.
02 OID PIC S9(9) COMP.
02 DATNAME PIC X(65).
01 DBVAL TYPE DBINFO-T.
01 DBSIZE PIC S9(18) COMP.
EXEC SQL END DECLARE SECTION END-EXEC.
EXEC SQL DECLARE cur1 CURSOR FOR SELECT oid, datname, pg_database_size(oid) AS size
FROM pg_database END-EXEC.
EXEC SQL OPEN cur1 END-EXEC.
* when end of result set reached, break out of loop
EXEC SQL WHENEVER NOT FOUND GOTO END-FETCH END-EXEC.
PERFORM NO LIMIT
* Fetch multiple columns into one structure.
EXEC SQL FETCH FROM cur1 INTO :DBVAL, :DBSIZE END-EXEC
* Print members of the structure.
DISPLAY "oid=" OID ", datname=" DATNAME ", size=" DBSIZE
END-PERFORM
FETCH-END.
EXEC SQL CLOSE cur1 END-EXEC.
ホスト変数のSQL文には、ネストされていない集団項目しか使用することはできません。ネストされた集団項目の宣言はOKですが、SQLに対しては集団項目のネストされていない部分を指定しなければなりません。(プリコンパイル時に集団項目に変換されるVARCHAR型は、このルールに従っているとは見なされません。)SQLにおける集団項目における内部の項目を使用するときは、COBOLの A OF B構文ではなく、ピリオドで区切られたCの構造体のように使用してください。以下に例を示します。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 NESTED-GROUP.
02 CHILD1.
03 A PIC X(10).
03 B PIC S9(9) COMP.
02 CHILD2.
03 A PIC X(10).
03 B PIC S9(9) COMP.
EXEC SQL END DECLARE SECTION END-EXEC.
* This SQL is valid. CHILD1 has no nested group items.
EXEC SQL SELECT * INTO :NESTED-GROUP.CHILD1 FROM TABLE1 END-EXEC.集団項目の基本項目を特定するために、その基本項目を一意にするために十分な特定を行えば、完全な特定は必要ではありません。詳細は、COBOLの文法資料を参照してください。
新しい型と既存の型を対応付けるためには TYPEDEF キーワードを使ってください。
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 MYCHARTYPE TYPEDEF PIC X(40).
01 SERIAL-T TYPEDEF PIC S9(9) COMP.
EXEC SQL END DECLARE SECTION END-EXEC.また、同様に以下を使うこともできます:
EXEC SQL TYPE SERIAL-T IS PIC S9(9) COMP-5. END-EXEC.
この宣言は、宣言セクションの一部である必要はありません。