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: 56
Committed: Mon Mar 6 10:20:02 2017 UTC (7 years, 1 month ago) by tony
Content type: text/x-pascal
File size: 12058 byte(s)
Log Message:
Committing updates for Trunk

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