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, 8 months ago) by tony
Content type: text/x-pascal
File size: 12058 byte(s)
Log Message:
Committing updates for Trunk

File Contents

# User Rev Content
1 tony 45 (*
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 tony 56 {$IFDEF MSWINDOWS}
64     {$DEFINE WINDOWS}
65     {$ENDIF}
66 tony 45
67     {$IFDEF FPC}
68 tony 56 {$mode delphi}
69 tony 45 {$interfaces COM}
70     {$ENDIF}
71    
72     interface
73    
74     uses
75     Classes, SysUtils, IB, IBHeader,IBExternals, FBClientAPI, FB25ClientAPI, FB25Attachment,
76 tony 56 FB25Transaction, FBActivityMonitor, FBBlob, FBOutputBlock;
77 tony 45
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 tony 56 RelationName, ColumnName: AnsiString); overload;
92 tony 45 constructor Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
93 tony 56 RelationName, ColumnName: AnsiString; SubType: integer); overload;
94 tony 45 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 tony 56 procedure GetInfo(Request: array of byte; Response: IBlobInfo); override;
108 tony 45 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 tony 56 RelName: AnsiString;
135     ColName: AnsiString;
136 tony 45 begin
137     if FHasFullMetaData then Exit;
138    
139     FSegmentSize := 80;
140 tony 56 RelName := AnsiUpperCase(GetRelationName);
141     ColName := AnsiUpperCase(GetColumnName);
142     if (ColName <> '') and (RelName <> '') then
143 tony 45 begin
144     with Firebird25ClientAPI do
145     Call(isc_blob_lookup_desc(StatusVector,@(FAttachment.Handle),
146     @(FTransaction.Handle),
147 tony 56 PAnsiChar(RelName),PAnsiChar(ColName),@BlobDesc,@Global));
148 tony 47 if FUnconfirmedCharacterSet then
149     FCharSetID := BlobDesc.blob_desc_charset;
150 tony 45 FSubType := BlobDesc.blob_desc_subtype;
151     FSegmentSize := BlobDesc.blob_desc_segment_size ;
152 tony 47 end;
153 tony 45
154 tony 47 if FUnconfirmedCharacterSet and (FCharSetID > 1) and FAttachment.HasDefaultCharSet then
155 tony 45 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 tony 56 Transaction: TFB25Transaction; RelationName, ColumnName: AnsiString);
167 tony 45 begin
168     inherited Create(Transaction,RelationName,ColumnName);
169     FAttachment := Attachment;
170     FTransaction := Transaction;
171     end;
172    
173     constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
174 tony 56 Transaction: TFB25Transaction; RelationName, ColumnName: AnsiString;
175 tony 45 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 tony 56 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 tony 45 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 tony 56 LocalBuffer: PByte;
295 tony 45 returnCode: long;
296     localCount: uShort;
297     begin
298     CheckReadable;
299     Result := 0;
300     if FEOB then
301     Exit;
302    
303 tony 56 LocalBuffer := PByte(@Buffer);
304 tony 45 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 tony 56 LocalBuffer: PByte;
326 tony 45 localCount: uShort;
327     begin
328     CheckWritable;
329 tony 56 LocalBuffer := PByte(@Buffer);
330 tony 45 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