ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/3.0/FB30Blob.pas
Revision: 60
Committed: Mon Mar 27 15:21:02 2017 UTC (7 years, 1 month ago) by tony
Content type: text/x-pascal
Original Path: ibx/trunk/fbintf/client/3.0/FB30Blob.pas
File size: 10141 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.
4     *
5     * The contents of this file are subject to the Initial Developer's
6     * Public License Version 1.0 (the "License"); you may not use this
7     * file except in compliance with the License. You may obtain a copy
8     * of the License here:
9     *
10     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
11     *
12     * Software distributed under the License is distributed on an "AS
13     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14     * implied. See the License for the specific language governing rights
15     * and limitations under the License.
16     *
17     * The Initial Developer of the Original Code is Tony Whyman.
18     *
19     * The Original Code is (C) 2016 Tony Whyman, MWA Software
20     * (http://www.mwasoftware.co.uk).
21     *
22     * All Rights Reserved.
23     *
24     * Contributor(s): ______________________________________.
25     *
26     *)
27     unit FB30Blob;
28 tony 56 {$IFDEF MSWINDOWS}
29     {$DEFINE WINDOWS}
30     {$ENDIF}
31 tony 45
32     {$IFDEF FPC}
33 tony 56 {$mode delphi}
34 tony 45 {$interfaces COM}
35     {$ENDIF}
36    
37     interface
38    
39     uses
40     Classes, SysUtils, Firebird, IB, IBHeader, IBExternals, FBClientAPI, FB30ClientAPI, FB30Attachment,
41 tony 56 FBTransaction, FB30Transaction, FBBlob, FBOutputBlock;
42 tony 45
43     type
44    
45     { TFB30BlobMetaData }
46    
47     TFB30BlobMetaData = class(TFBBlobMetaData, IBlobMetaData)
48     private
49     FHasFullMetaData: boolean;
50     FAttachment: TFB30Attachment;
51     FTransaction: TFB30Transaction;
52     protected
53 tony 60 function Attachment: IAttachment; override;
54 tony 45 procedure NeedFullMetadata; override;
55     public
56     constructor Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction;
57 tony 56 RelationName, ColumnName: AnsiString); overload;
58 tony 45 constructor Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction;
59 tony 56 RelationName, ColumnName: AnsiString; SubType: integer); overload;
60 tony 45
61     end;
62    
63    
64     { TFB30Blob }
65    
66     TFB30Blob = class(TFBBlob,IBlob)
67     private
68     FBlobIntf: Firebird.IBlob;
69     FEOB: boolean;
70     protected
71     procedure CheckReadable; override;
72     procedure CheckWritable; override;
73     function GetIntf: IBlob; override;
74 tony 56 procedure GetInfo(Request: array of byte; Response: IBlobInfo); override;
75 tony 45 procedure InternalClose(Force: boolean); override;
76     procedure InternalCancel(Force: boolean); override;
77     public
78     constructor Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction;
79     MetaData: IBlobMetaData; BPB: IBPB); overload;
80     constructor Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction;
81     SubType: integer; CharSetID: cardinal; BPB: IBPB); overload;
82     constructor Create(Attachment: TFB30Attachment; Transaction: TFBTransaction;
83     MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB); overload;
84     property BlobIntf: Firebird.IBlob read FBlobIntf;
85    
86     {IBlob}
87     public
88     function Read(var Buffer; Count: Longint): Longint; override;
89     function Write(const Buffer; Count: Longint): Longint; override;
90     end;
91    
92     implementation
93    
94 tony 47 uses FBMessages, FB30Statement, FBParamBlock, Math;
95 tony 45
96     const
97     sLookupBlobMetaData = 'Select F.RDB$FIELD_SUB_TYPE, F.RDB$SEGMENT_LENGTH, RDB$CHARACTER_SET_ID, F.RDB$FIELD_TYPE '+
98     'From RDB$FIELDS F JOIN RDB$RELATION_FIELDS R On R.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME '+
99     'Where Trim(R.RDB$RELATION_NAME) = Upper(Trim(?)) and Trim(R.RDB$FIELD_NAME) = Upper(Trim(?))';
100    
101     { TFB30BlobMetaData }
102    
103 tony 60 function TFB30BlobMetaData.Attachment: IAttachment;
104     begin
105     Result := FAttachment;
106     end;
107    
108 tony 45 procedure TFB30BlobMetaData.NeedFullMetadata;
109     var stmt: IStatement;
110     begin
111     if FHasFullMetaData then Exit;
112    
113     FSegmentSize := 80;
114     if (GetColumnName <> '') and (GetRelationName <> '') then
115     begin
116     stmt := TFB30Statement.Create(FAttachment,FTransaction, sLookupBlobMetaData ,FAttachment.SQLDialect);
117     with stmt do
118     begin
119     SQLParams[0].AsString := GetRelationName;
120     SQLParams[1].AsString := GetColumnName;
121     with OpenCursor do
122     if FetchNext then
123     begin
124     if Data[3].AsInteger <> blr_blob then
125     IBError(ibxeInvalidBlobMetaData,[nil]);
126     FSubType := Data[0].AsInteger;
127     FSegmentSize := Data[1].AsInteger;
128 tony 47 if FUnconfirmedCharacterSet then
129     FCharSetID := Data[2].AsInteger;
130 tony 45 end
131     else
132     IBError(ibxeInvalidBlobMetaData,[nil]);
133    
134     end;
135 tony 47 end;
136 tony 45
137 tony 47 if FUnconfirmedCharacterSet and (FCharSetID > 1) and FAttachment.HasDefaultCharSet then
138 tony 45 begin
139     FCharSetID := FAttachment.CharSetID;
140     FUnconfirmedCharacterSet := false;
141     end;
142    
143     FHasFullMetaData := true;
144     FHasSubType := true;
145     end;
146    
147     constructor TFB30BlobMetaData.Create(Attachment: TFB30Attachment;
148 tony 56 Transaction: TFB30Transaction; RelationName, ColumnName: AnsiString);
149 tony 45 begin
150     inherited Create(Transaction,RelationName,ColumnName);
151     FAttachment := Attachment;
152     FTransaction := Transaction;
153     end;
154    
155     constructor TFB30BlobMetaData.Create(Attachment: TFB30Attachment;
156 tony 56 Transaction: TFB30Transaction; RelationName, ColumnName: AnsiString;
157 tony 45 SubType: integer);
158     begin
159     Create(Attachment,Transaction,RelationName,ColumnName);
160     FSubType := SubType;
161     FHasSubType := true;
162     end;
163    
164     { TFB30Blob }
165    
166     procedure TFB30Blob.CheckReadable;
167     begin
168     if FCreating or (FBlobIntf = nil) then
169     IBError(ibxeBlobCannotBeRead, [nil]);
170     end;
171    
172     procedure TFB30Blob.CheckWritable;
173     begin
174     if not FCreating or (FBlobIntf = nil) then
175     IBError(ibxeBlobCannotBeWritten, [nil]);
176     end;
177    
178     function TFB30Blob.GetIntf: IBlob;
179     begin
180     Result := self;
181     end;
182    
183 tony 56 procedure TFB30Blob.GetInfo(Request: array of byte; Response: IBlobInfo);
184     begin
185     if FBlobIntf = nil then
186     IBError(ibxeBlobNotOpen,[nil]);
187    
188     with Firebird30ClientAPI, Response as TBlobInfo do
189     begin
190     FBlobIntf.getInfo(StatusIntf,Length(Request),BytePtr(@Request),
191     GetBufSize, BytePtr(Buffer));
192     Check4DataBaseError;
193     SignalActivity;
194     end;
195     end;
196    
197 tony 45 procedure TFB30Blob.InternalClose(Force: boolean);
198     begin
199     if FBlobIntf = nil then
200     Exit;
201     with Firebird30ClientAPI do
202     begin
203     FBlobIntf.close(StatusIntf);
204     if not Force then Check4DataBaseError;
205     end;
206     FBlobIntf.release;
207     FBlobIntf := nil;
208     end;
209    
210     procedure TFB30Blob.InternalCancel(Force: boolean);
211     begin
212     if FBlobIntf = nil then
213     Exit;
214     with Firebird30ClientAPI do
215     begin
216     FBlobIntf.cancel(StatusIntf);
217     if not Force then Check4DataBaseError;
218     end;
219     FBlobIntf.release;
220     FBlobIntf := nil;
221     end;
222    
223     constructor TFB30Blob.Create(Attachment: TFB30Attachment; Transaction: TFB30Transaction;
224     MetaData: IBlobMetaData; BPB: IBPB);
225     begin
226     inherited Create(Attachment,Transaction,MetaData,BPB);
227     with Firebird30ClientAPI do
228     begin
229     if BPB = nil then
230     FBlobIntf := Attachment.AttachmentIntf.createBlob(StatusIntf,Transaction.TransactionIntf,
231     @FBlobID,0,nil)
232     else
233     with BPB as TBPB do
234     FBlobIntf := Attachment.AttachmentIntf.createBlob(StatusIntf,Transaction.TransactionIntf,
235     @FBlobID,getDataLength, BytePtr(getBuffer));
236     Check4DataBaseError;
237     end;
238     end;
239    
240     constructor TFB30Blob.Create(Attachment: TFB30Attachment;
241     Transaction: TFB30Transaction; SubType: integer; CharSetID: cardinal;
242     BPB: IBPB);
243     var MetaData: TFB30BlobMetaData;
244     begin
245     MetaData := TFB30BlobMetaData.Create(Attachment,Transaction,'','',SubType);
246     MetaData.FCharSetID := CharSetID;
247     MetaData.FHasFullMetaData := true;
248     inherited Create(Attachment,Transaction,MetaData,BPB);
249     with Firebird30ClientAPI do
250     begin
251     if BPB = nil then
252     FBlobIntf := Attachment.AttachmentIntf.createBlob(StatusIntf,Transaction.TransactionIntf,
253     @FBlobID,0,nil)
254     else
255     with BPB as TBPB do
256     FBlobIntf := Attachment.AttachmentIntf.createBlob(StatusIntf,Transaction.TransactionIntf,
257     @FBlobID,getDataLength, BytePtr(getBuffer));
258     Check4DataBaseError;
259     end;
260     end;
261    
262     constructor TFB30Blob.Create(Attachment: TFB30Attachment;
263     Transaction: TFBTransaction; MetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB);
264     begin
265     inherited Create(Attachment,Transaction,MetaData,BlobID,BPB);
266     if (BlobID.gds_quad_high = 0) and (BlobID.gds_quad_low = 0) then
267     Exit;
268    
269     with Firebird30ClientAPI do
270     begin
271     if BPB = nil then
272     FBlobIntf := Attachment.AttachmentIntf.openBlob(StatusIntf,(Transaction as TFB30Transaction).TransactionIntf,
273     @FBlobID, 0, nil)
274     else
275     with BPB as TBPB do
276     FBlobIntf := Attachment.AttachmentIntf.openBlob(StatusIntf,(Transaction as TFB30Transaction).TransactionIntf,
277     @FBlobID, getDataLength, BytePtr(getBuffer));
278     Check4DataBaseError;
279     end;
280     end;
281    
282     function TFB30Blob.Read(var Buffer; Count: Longint): Longint;
283     var
284     BytesRead : cardinal;
285 tony 56 LocalBuffer: PAnsiChar;
286 tony 45 returnCode: integer;
287     localCount: uShort;
288     begin
289     CheckReadable;
290     Result := 0;
291     if FEOB then
292     Exit;
293    
294 tony 56 LocalBuffer := PAnsiChar(@Buffer);
295 tony 45 repeat
296 tony 47 localCount := Min(Count,MaxuShort);
297 tony 45 with Firebird30ClientAPI do
298     returnCode := FBlobIntf.getSegment(StatusIntf,localCount, LocalBuffer, @BytesRead);
299     SignalActivity;
300     Inc(LocalBuffer,BytesRead);
301     Inc(Result,BytesRead);
302     Dec(Count,BytesRead);
303     until ((returncode <> Firebird.IStatus.Result_OK) and (returnCode <> Firebird.IStatus.Result_SEGMENT)) or (Count = 0);
304    
305     FEOB := returnCode = Firebird.IStatus.RESULT_NO_DATA;
306     ClearStringCache;
307     if (returnCode <> Firebird.IStatus.Result_OK) and
308     (returnCode <> Firebird.IStatus.Result_SEGMENT) and
309     (returnCode <> Firebird.IStatus.RESULT_NO_DATA) then
310     Firebird30ClientAPI.IBDataBaseError
311     end;
312    
313     function TFB30Blob.Write(const Buffer; Count: Longint): Longint;
314 tony 47 var
315 tony 56 LocalBuffer: PAnsiChar;
316 tony 47 localCount: uShort;
317 tony 45 begin
318     CheckWritable;
319     Result := 0;
320     if Count = 0 then Exit;
321    
322 tony 56 LocalBuffer := PAnsiChar(@Buffer);
323 tony 47 repeat
324     localCount := Min(Count,MaxuShort);
325     with Firebird30ClientAPI do
326     begin
327     FBlobIntf.putSegment(StatusIntf,localCount,LocalBuffer);
328     Check4DataBaseError;
329     end;
330     Inc(LocalBuffer,localCount);
331     Inc(Result,localCount);
332     Dec(Count,localCount);
333     until Count = 0;
334 tony 45 ClearStringCache;
335     SignalActivity;
336     end;
337    
338     end.
339