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: 45
Committed: Tue Dec 6 10:33:46 2016 UTC (7 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 13066 byte(s)
Log Message:
Committing updates for Release R2-0-0

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    
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     FCharSetID := 0;
136     FSegmentSize := 80;
137     FUnconfirmedCharacterSet := false;
138     if (GetColumnName <> '') and (GetRelationName <> '') then
139     begin
140     with Firebird25ClientAPI do
141     Call(isc_blob_lookup_desc(StatusVector,@(FAttachment.Handle),
142     @(FTransaction.Handle),
143     PChar(AnsiUpperCase(GetRelationName)),PChar(AnsiUpperCase(GetColumnName)),@BlobDesc,@Global));
144     FCharSetID := BlobDesc.blob_desc_charset;
145     FSubType := BlobDesc.blob_desc_subtype;
146     FSegmentSize := BlobDesc.blob_desc_segment_size ;
147     end
148     else
149     FUnconfirmedCharacterSet := true;
150    
151     if (FCharSetID > 1) and FAttachment.HasDefaultCharSet then
152     begin
153     FCharSetID := FAttachment.CharSetID;
154     FUnconfirmedCharacterSet := false;
155     end;
156    
157    
158     FHasFullMetaData := true;
159     FHasSubType := true;
160     end;
161    
162     constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
163     Transaction: TFB25Transaction; RelationName, ColumnName: string);
164     begin
165     inherited Create(Transaction,RelationName,ColumnName);
166     FAttachment := Attachment;
167     FTransaction := Transaction;
168     end;
169    
170     constructor TFB25BlobMetaData.Create(Attachment: TFB25Attachment;
171     Transaction: TFB25Transaction; RelationName, ColumnName: string;
172     SubType: integer);
173     begin
174     Create(Attachment,Transaction,RelationName,ColumnName);
175     FSubType := SubType;
176     FHasSubType := true;
177     end;
178    
179     { TFB25Blob }
180    
181     procedure TFB25Blob.CheckReadable;
182     begin
183     if FCreating or (FHandle = nil) then
184     IBError(ibxeBlobCannotBeRead, [nil]);
185     end;
186    
187     procedure TFB25Blob.CheckWritable;
188     begin
189     if not FCreating or (FHandle = nil) then
190     IBError(ibxeBlobCannotBeWritten, [nil]);
191     end;
192    
193     function TFB25Blob.GetIntf: IBlob;
194     begin
195     Result := self;
196     end;
197    
198     procedure TFB25Blob.InternalClose(Force: boolean);
199     begin
200     if FHandle = nil then
201     Exit;
202     with Firebird25ClientAPI do
203     Call(isc_close_blob(StatusVector, @FHandle), not Force);
204     FHandle := nil;
205     end;
206    
207     procedure TFB25Blob.InternalCancel(Force: boolean);
208     begin
209     if FHandle = nil then
210     Exit;
211     with Firebird25ClientAPI do
212     Call(isc_cancel_blob(StatusVector,@FHandle),not Force);
213     FHandle := nil;
214     end;
215    
216     constructor TFB25Blob.Create(Attachment: TFB25Attachment; Transaction: TFB25Transaction;
217     MetaData: IBlobMetaData; BPB: IBPB);
218     var DBHandle: TISC_DB_HANDLE;
219     TRHandle: TISC_TR_HANDLE;
220     begin
221     inherited Create(Attachment,Transaction,MetaData,BPB);
222     DBHandle := Attachment.Handle;
223     TRHandle := Transaction.Handle;
224     with Firebird25ClientAPI do
225     if BPB = nil then
226     Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
227     0, nil))
228     else
229     with BPB as TBPB do
230     Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
231     getDataLength, getBuffer));
232     end;
233    
234     constructor TFB25Blob.Create(Attachment: TFB25Attachment;
235     Transaction: TFB25Transaction; SubType: integer; CharSetID: cardinal;
236     BPB: IBPB);
237     var DBHandle: TISC_DB_HANDLE;
238     TRHandle: TISC_TR_HANDLE;
239     MetaData: TFB25BlobMetaData;
240     begin
241     MetaData := TFB25BlobMetaData.Create(Attachment,Transaction,'','',SubType);
242     MetaData.FCharSetID := CharSetID;
243     MetaData.FHasFullMetaData := true;
244     inherited Create(Attachment,Transaction,MetaData,BPB);
245     DBHandle := Attachment.Handle;
246     TRHandle := Transaction.Handle;
247     with Firebird25ClientAPI do
248     if BPB = nil then
249     Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
250     0, nil))
251     else
252     with BPB as TBPB do
253     Call(isc_create_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle, @FBlobID,
254     getDataLength, getBuffer));
255     end;
256    
257     constructor TFB25Blob.Create(Attachment: TFB25Attachment;
258     Transaction: TFB25Transaction; MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB);
259     var DBHandle: TISC_DB_HANDLE;
260     TRHandle: TISC_TR_HANDLE;
261     begin
262     inherited Create(Attachment,Transaction,MetaData,BlobID,BPB);
263     DBHandle := Attachment.Handle;
264     TRHandle := Transaction.Handle;
265     if (BlobID.gds_quad_high = 0) and (BlobID.gds_quad_low = 0) then
266     Exit;
267    
268     with Firebird25ClientAPI do
269     if BPB = nil then
270     Call(isc_open_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle,
271     @FBlobID, 0, nil))
272     else
273     with BPB as TBPB do
274     Call(isc_open_blob2(StatusVector, @DBHandle, @TRHandle, @FHandle,
275     @FBlobID, getDataLength, getBuffer));
276     end;
277    
278     procedure TFB25Blob.GetInfo(var NumSegments: Int64; var MaxSegmentSize,
279     TotalSize: Int64; var BlobType: TBlobType);
280     var
281     items: array[0..3] of Char;
282     results: array[0..99] of Char;
283     i, item_length: Integer;
284     item: Integer;
285     begin
286     if FHandle = nil then
287     IBError(ibxeBlobNotOpen,[nil]);
288    
289     items[0] := Char(isc_info_blob_num_segments);
290     items[1] := Char(isc_info_blob_max_segment);
291     items[2] := Char(isc_info_blob_total_length);
292     items[3] := Char(isc_info_blob_type);
293    
294     with Firebird25ClientAPI do
295     begin
296     Call(isc_blob_info(StatusVector, @FHandle, 4, @items[0], SizeOf(results),
297     @results[0]));
298     i := 0;
299     while (i < SizeOf(results)) and (results[i] <> Char(isc_info_end)) do
300     begin
301     item := Integer(results[i]); Inc(i);
302     item_length := isc_portable_integer(@results[i], 2); Inc(i, 2);
303     case item of
304     isc_info_blob_num_segments:
305     NumSegments := isc_portable_integer(@results[i], item_length);
306     isc_info_blob_max_segment:
307     MaxSegmentSize := isc_portable_integer(@results[i], item_length);
308     isc_info_blob_total_length:
309     TotalSize := isc_portable_integer(@results[i], item_length);
310     isc_info_blob_type:
311     if isc_portable_integer(@results[i], item_length) = 0 then
312     BlobType := btSegmented
313     else
314     BlobType := btStream;
315     end;
316     Inc(i, item_length);
317     end;
318     end;
319     end;
320    
321     function TFB25Blob.Read(var Buffer; Count: Longint): Longint;
322     var
323     BytesRead : UShort;
324     LocalBuffer: PChar;
325     returnCode: long;
326     localCount: uShort;
327     begin
328     CheckReadable;
329     Result := 0;
330     if FEOB then
331     Exit;
332    
333     LocalBuffer := PChar(@Buffer);
334     repeat
335     if Count > MaxuShort then
336     localCount := MaxuShort
337     else
338     localCount := Count;
339     with Firebird25ClientAPI do
340     returnCode := isc_get_segment(StatusVector, @FHandle, @BytesRead, localCount,
341     LocalBuffer);
342     Inc(LocalBuffer,BytesRead);
343     Inc(Result,BytesRead);
344     Dec(Count,BytesRead);
345     until ((returncode <> 0) and (returnCode <> isc_segment)) or (Count = 0);
346    
347     FEOB := returnCode = isc_segstr_eof;
348     ClearStringCache;
349     if (returnCode <> 0) and (returnCode <> isc_segment) and (returnCode <> isc_segstr_eof) then
350     Firebird25ClientAPI.IBDataBaseError
351     end;
352    
353     function TFB25Blob.Write(const Buffer; Count: Longint): Longint;
354     var
355     LocalBuffer: PChar;
356     localCount: uShort;
357     begin
358     CheckWritable;
359     LocalBuffer := PChar(@Buffer);
360     Result := 0;
361     if Count = 0 then Exit;
362    
363     repeat
364     if Count > MaxuShort then
365     localCount := MaxuShort
366     else
367     localCount := Count;
368     with Firebird25ClientAPI do
369     Call(isc_put_segment(StatusVector,@FHandle,localCount,LocalBuffer));
370     Dec(Count,localCount);
371     Inc(LocalBuffer,localCount);
372     Inc(Result,localCount);
373     until Count = 0;
374     ClearStringCache;
375     end;
376    
377    
378     end.
379