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: 60
Committed: Mon Mar 27 15:21:02 2017 UTC (7 years, 8 months ago) by tony
Content type: text/x-pascal
File size: 12196 byte(s)
Log Message:

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