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: 47
Committed: Mon Jan 9 15:31:51 2017 UTC (7 years, 3 months ago) by tony
Content type: text/x-pascal
File size: 13034 byte(s)
Log Message:
Committing updates for Release R2-0-1

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