Hitachi

ノンストップデータベース HiRDB Version 9 UAP開発ガイド


8.2.6 ポインタでの埋込み変数指定

〈この項の構成〉

(1) 概要

C言語では,/Eオプション(UNIX版の場合は-Eオプション)でポインタを埋込み変数として宣言して使用できます。この機能を使用すると,動的に確保した領域をSQL文で直接指定できます。

オプションについては,「UNIX環境でのプリプロセス」又は「Windows環境でのプリプロセス」のオプションの説明を参照してください。また,ポインタを使用できるSQLについては,「プリプロセサの/E2,/E3オプションを指定した場合のポインタ,構造体,及び構造体修飾の使用可否」を参照してください。

ポインタ変数は,C言語の文法に従って宣言します。例を次に示します。

long  *xtanka;
long  *xgryo;
char  *xsname;
:
xtanka  =  (long *)malloc(sizeof(long));
xgryo  =  (long *)malloc(sizeof(long));
xsname  =  (char *)malloc(MAX_CHAR_LEN+1);
memset(xsname, ' ', MAX_CHAR_LEN);
xsname [MAX_CHAR_LEN] = '\0';
EXEC SQL FETCH CUR1 INTO :xtanka,:xgryo,:xsname;

(2) 規則

  1. ポインタ変数は,SQL文中では変数名の前にコロンを付けます。アスタリスクは付けません。

  2. 参照される値のサイズは,宣言で指定した型のサイズになります。ただし,固定長文字列型(CHAR)を除きます。

  3. 固定長文字列型のポインタのデータ長は,プリプロセス時ではなく,実行時に求められます。値のサイズは,ポインタが指している領域が格納している,文字列の終端(\0)までの長さ(strlen(ポインタ変数))になります。1行SELECT文やFETCH文の検索結果を格納する場合も,SQL文を実行する前に,あらかじめ領域全体を\0以外の文字でクリアして,末尾に\0を設定しておく必要があります。

  4. ポインタが指す領域は,ユーザが確保しておく必要があります。固定長文字列型のポインタの場合は,\0を格納するために1バイト余分に領域を確保します。ポインタが不正な値の場合,及びデータを格納するのに十分な領域が確保できない場合は,動作が保証されません。

  5. ポインタへのポインタは使用できません。

  6. 構造体へのポインタは指定できます。

  7. クラスへのポインタは使用できません。

  8. 配列へのポインタは使用できません。配列へのポインタを使用する場合は,構造体を使用して次のように宣言します。

    struct {
    long  xtanka[50];
    long  xgryo[50];
    char  xsname[50][17];
    } *xrec_ptr;

(3) RISC型のCPUを使用しているマシンで繰り返し型のポインタを使用する場合の注意事項

  1. 繰り返し列型の変数は,次の構造となっているため,語境界に合わせたアドレス(1)をポインタに設定する必要があります。

    [図データ]

    通常,malloc()などで確保した領域は,既に語境界に調整されているため,特に問題は発生しません。ただし,ユーザが独自にメモリアドレスを計算して割り当てる場合は,語境界に調整する必要があります。

    ポインタに設定するアドレスが語境界に設定されていないと,繰返し列の操作用のマクロを利用して,データを参照,設定したときにメモリアクセス例外が発生します。繰返し列の埋込み変数の構造については,「繰返し列の展開形式」を参照してください。

  2. FLOAT型の繰返し列の場合,繰り返し回数を格納する領域よりも繰返し要素の方がデータ長が大きくなります。そのため,繰返し要素の語長に合わせたアドレスに,境界調整をしておく必要があります。ポインタには,先頭の空き領域を含めたアドレス(2)を設定します。

    [図データ]

    プリプロセサは,自動的に先頭から4バイト後ろのアドレス(3)を,繰返し列の先頭として使用するポストソースを生成します。FLOAT型の繰返し列を操作するマクロも,アドレス(3)を先頭として使用しています。ただし,SQL記述領域を使用して繰返し列のアドレスを直接設定する場合は,(3)のアドレスを設定してください。

  3. 繰返し要素数の最大値は宣言時の値で決まるため,それより小さい領域を割り当てると,メモリアクセス例外が発生するおそれがあります。

    通常は,次のコーディングのようにメモリを確保すれば問題は発生しません。

    PD_MV_SINT(32) *ptr;              /* 最大要素数32 */
    ptr = malloc(sizeof(*ptr));
    EXEC SQL FETCH CUR1 INTO :ptr;