25 |
|
* |
26 |
|
*) |
27 |
|
unit FB30Blob; |
28 |
+ |
{$IFDEF MSWINDOWS} |
29 |
+ |
{$DEFINE WINDOWS} |
30 |
+ |
{$ENDIF} |
31 |
|
|
32 |
|
{$IFDEF FPC} |
33 |
< |
{$mode objfpc}{$H+} |
33 |
> |
{$mode delphi} |
34 |
|
{$interfaces COM} |
35 |
|
{$ENDIF} |
36 |
|
|
38 |
|
|
39 |
|
uses |
40 |
|
Classes, SysUtils, Firebird, IB, IBHeader, IBExternals, FBClientAPI, FB30ClientAPI, FB30Attachment, |
41 |
< |
FBTransaction, FB30Transaction, FBBlob; |
41 |
> |
FBTransaction, FB30Transaction, FBBlob, FBOutputBlock; |
42 |
|
|
43 |
|
type |
44 |
|
|
53 |
|
procedure NeedFullMetadata; override; |
54 |
|
public |
55 |
|
constructor Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction; |
56 |
< |
RelationName, ColumnName: string); overload; |
56 |
> |
RelationName, ColumnName: AnsiString); overload; |
57 |
|
constructor Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction; |
58 |
< |
RelationName, ColumnName: string; SubType: integer); overload; |
58 |
> |
RelationName, ColumnName: AnsiString; SubType: integer); overload; |
59 |
|
|
60 |
|
end; |
61 |
|
|
70 |
|
procedure CheckReadable; override; |
71 |
|
procedure CheckWritable; override; |
72 |
|
function GetIntf: IBlob; override; |
73 |
+ |
procedure GetInfo(Request: array of byte; Response: IBlobInfo); override; |
74 |
|
procedure InternalClose(Force: boolean); override; |
75 |
|
procedure InternalCancel(Force: boolean); override; |
76 |
|
public |
84 |
|
|
85 |
|
{IBlob} |
86 |
|
public |
83 |
– |
procedure GetInfo(var NumSegments: Int64; var MaxSegmentSize, TotalSize: Int64; |
84 |
– |
var BlobType: TBlobType); override; |
87 |
|
function Read(var Buffer; Count: Longint): Longint; override; |
88 |
|
function Write(const Buffer; Count: Longint): Longint; override; |
89 |
|
end; |
139 |
|
end; |
140 |
|
|
141 |
|
constructor TFB30BlobMetaData.Create(Attachment: TFB30Attachment; |
142 |
< |
Transaction: TFB30Transaction; RelationName, ColumnName: string); |
142 |
> |
Transaction: TFB30Transaction; RelationName, ColumnName: AnsiString); |
143 |
|
begin |
144 |
|
inherited Create(Transaction,RelationName,ColumnName); |
145 |
|
FAttachment := Attachment; |
147 |
|
end; |
148 |
|
|
149 |
|
constructor TFB30BlobMetaData.Create(Attachment: TFB30Attachment; |
150 |
< |
Transaction: TFB30Transaction; RelationName, ColumnName: string; |
150 |
> |
Transaction: TFB30Transaction; RelationName, ColumnName: AnsiString; |
151 |
|
SubType: integer); |
152 |
|
begin |
153 |
|
Create(Attachment,Transaction,RelationName,ColumnName); |
174 |
|
Result := self; |
175 |
|
end; |
176 |
|
|
177 |
+ |
procedure TFB30Blob.GetInfo(Request: array of byte; Response: IBlobInfo); |
178 |
+ |
begin |
179 |
+ |
if FBlobIntf = nil then |
180 |
+ |
IBError(ibxeBlobNotOpen,[nil]); |
181 |
+ |
|
182 |
+ |
with Firebird30ClientAPI, Response as TBlobInfo do |
183 |
+ |
begin |
184 |
+ |
FBlobIntf.getInfo(StatusIntf,Length(Request),BytePtr(@Request), |
185 |
+ |
GetBufSize, BytePtr(Buffer)); |
186 |
+ |
Check4DataBaseError; |
187 |
+ |
SignalActivity; |
188 |
+ |
end; |
189 |
+ |
end; |
190 |
+ |
|
191 |
|
procedure TFB30Blob.InternalClose(Force: boolean); |
192 |
|
begin |
193 |
|
if FBlobIntf = nil then |
273 |
|
end; |
274 |
|
end; |
275 |
|
|
260 |
– |
procedure TFB30Blob.GetInfo(var NumSegments: Int64; var MaxSegmentSize, |
261 |
– |
TotalSize: Int64; var BlobType: TBlobType); |
262 |
– |
var |
263 |
– |
items: array[0..3] of Char; |
264 |
– |
results: array[0..99] of Char; |
265 |
– |
i, item_length: Integer; |
266 |
– |
item: Integer; |
267 |
– |
begin |
268 |
– |
if FBlobIntf = nil then |
269 |
– |
IBError(ibxeBlobNotOpen,[nil]); |
270 |
– |
|
271 |
– |
items[0] := Char(isc_info_blob_num_segments); |
272 |
– |
items[1] := Char(isc_info_blob_max_segment); |
273 |
– |
items[2] := Char(isc_info_blob_total_length); |
274 |
– |
items[3] := Char(isc_info_blob_type); |
275 |
– |
|
276 |
– |
with Firebird30ClientAPI do |
277 |
– |
begin |
278 |
– |
FBlobIntf.getInfo(StatusIntf,4,@items[0],SizeOf(results),@results[0]); |
279 |
– |
Check4DataBaseError; |
280 |
– |
SignalActivity; |
281 |
– |
i := 0; |
282 |
– |
while (i < SizeOf(results)) and (results[i] <> Char(isc_info_end)) do |
283 |
– |
begin |
284 |
– |
item := Integer(results[i]); Inc(i); |
285 |
– |
item_length := DecodeInteger(@results[i], 2); Inc(i, 2); |
286 |
– |
case item of |
287 |
– |
isc_info_blob_num_segments: |
288 |
– |
NumSegments := DecodeInteger(@results[i], item_length); |
289 |
– |
isc_info_blob_max_segment: |
290 |
– |
MaxSegmentSize := DecodeInteger(@results[i], item_length); |
291 |
– |
isc_info_blob_total_length: |
292 |
– |
TotalSize := DecodeInteger(@results[i], item_length); |
293 |
– |
isc_info_blob_type: |
294 |
– |
if DecodeInteger(@results[i], item_length) = 0 then |
295 |
– |
BlobType := btSegmented |
296 |
– |
else |
297 |
– |
BlobType := btStream; |
298 |
– |
end; |
299 |
– |
Inc(i, item_length); |
300 |
– |
end; |
301 |
– |
end; |
302 |
– |
end; |
303 |
– |
|
276 |
|
function TFB30Blob.Read(var Buffer; Count: Longint): Longint; |
277 |
|
var |
278 |
|
BytesRead : cardinal; |
279 |
< |
LocalBuffer: PChar; |
279 |
> |
LocalBuffer: PAnsiChar; |
280 |
|
returnCode: integer; |
281 |
|
localCount: uShort; |
282 |
|
begin |
285 |
|
if FEOB then |
286 |
|
Exit; |
287 |
|
|
288 |
< |
LocalBuffer := PChar(@Buffer); |
288 |
> |
LocalBuffer := PAnsiChar(@Buffer); |
289 |
|
repeat |
290 |
|
localCount := Min(Count,MaxuShort); |
291 |
|
with Firebird30ClientAPI do |
306 |
|
|
307 |
|
function TFB30Blob.Write(const Buffer; Count: Longint): Longint; |
308 |
|
var |
309 |
< |
LocalBuffer: PChar; |
309 |
> |
LocalBuffer: PAnsiChar; |
310 |
|
localCount: uShort; |
311 |
|
begin |
312 |
|
CheckWritable; |
313 |
|
Result := 0; |
314 |
|
if Count = 0 then Exit; |
315 |
|
|
316 |
< |
LocalBuffer := PChar(@Buffer); |
316 |
> |
LocalBuffer := PAnsiChar(@Buffer); |
317 |
|
repeat |
318 |
|
localCount := Min(Count,MaxuShort); |
319 |
|
with Firebird30ClientAPI do |