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: 263
Committed: Thu Dec 6 15:55:01 2018 UTC (5 years, 11 months ago) by tony
Content type: text/x-pascal
File size: 12759 byte(s)
Log Message:
Release 2.3.2 committed

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 {$IFDEF MSWINDOWS}
64 {$DEFINE WINDOWS}
65 {$ENDIF}
66
67 {$IFDEF FPC}
68 {$mode delphi}
69 {$interfaces COM}
70 {$ENDIF}
71
72 interface
73
74 uses
75 Classes, SysUtils, IB, IBHeader,IBExternals, FBClientAPI, FB25ClientAPI, FB25Attachment,
76 FB25Transaction, FBActivityMonitor, FBBlob, FBOutputBlock;
77
78 type
79
80 { TFB25BlobMetaData }
81
82 TFB25BlobMetaData = class(TFBBlobMetaData, IBlobMetaData)
83 private
84 FHasFullMetaData: boolean;
85 FAttachment: TFB25Attachment;
86 FTransaction: TFB25Transaction;
87 FFirebird25ClientAPI: TFB25ClientAPI;
88 protected
89 function Attachment: IAttachment; override;
90 procedure NeedFullMetadata; override;
91 public
92 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
93 RelationName, ColumnName: AnsiString); overload;
94 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
95 RelationName, ColumnName: AnsiString; SubType: integer); overload;
96 end;
97
98
99 { TFB25Blob }
100
101 TFB25Blob = class(TFBBlob,IBlob)
102 private
103 FHandle: TISC_BLOB_HANDLE;
104 FEOB: boolean;
105 FFirebird25ClientAPI: TFB25ClientAPI;
106 protected
107 procedure CheckReadable; override;
108 procedure CheckWritable; override;
109 function GetIntf: IBlob; override;
110 procedure GetInfo(Request: array of byte; Response: IBlobInfo); override;
111 procedure InternalClose(Force: boolean); override;
112 procedure InternalCancel(Force: boolean); override;
113 public
114 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
115 MetaData: IBlobMetaData; BPB: IBPB); overload;
116 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
117 SubType: integer; CharSetID: cardinal; BPB: IBPB); overload;
118 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
119 MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB); overload;
120 property Handle: TISC_BLOB_HANDLE read FHandle;
121
122 public
123 function Read(var Buffer; Count: Longint): Longint; override;
124 function Write(const Buffer; Count: Longint): Longint; override;
125 end;
126
127 implementation
128
129 uses IBErrorCodes, FBMessages, FBParamBlock;
130
131 { TFB25BlobMetaData }
132
133 function TFB25BlobMetaData.Attachment: IAttachment;
134 begin
135 Result := FAttachment;
136 end;
137
138 procedure TFB25BlobMetaData.NeedFullMetadata;
139 var
140 BlobDesc: TISC_BLOB_DESC;
141 Global: array [0..31] of char;
142 RelName: AnsiString;
143 ColName: AnsiString;
144 begin
145 if FHasFullMetaData then Exit;
146
147 FSegmentSize := 80;
148 RelName := AnsiUpperCase(GetRelationName);
149 ColName := AnsiUpperCase(GetColumnName);
150 if (ColName <> '') and (RelName <> '') then
151 begin
152 with FFirebird25ClientAPI do
153 Call(isc_blob_lookup_desc(StatusVector,@(FAttachment.Handle),
154 @(FTransaction.Handle),
155 PAnsiChar(RelName),PAnsiChar(ColName),@BlobDesc,@Global));
156 if FUnconfirmedCharacterSet then
157 FCharSetID := BlobDesc.blob_desc_charset;
158 FSubType := BlobDesc.blob_desc_subtype;
159 FSegmentSize := BlobDesc.blob_desc_segment_size ;
160 end;
161
162 if FUnconfirmedCharacterSet and (FCharSetID > 1) and FAttachment.HasDefaultCharSet then
163 begin
164 FCharSetID := FAttachment.CharSetID;
165 FUnconfirmedCharacterSet := false;
166 end;
167
168
169 FHasFullMetaData := true;
170 FHasSubType := true;
171 end;
172
173 constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
174 Transaction: TFB25Transaction; RelationName, ColumnName: AnsiString);
175 begin
176 inherited Create(Transaction,RelationName,ColumnName);
177 FAttachment := Attachment;
178 FTransaction := Transaction;
179 FFirebird25ClientAPI := Attachment.Firebird25ClientAPI;
180 OnDatabaseError := FFirebird25ClientAPI.IBDataBaseError;
181 end;
182
183 constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
184 Transaction: TFB25Transaction; RelationName, ColumnName: AnsiString;
185 SubType: integer);
186 begin
187 Create(Attachment,Transaction,RelationName,ColumnName);
188 FSubType := SubType;
189 FHasSubType := true;
190 end;
191
192 { TFB25Blob }
193
194 procedure TFB25Blob.CheckReadable;
195 begin
196 if FCreating or (FHandle = nil) then
197 IBError(ibxeBlobCannotBeRead, [nil]);
198 end;
199
200 procedure TFB25Blob.CheckWritable;
201 begin
202 if not FCreating or (FHandle = nil) then
203 IBError(ibxeBlobCannotBeWritten, [nil]);
204 end;
205
206 function TFB25Blob.GetIntf: IBlob;
207 begin
208 Result := self;
209 end;
210
211 procedure TFB25Blob.GetInfo(Request: array of byte; Response: IBlobInfo);
212 begin
213 if FHandle = nil then
214 IBError(ibxeBlobNotOpen,[nil]);
215
216 with FFirebird25ClientAPI, Response as TBlobInfo do
217 Call(isc_blob_info(StatusVector, @FHandle, Length(Request),@Request,
218 GetBufSize, Buffer));
219 end;
220
221 procedure TFB25Blob.InternalClose(Force: boolean);
222 begin
223 if FHandle = nil then
224 Exit;
225 with FFirebird25ClientAPI do
226 Call(isc_close_blob(StatusVector, @FHandle), not Force);
227 FHandle := nil;
228 end;
229
230 procedure TFB25Blob.InternalCancel(Force: boolean);
231 begin
232 if FHandle = nil then
233 Exit;
234 with FFirebird25ClientAPI do
235 Call(isc_cancel_blob(StatusVector,@FHandle),not Force);
236 FHandle := nil;
237 end;
238
239 constructor TFB25Blob.Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
240 MetaData: IBlobMetaData; BPB: IBPB);
241 var DBHandle: TISC_DB_HANDLE;
242 TRHandle: TISC_TR_HANDLE;
243 begin
244 inherited Create(Attachment,Transaction,MetaData,BPB);
245 DBHandle := Attachment.Handle;
246 TRHandle := Transaction.Handle;
247 FFirebird25ClientAPI := Attachment.Firebird25ClientAPI;
248 OnDatabaseError := FFirebird25ClientAPI.IBDataBaseError;
249 with FFirebird25ClientAPI do
250 if BPB = nil then
251 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
252 0, nil))
253 else
254 with BPB as TBPB do
255 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
256 getDataLength, getBuffer));
257 end;
258
259 constructor TFB25Blob.Create(Attachment: TFB25Attachment;
260 Transaction: TFB25Transaction; SubType: integer; CharSetID: cardinal;
261 BPB: IBPB);
262 var DBHandle: TISC_DB_HANDLE;
263 TRHandle: TISC_TR_HANDLE;
264 MetaData: TFB25BlobMetaData;
265 begin
266 MetaData := TFB25BlobMetaData.Create(Attachment,Transaction,'','',SubType);
267 MetaData.FCharSetID := CharSetID;
268 MetaData.FHasFullMetaData := true;
269 inherited Create(Attachment,Transaction,MetaData,BPB);
270 DBHandle := Attachment.Handle;
271 TRHandle := Transaction.Handle;
272 FFirebird25ClientAPI := Attachment.Firebird25ClientAPI;
273 OnDatabaseError := FFirebird25ClientAPI.IBDataBaseError;
274 with FFirebird25ClientAPI do
275 if BPB = nil then
276 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
277 0, nil))
278 else
279 with BPB as TBPB do
280 Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
281 getDataLength, getBuffer));
282 end;
283
284 constructor TFB25Blob.Create(Attachment: TFB25Attachment;
285 Transaction: TFB25Transaction; MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB);
286 var DBHandle: TISC_DB_HANDLE;
287 TRHandle: TISC_TR_HANDLE;
288 begin
289 inherited Create(Attachment,Transaction,MetaData,BlobID,BPB);
290 DBHandle := Attachment.Handle;
291 TRHandle := Transaction.Handle;
292 FFirebird25ClientAPI := Attachment.Firebird25ClientAPI;
293 OnDatabaseError := FFirebird25ClientAPI.IBDataBaseError;
294 if (BlobID.gds_quad_high = 0) and (BlobID.gds_quad_low = 0) then
295 Exit;
296
297 with FFirebird25ClientAPI do
298 if BPB = nil then
299 Call(isc_open_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle,
300 @FBlobID, 0, nil))
301 else
302 with BPB as TBPB do
303 Call(isc_open_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle,
304 @FBlobID, getDataLength, getBuffer));
305 end;
306
307 function TFB25Blob.Read(var Buffer; Count: Longint): Longint;
308 var
309 BytesRead : UShort;
310 LocalBuffer: PByte;
311 returnCode: long;
312 localCount: uShort;
313 begin
314 CheckReadable;
315 Result := 0;
316 if FEOB then
317 Exit;
318
319 LocalBuffer := PByte(@Buffer);
320 repeat
321 if Count > MaxuShort then
322 localCount := MaxuShort
323 else
324 localCount := Count;
325 with FFirebird25ClientAPI do
326 returnCode := isc_get_segment(StatusVector, @FHandle, @BytesRead, localCount,
327 LocalBuffer);
328 Inc(LocalBuffer,BytesRead);
329 Inc(Result,BytesRead);
330 Dec(Count,BytesRead);
331 until ((returncode <> 0) and (returnCode <> isc_segment)) or (Count = 0);
332
333 FEOB := returnCode = isc_segstr_eof;
334 ClearStringCache;
335 if (returnCode <> 0) and (returnCode <> isc_segment) and (returnCode <> isc_segstr_eof) then
336 FFirebird25ClientAPI.IBDataBaseError
337 end;
338
339 function TFB25Blob.Write(const Buffer; Count: Longint): Longint;
340 var
341 LocalBuffer: PByte;
342 localCount: uShort;
343 begin
344 CheckWritable;
345 LocalBuffer := PByte(@Buffer);
346 Result := 0;
347 if Count = 0 then Exit;
348
349 repeat
350 if Count > MaxuShort then
351 localCount := MaxuShort
352 else
353 localCount := Count;
354 with FFirebird25ClientAPI do
355 Call(isc_put_segment(StatusVector,@FHandle,localCount,LocalBuffer));
356 Dec(Count,localCount);
357 Inc(LocalBuffer,localCount);
358 Inc(Result,localCount);
359 until Count = 0;
360 ClearStringCache;
361 end;
362
363
364 end.
365