第3章 アプリケーションの作成
3.1 SQL 埋込み C プログラムの作成方法
3.1.8 ポインタ変数として宣言したホスト変数の使用方法
ここでは、ポインタ変数として宣言したホスト変数の使用方法について、以下を説明します。
・
ポインタ変数のデータ領域の設定とサイズ・
ポインタ変数の使用方法ポインタ変数のデータ領域の設定とサイズ
ポインタ変数は、領域のアドレスを保持する変数です。ポインタ変数を利用すると、動的に領域を獲得することができま す。また、関数のパラメタで領域のアドレスを渡すことができるため、アプリケーション間で領域を共有できます。
ホスト変数をポインタ変数として宣言した場合、ホスト変数はデータではなくデータ領域の先頭アドレスを保持します。し たがって、アプリケーション中で、最初にホスト変数を使用する前に、参照するデータ領域のアドレスを設定してください。
ポインタ変数が参照するデータ領域のサイズは、コンパイル時または実行時に、以下のように認識されます。
数値型の場合
数値型の場合、ポインタ変数が参照する領域のサイズは参照する先の数値型のサイズになります。
参照
数値型については、“SQLリファレンス”を参照してください。
文字列型の場合
文字列型のポインタ変数が参照する領域のサイズは、先頭アドレスからNULL文字までの長さとなります。
文字列型のポインタ変数を値指定に使用する場合、参照先のデータ領域に設定した文字列の最後にNULL文字を 設定する必要があります。
例
EXEC SQL BEGIN DECLARE SECTION;
char *country; (1) :
EXEC SQL END DECLARE SECTION;
:
country = malloc(11); (2) strcpy( country, "Japanese" ); (3) EXEC SQL INSERT INTO SCH.TBL( COUNTRY ) (4) VALUES( :country );
(1) 文字列型のポインタ変数countryを宣言します。
(2) countryに11バイトの領域のアドレスを設定します。
(3) countryの参照する領域に文字列を設定します。strcpy関数を使用して、文字列の最後にNULL文字を設定し ます。
(4) INSERT文の値指定にcountryを指定します。
文字列型のポインタ変数を相手指定に使用する場合、参照先のデータ領域の最後にNULL文字を設定します。
Symfoware/RDBは先頭アドレスからNULL文字までを領域のサイズとします。
例
EXEC SQL BEGIN DECLARE SECTION;
char *country; (1) :
EXEC SQL END DECLARE SECTION;
:
country = malloc(11); (2) memset( country, ' ', 10 ); (3)
*(country+10) = '¥0'; (4) EXEC SQL SELECT COUNTRY INTO :country (5) FROM SCH.TBL
WHERE DATANO = 1;
(1) 文字列型のポインタ変数countryを宣言します。
(2) countryに11バイトの領域のアドレスを取得します。
(3) 領域の値は不定なので、空白文字を設定します。
(4) 11バイト目にNULL文字を設定します。
(5) 単一行SELECT文の相手指定にcountryを指定します。
可変長文字列型の場合
可変長文字列型の場合はコンパイル時に構造体に変換されるため、データ領域はデータ長に2バイト足したサイズ が必要になります。可変長文字列型のサイズは、変換された構造体のメンバ sqllen に設定してください。
アプリケーション中に以下のように宣言します。
VARCHAR *country;
↓コンパイル時に構造体に変換します。
struct country_SQLVAR { short sqllen;
char sqlvar[1];
} *country;
可変長文字列型のポインタ変数を相手指定に使用する場合、SQL文を実行するとデータ領域長を設定するメンバ sqllen に取得したデータの長さが設定されます。したがって、再度SQL文を実行する場合は、実行前に領域長を設定し直 す必要があります。
例
EXEC SQL BEGIN DECLARE SECTION;
VARCHAR *country;
short loop;
EXEC SQL END DECLARE SECTION;
char buff[12];
:
country = (struct country_SQLVAR *)malloc(13); (1) country->sqllen = 10; (2) for ( loop=0; loop<MAX_COUNTRY; loop++ ) { (3) EXEC SQL SELECT COUNTRY INTO :country (4) FROM SCH.TBL
WHERE DATANO = :loop;
:
country->sqllen = 10; (5) }
:
(1) countryに13バイトの領域のアドレスを設定します。
(2) 変換後の構造体のメンバsqllenに領域長を設定します。
(3) MAX_COUNTRY件のデータを取り出します。
(4) countryを指定したSELECT文を実行します。
(5) 次のSQL文の実行前に、変換後の構造体のメンバsqllenに領域長を設定します。
BLOB型の場合
BLOB型の場合はコンパイル時に構造体に変換されるため、データ領域はデータ長に8バイト足したサイズが必要に なります。また、データ領域は1Kバイト(1024バイト)単位で取得してください。BLOB型のサイズは、変換された構造体 のメンバ ホスト変数名_length に設定してください。
アプリケーション中に以下のように宣言します。
SQL TYPE IS BLOB *image;
↓コンパイル時に構造体に変換します。
struct image_SQLBLOB {
long image_reserced;
long image_length;
char image_data[1];
} *image;
BLOB型のポインタ変数を相手指定に使用する場合、SQL文を実行するとデータ領域長を設定するメンバ変数名_length に取得したデータの長さが設定されます。したがって、再度SQL文を実行する場合は、実行前に領域長を設定し直 す必要があります。
例
EXEC SQL BEGIN DECLARE SECTION;
SQL TYPE IS BLOB *image;
short loop;
EXEC SQL END DECLARE SECTION;
char buff[12];
:
image = (struct image_SQLBLOB *)malloc(10248); (1) image->image_length = 10240; (2) for ( loop=0; loop<MAX_COUNTRY; loop++ ) { (3) EXEC SQL SELECT COUNTRY INTO :image (4) FROM SCH.TBL
WHERE DATANO = :loop;
:
image->image_length = 10240; (5) }
:
(1) imageに10248バイトの領域のアドレスを設定します。
(2) 変換後の構造体のメンバimage_lengthに領域長を設定します。
(3) MAX_COUNTRY件のデータを取り出します。
(4) imageを指定したSELECT文を実行します。
(5) 次のSQL文の実行前に、変換後のメンバimage_lengthに領域長を設定します。
ROW_ID型の場合
ROW_ID型の場合、ポインタ変数が参照する領域は24バイト必要です。また、サイズは24になります。
DECIMAL型の場合
精度が p のDECIMAL型の場合、ポインタ変数が参照する領域は (p÷2)+1 バイト必要です。また、サイズも(p÷2)+1
になります。
NUMERIC型の場合
精度が p のNUMERIC型の場合、ポインタ変数が参照する領域は p+1 バイト必要です。また、サイズも p+1 になりま す。
構造体型の場合
構造体型の場合、ポインタ変数が参照する領域のサイズは各メンバのサイズの合計となります。
SQLSTATEの場合
SQLSTATEをポインタ宣言する場合は、5バイト以上の領域が必要です。
ポインタ変数の使用方法
以下に、ポインタ変数を使用したデータ操作を実現するためのプログラミング例を示します。
データ領域を動的に取得する例
EXEC SQL BEGIN DECLARE SECTION;
char SQLSTATE[6];
char SQLMSG[256];
: short datano;
SQL TYPE IS BLOB *image;
:
EXEC SQL END DECLARE SECTION;
short main() {
:
image = (struct image_SQLBLOB *)malloc( 10240 + 8 ); …… (1) image->image_length = 10240;
datano = 5;
: /* データの取得 */
EXEC SQL SELECT IMAGE …… (2) INTO :image
FROM SCH01.TBL01 WHERE DATANO = :datano;
: return 1;
}
(1) ホスト変数 image に領域のアドレスを設定します。
(2) 該当するデータを取得します。
関数パラメタをデータ領域として使用する例 /* データ取得関数 */
short get_data( void *, short );
short main() {
: void *image;
:
image = malloc( 10240 + 8 ); …… (1)
:
ret = get_data( image, 5 ); …… (2) :
return 1;
}
short get_data(
void *image_data;
short number;
{
EXEC SQL BEGIN DECLARE SECTION;
char SQLSTATE[6];
char SQLMSG[256];
:
SQL TYPE IS BLOB *image;
short datano;
:
EXEC SQL END DECLARE SECTION;
:
image = (struct image_SQLBLOB *)image_data; …… (3) image->image_length = 10240; …… (4) datano = number;
: /* データの取得 */
EXEC SQL SELECT IMAGE …… (5) INTO :image
FROM SCH01.TBL01 WHERE DATANO = :datano;
: return 0;
}
(1) データ取得関数に指定するデータ領域を取得します。
(2) データ取得関数を呼び出します。
(3) ホスト変数に領域アドレスを設定します。
(4) ホスト変数の領域長を設定します。
(5) データを取得します。