ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/client/2.5/FB25Blob.pas
Revision: 47
Committed: Mon Jan 9 15:31:51 2017 UTC (7 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 13034 byte(s)
Log Message:
Committing updates for Release R2-0-1

File Contents

# Content
1 (*
2 * Firebird Interface (fbintf). The fbintf components provide a set of
3 * Pascal language bindings for the Firebird API. Although predominantly
4 * a new development they include source code taken from IBX and may be
5 * considered a derived product. This software thus also includes the copyright
6 * notice and license conditions from IBX.
7 *
8 * Except for those parts dervied from IBX, contents of this file are subject
9 * to the Initial Developer's Public License Version 1.0 (the "License"); you
10 * may not use this file except in compliance with the License. You may obtain a
11 * copy of the License here:
12 *
13 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
14 *
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing rights
18 * and limitations under the License.
19 *
20 * The Initial Developer of the Original Code is Tony Whyman.
21 *
22 * The Original Code is (C) 2016 Tony Whyman, MWA Software
23 * (http://www.mwasoftware.co.uk).
24 *
25 * All Rights Reserved.
26 *
27 * Contributor(s): ______________________________________.
28 *
29 *)
30 {************************************************************************}
31 { }
32 { Borland Delphi Visual Component Library }
33 { InterBase Express core components }
34 { }
35 { Copyright (c) 1998-2000 Inprise Corporation }
36 { }
37 { InterBase Express is based in part on the product }
38 { Free IB Components, written by Gregory H. Deatz for }
39 { Hoagland, Longo, Moran, Dunst & Doukas Company. }
40 { Free IB Components is used under license. }
41 { }
42 { The contents of this file are subject to the InterBase }
43 { Public License Version 1.0 (the "License"); you may not }
44 { use this file except in compliance with the License. You }
45 { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
46 { Software distributed under the License is distributed on }
47 { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
48 { express or implied. See the License for the specific language }
49 { governing rights and limitations under the License. }
50 { The Original Code was created by InterBase Software Corporation }
51 { and its successors. }
52 { Portions created by Inprise Corporation are Copyright (C) Inprise }
53 { Corporation. All Rights Reserved. }
54 { Contributor(s): Jeff Overcash }
55 { }
56 { IBX For Lazarus (Firebird Express) }
57 { Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk }
58 { Portions created by MWA Software are copyright McCallum Whyman }
59 { Associates Ltd 2011 - 2015 }
60 { }
61 {************************************************************************}
62 unit FB25Blob;
63
64 {$IFDEF FPC}
65 {$mode objfpc}{$H+}
66 {$interfaces COM}
67 {$ENDIF}
68
69 interface
70
71 uses
72 Classes, SysUtils, IB, IBHeader,IBExternals, FBClientAPI, FB25ClientAPI, FB25Attachment,
73 FB25Transaction, FBActivityMonitor, FBBlob;
74
75 type
76
77 { TFB25BlobMetaData }
78
79 TFB25BlobMetaData = class(TFBBlobMetaData, IBlobMetaData)
80 private
81 FHasFullMetaData: boolean;
82 FAttachment: TFB25Attachment;
83 FTransaction: TFB25Transaction;
84 protected
85 procedure NeedFullMetadata; override;
86 public
87 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
88 RelationName, ColumnName: string); overload;
89 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
90 RelationName, ColumnName: string; SubType: integer); overload;
91 end;
92
93
94 { TFB25Blob }
95
96 TFB25Blob = class(TFBBlob,IBlob)
97 private
98 FHandle: TISC_BLOB_HANDLE;
99 FEOB: boolean;
100 protected
101 procedure CheckReadable; override;
102 procedure CheckWritable; override;
103 function GetIntf: IBlob; override;
104 procedure InternalClose(Force: boolean); override;
105 procedure InternalCancel(Force: boolean); override;
106 public
107 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
108 MetaData: IBlobMetaData; BPB: IBPB); overload;
109 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
110 SubType: integer; CharSetID: cardinal; BPB: IBPB); overload;
111 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
112 MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB); overload;
113 property Handle: TISC_BLOB_HANDLE read FHandle;
114
115 public
116 procedure GetInfo(var NumSegments: Int64; var MaxSegmentSize, TotalSize: Int64;
117 var BlobType: TBlobType); override;
118 function Read(var Buffer; Count: Longint): Longint; override;
119 function Write(const Buffer; Count: Longint): Longint; override;
120 end;
121
122 implementation
123
124 uses IBErrorCodes, FBMessages, FBParamBlock;
125
126 { TFB25BlobMetaData }
127
128 procedure TFB25BlobMetaData.NeedFullMetadata;
129 var
130 BlobDesc: TISC_BLOB_DESC;
131 Global: array [0..31] of char;
132 begin
133 if FHasFullMetaData then Exit;
134
135 FSegmentSize := 80;
136 if (GetColumnName <> '') and (GetRelationName <> '') then
137 begin
138 with Firebird25ClientAPI do
139 Call(isc_blob_lookup_desc(StatusVector,@(FAttachment.Handle),
140 @(FTransaction.Handle),
141 PChar(AnsiUpperCase(GetRelationName)),PChar(AnsiUpperCase(GetColumnName)),@BlobDesc,@Global));
142 if FUnconfirmedCharacterSet then
143 FCharSetID := BlobDesc.blob_desc_charset;
144 FSubType := BlobDesc.blob_desc_subtype;
145 FSegmentSize := BlobDesc.blob_desc_segment_size ;
146 end;
147
148 if FUnconfirmedCharacterSet and (FCharSetID > 1) and FAttachment.HasDefaultCharSet then
149 begin
150 FCharSetID := FAttachment.CharSetID;
151 FUnconfirmedCharacterSet := false;
152 end;
153
154
155 FHasFullMetaData := true;
156 FHasSubType := true;
157 end;
158
159 constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
160 Transaction: TFB25Transaction; RelationName, ColumnName: string);
161 begin
162 inherited Create(Transaction,RelationName,ColumnName);
163 FAttachment := Attachment;
164 FTransaction := Transaction;
165 end;
166
167 constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
168 Transaction: TFB25Transaction; RelationName, ColumnName: string;
169 SubType: integer);
170 begin
171 Create(Attachment,Transaction,RelationName,ColumnName);
172 FSubType := SubType;
173 FHasSubType := true;
174 end;
175
176 { TFB25Blob }
177
178 procedure TFB25Blob.CheckReadable;
179 begin
180 if FCreating or (FHandle = nil) then
181 IBError(ibxeBlobCannotBeRead, [nil]);
182 end;
183
184 procedure TFB25Blob.CheckWritable;
185 begin
186 if not FCreating or (FHandle = nil) then
187 IBError(ibxeBlobCannotBeWritten, [nil]);
188 end;
189
190 function TFB25Blob.GetIntf: IBlob;
191 begin
192 Result := self;
193 end;
194
195 procedure TFB25Blob.InternalClose(Force: boolean);
196 begin
197 if FHandle = nil then
198 Exit;
199 with Firebird25ClientAPI do
200 Call(isc_close_blob(StatusVector, @FHandle), not Force);
201 FHandle := nil;
202 end;
203
204 procedure TFB25Blob.InternalCancel(Force: boolean);
205 begin
206 if FHandle = nil then
207 Exit;
208 with Firebird25ClientAPI do
209 Call(isc_cancel_blob(StatusVector,@FHandle),not Force);
210 FHandle := nil;
211 end;
212
213 constructor TFB25Blob.Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
214 MetaData: IBlobMetaData; BPB: IBPB);
215 var DBHandle: TISC_DB_HANDLE;
216 TRHandle: TISC_TR_HANDLE;
217 begin
218 inherited Create(Attachment,Transaction,MetaData,BPB);
219 DBHandle := Attachment.Handle;
220 TRHandle := Transaction.Handle;
221 with Firebird25ClientAPI do
222 if BPB = nil then
223 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
224 0, nil))
225 else
226 with BPB as TBPB do
227 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
228 getDataLength, getBuffer));
229 end;
230
231 constructor TFB25Blob.Create(Attachment: TFB25Attachment;
232 Transaction: TFB25Transaction; SubType: integer; CharSetID: cardinal;
233 BPB: IBPB);
234 var DBHandle: TISC_DB_HANDLE;
235 TRHandle: TISC_TR_HANDLE;
236 MetaData: TFB25BlobMetaData;
237 begin
238 MetaData := TFB25BlobMetaData.Create(Attachment,Transaction,'','',SubType);
239 MetaData.FCharSetID := CharSetID;
240 MetaData.FHasFullMetaData := true;
241 inherited Create(Attachment,Transaction,MetaData,BPB);
242 DBHandle := Attachment.Handle;
243 TRHandle := Transaction.Handle;
244 with Firebird25ClientAPI do
245 if BPB = nil then
246 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
247 0, nil))
248 else
249 with BPB as TBPB do
250 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
251 getDataLength, getBuffer));
252 end;
253
254 constructor TFB25Blob.Create(Attachment: TFB25Attachment;
255 Transaction: TFB25Transaction; MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB);
256 var DBHandle: TISC_DB_HANDLE;
257 TRHandle: TISC_TR_HANDLE;
258 begin
259 inherited Create(Attachment,Transaction,MetaData,BlobID,BPB);
260 DBHandle := Attachment.Handle;
261 TRHandle := Transaction.Handle;
262 if (BlobID.gds_quad_high = 0) and (BlobID.gds_quad_low = 0) then
263 Exit;
264
265 with Firebird25ClientAPI do
266 if BPB = nil then
267 Call(isc_open_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle,
268 @FBlobID, 0, nil))
269 else
270 with BPB as TBPB do
271 Call(isc_open_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle,
272 @FBlobID, getDataLength, getBuffer));
273 end;
274
275 procedure TFB25Blob.GetInfo(var NumSegments: Int64; var MaxSegmentSize,
276 TotalSize: Int64; var BlobType: TBlobType);
277 var
278 items: array[0..3] of Char;
279 results: array[0..99] of Char;
280 i, item_length: Integer;
281 item: Integer;
282 begin
283 if FHandle = nil then
284 IBError(ibxeBlobNotOpen,[nil]);
285
286 items[0] := Char(isc_info_blob_num_segments);
287 items[1] := Char(isc_info_blob_max_segment);
288 items[2] := Char(isc_info_blob_total_length);
289 items[3] := Char(isc_info_blob_type);
290
291 with Firebird25ClientAPI do
292 begin
293 Call(isc_blob_info(StatusVector, @FHandle, 4, @items[0], SizeOf(results),
294 @results[0]));
295 i := 0;
296 while (i < SizeOf(results)) and (results[i] <> Char(isc_info_end)) do
297 begin
298 item := Integer(results[i]); Inc(i);
299 item_length := isc_portable_integer(@results[i], 2); Inc(i, 2);
300 case item of
301 isc_info_blob_num_segments:
302 NumSegments := isc_portable_integer(@results[i], item_length);
303 isc_info_blob_max_segment:
304 MaxSegmentSize := isc_portable_integer(@results[i], item_length);
305 isc_info_blob_total_length:
306 TotalSize := isc_portable_integer(@results[i], item_length);
307 isc_info_blob_type:
308 if isc_portable_integer(@results[i], item_length) = 0 then
309 BlobType := btSegmented
310 else
311 BlobType := btStream;
312 end;
313 Inc(i, item_length);
314 end;
315 end;
316 end;
317
318 function TFB25Blob.Read(var Buffer; Count: Longint): Longint;
319 var
320 BytesRead : UShort;
321 LocalBuffer: PChar;
322 returnCode: long;
323 localCount: uShort;
324 begin
325 CheckReadable;
326 Result := 0;
327 if FEOB then
328 Exit;
329
330 LocalBuffer := PChar(@Buffer);
331 repeat
332 if Count > MaxuShort then
333 localCount := MaxuShort
334 else
335 localCount := Count;
336 with Firebird25ClientAPI do
337 returnCode := isc_get_segment(StatusVector, @FHandle, @BytesRead, localCount,
338 LocalBuffer);
339 Inc(LocalBuffer,BytesRead);
340 Inc(Result,BytesRead);
341 Dec(Count,BytesRead);
342 until ((returncode <> 0) and (returnCode <> isc_segment)) or (Count = 0);
343
344 FEOB := returnCode = isc_segstr_eof;
345 ClearStringCache;
346 if (returnCode <> 0) and (returnCode <> isc_segment) and (returnCode <> isc_segstr_eof) then
347 Firebird25ClientAPI.IBDataBaseError
348 end;
349
350 function TFB25Blob.Write(const Buffer; Count: Longint): Longint;
351 var
352 LocalBuffer: PChar;
353 localCount: uShort;
354 begin
355 CheckWritable;
356 LocalBuffer := PChar(@Buffer);
357 Result := 0;
358 if Count = 0 then Exit;
359
360 repeat
361 if Count > MaxuShort then
362 localCount := MaxuShort
363 else
364 localCount := Count;
365 with Firebird25ClientAPI do
366 Call(isc_put_segment(StatusVector,@FHandle,localCount,LocalBuffer));
367 Dec(Count,localCount);
368 Inc(LocalBuffer,localCount);
369 Inc(Result,localCount);
370 until Count = 0;
371 ClearStringCache;
372 end;
373
374
375 end.
376