Example - Long & Long Raw

Top  Previous  Next

これら2つのOracleデータ型は非常に大きな値(最大2GB)を取れます。それゆえ、Long値に関する制約はあまりありません:

w        他のクエリーフィールドと違って、Long値はバッファーされません。Long値のField 関数が呼ばれる度に、値はデータベースからフェッチされます。その一方で、Field関数を呼ばない限り値はフェッチされません。
w        クエリーがselect-list内のLongカラムを発見するといつでも、クエリーのReadBufferプロパティに関係なくレコードだけがバッファーされます。
w        Longデータ型の出力変数はサポートされていません。可能な限りselect命令を使用してください。もしLong出力変数を使わなければいけないなら、その変数の保有最大値を入力変数のものと等しくしてください。つまりそれは入力/出力変数となります。もしより大きな値を偏すに割り当てると、"ORA-06502: PL/SQL: numeric or value error"が発生します。割り当てサイズが十分であるようにしてください。

Long Rawは、文字列かバイトのゼロベースバリアント配列として扱われます。可能な限りハイパフォーマンスでバイト配列にアクセスするために、VarArrayLockVarArrayUnlock関数を使ってください。値のサイズを調べるためにはVarArrayHighBoundを使ってください。 次のサンプルは絵をフェッチし、サイズを調べ、ディスクにバイナリーデータを保存します:

// SelectEmpPictureQuery.SQL =

// select picture from emp

// where empno = :empno

try

with SelectEmpPictureQuery do

begin

   SetVariable('EMPNO', Emp.EmpNo);

   Execute;

   Picture := Field('PICTURE');

   Size    := VarArrayHighBound(Picture, 1) + 1;

   Ptr     := VarArrayLock(Picture);

   WriteFile('Employee.gif', Ptr^, Size);

   VarArrayUnlock(Picture);

end;

except

on E:EOracleError do ShowMessage(E.Message);

end;

 

LongLong Rawデータに簡単に素早くアクセスするために2つの低レベルメソッドが用意されています。FieldSetVariableメソッドは全てのデータ型に対して一貫したアクセスを提供します。しかしメモリー使用、メモリー移動そしてデータベースアクセスにおいて若干のオーバーヘッドが発生します。

もしLongLong Rawの内部構造を知っていれば、正確なサイズもわかり、最低限のネットワーク往復で正確に必要なものをフェッチできるでしょう。GetLongField メソッドは次のような状況で使えます:

GetLongField(FieldId: Integer; Buffer: Pointer; Offset, Length: Integer): Integer

 

例えば、もしLong Rawカラムが16-colorビットマップだとわかっていれば、高さと幅が1822の位置に格納されていることもわかっているはずです。もし最初にこれら2つのIntegerをフェッチすれば、ビットマップのサイズを判断でき残りをフェッチすることが出来ます:

var wh: TPoint;

   Size: Integer;

   Bitmap: Pointer;

begin

Query.GetLongField(BmpField, @wh, 18, SizeOf(wh));

Size := ((wh.x * wh.y) div 2) + 70;

GetMem(Bitmap, Size);

Query.GetLongField(BmpField, Bitmap, 0, Size);

...

end;

 

もしLongLong Raw変数の値を設定するためにSetVariableメソッドを使うなら、値に文字列(LongLong Raw)かバイトのバリアント配列(Long Raw)を渡す必要があります。しかし多量のメモリーを変換しコピーする代わりに使うデータへのポインターを渡すほうがより効果的です。SetLongVariableメソッドでこうすることができます:

SetLongVariable(Name: String; Buffer: Pointer; Length: Integer)

 

Bufferポインターによって指し示されたメモリーはコピーされず、クエリーが実行されるまで有効なまま保たれます。次のサンプルは変数をメモリ内のある録音されたwavファイルに設定し、新しいレコードを挿入します:

var WavBuffer: Pointer;

   WavLength: Integer;

begin

RecordWavFile(WavBuffer, WavLength);

Query.SetVariable('wavname', WavName.Text);

Query.SetLongVariable('wavfile', WavBuffer, WavLength);

Query.Execute;

FreeMem(WavBuffer, WavLength);

end;

 

: GetLongFieldSetLongVariableメソッドは低レベルであるため、FieldSetVariableメソッドと違ってLong値のためにLFCR/LF間の変換を行いません。Long Raw値に関してはこのことは問題になりません。