ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/fbintf/client/3.0/FB30Attachment.pas
Revision: 345
Committed: Mon Aug 23 14:22:29 2021 UTC (2 years, 7 months ago) by tony
Content type: text/x-pascal
Original Path: ibx/trunk/fbintf/client/3.0/FB30Attachment.pas
File size: 14914 byte(s)
Log Message:
Merged into public release

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 FB30Attachment;
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 tony 315 Classes, SysUtils, FBAttachment, FBClientAPI, FB30ClientAPI, Firebird, IB,
41     FBActivityMonitor, FBParamBlock;
42 tony 45
43     type
44    
45     { TFB30Attachment }
46    
47     TFB30Attachment = class(TFBAttachment,IAttachment, IActivityMonitor)
48     private
49     FAttachmentIntf: Firebird.IAttachment;
50 tony 263 FFirebird30ClientAPI: TFB30ClientAPI;
51 tony 315 FTimeZoneServices: ITimeZoneServices;
52     FUsingRemoteICU: boolean;
53     procedure SetUseRemoteICU(aValue: boolean);
54 tony 45 protected
55     procedure CheckHandle; override;
56     public
57 tony 263 constructor Create(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB;
58 tony 45 RaiseExceptionOnConnectError: boolean);
59 tony 263 constructor CreateDatabase(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB; RaiseExceptionOnError: boolean); overload;
60     constructor CreateDatabase(api: TFB30ClientAPI; sql: AnsiString; aSQLDialect: integer;
61 tony 47 RaiseExceptionOnError: boolean); overload;
62 tony 45 destructor Destroy; override;
63 tony 143 function GetDBInfo(ReqBuffer: PByte; ReqBufLen: integer): IDBInformation;
64     override;
65 tony 45 property AttachmentIntf: Firebird.IAttachment read FAttachmentIntf;
66 tony 263 property Firebird30ClientAPI: TFB30ClientAPI read FFirebird30ClientAPI;
67 tony 45
68     public
69     {IAttachment}
70     procedure Connect;
71     procedure Disconnect(Force: boolean=false); override;
72 tony 117 function IsConnected: boolean; override;
73 tony 45 procedure DropDatabase;
74     function StartTransaction(TPB: array of byte; DefaultCompletion: TTransactionCompletion): ITransaction; override;
75     function StartTransaction(TPB: ITPB; DefaultCompletion: TTransactionCompletion): ITransaction; override;
76 tony 56 procedure ExecImmediate(transaction: ITransaction; sql: AnsiString; aSQLDialect: integer); override;
77     function Prepare(transaction: ITransaction; sql: AnsiString; aSQLDialect: integer): IStatement; override;
78     function PrepareWithNamedParameters(transaction: ITransaction; sql: AnsiString;
79 tony 270 aSQLDialect: integer; GenerateParamNames: boolean=false;
80     CaseSensitiveParams: boolean=false): IStatement; override;
81 tony 45
82     {Events}
83     function GetEventHandler(Events: TStrings): IEvents; override;
84    
85     {Blob - may use to open existing Blobs. However, ISQLData.AsBlob is preferred}
86    
87 tony 291 function CreateBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BPB: IBPB=nil): IBlob; overload; override;
88 tony 45 function CreateBlob(transaction: ITransaction; SubType: integer; aCharSetID: cardinal=0; BPB: IBPB=nil): IBlob; overload;
89 tony 56 function OpenBlob(transaction: ITransaction; BlobMetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB=nil): IBlob; overload; override;
90 tony 45
91     {Array}
92 tony 291 function OpenArray(transaction: ITransaction; ArrayMetaData: IArrayMetaData; ArrayID: TISC_QUAD): IArray; overload; override;
93     function CreateArray(transaction: ITransaction; ArrayMetaData: IArrayMetaData): IArray; overload; override;
94 tony 56 function CreateArrayMetaData(SQLType: cardinal; tableName: AnsiString;
95     columnName: AnsiString; Scale: integer; size: cardinal; aCharSetID: cardinal;
96 tony 263 dimensions: cardinal; bounds: TArrayBounds): IArrayMetaData;
97 tony 45
98 tony 47
99 tony 45 {Database Information}
100 tony 291 function GetBlobMetaData(Transaction: ITransaction; tableName, columnName: AnsiString): IBlobMetaData; override;
101     function GetArrayMetaData(Transaction: ITransaction; tableName, columnName: AnsiString): IArrayMetaData; override;
102 tony 266 procedure getFBVersion(version: TStrings);
103 tony 315 function HasDecFloatSupport: boolean; override;
104 tony 345 function HasBatchMode: boolean; override;
105 tony 315
106     {Time Zone Support}
107     function GetTimeZoneServices: ITimeZoneServices; override;
108     function HasTimeZoneSupport: boolean; override;
109 tony 45 end;
110    
111     implementation
112    
113     uses FB30Transaction, FB30Statement, FB30Array, FB30Blob, FBMessages,
114 tony 315 FBOutputBlock, FB30Events, IBUtils, FB30TimeZoneServices;
115 tony 45
116 tony 266 type
117     { TVersionCallback }
118    
119     TVersionCallback = class(Firebird.IVersionCallbackImpl)
120     private
121     FOutput: TStrings;
122 tony 315 FFirebirdClientAPI: TFBClientAPI;
123 tony 266 public
124 tony 315 constructor Create(FirebirdClientAPI: TFBClientAPI; output: TStrings);
125 tony 266 procedure callback(status: Firebird.IStatus; text: PAnsiChar); override;
126     end;
127    
128     { TVersionCallback }
129    
130 tony 315 constructor TVersionCallback.Create(FirebirdClientAPI: TFBClientAPI;
131     output: TStrings);
132 tony 266 begin
133     inherited Create;
134 tony 315 FFirebirdClientAPI := FirebirdClientAPI;
135 tony 266 FOutput := output;
136     end;
137    
138     procedure TVersionCallback.callback(status: Firebird.IStatus; text: PAnsiChar);
139 tony 315 var StatusObj: TFB30StatusObject;
140 tony 266 begin
141 tony 315 if ((status.getState and status.STATE_ERRORS) <> 0) then
142     begin
143     StatusObj := TFB30StatusObject.Create(FFirebirdClientAPI,status);
144     try
145     raise EIBInterBaseError.Create(StatusObj);
146     finally
147     StatusObj.Free;
148     end;
149     end;
150 tony 266 FOutput.Add(text);
151     end;
152    
153    
154 tony 45 { TFB30Attachment }
155    
156 tony 315 procedure TFB30Attachment.SetUseRemoteICU(aValue: boolean);
157     begin
158     if (FUsingRemoteICU <> aValue) and (GetODSMajorVersion >= 13) then
159     begin
160     if aValue then
161     ExecImmediate([isc_tpb_write,isc_tpb_wait,isc_tpb_concurrency],'SET BIND OF TIME ZONE TO EXTENDED')
162     else
163     ExecImmediate([isc_tpb_write,isc_tpb_wait,isc_tpb_concurrency],'SET BIND OF TIME ZONE TO NATIVE');
164     FUsingRemoteICU := aValue;
165     end;
166     end;
167    
168 tony 45 procedure TFB30Attachment.CheckHandle;
169     begin
170     if FAttachmentIntf = nil then
171     IBError(ibxeDatabaseClosed,[nil]);
172     end;
173    
174 tony 263 constructor TFB30Attachment.Create(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB;
175 tony 45 RaiseExceptionOnConnectError: boolean);
176     begin
177 tony 263 FFirebird30ClientAPI := api;
178 tony 45 if aDPB = nil then
179     begin
180     if RaiseExceptionOnConnectError then
181     IBError(ibxeNoDPB,[nil]);
182     Exit;
183     end;
184 tony 263 inherited Create(api,DatabaseName,aDPB,RaiseExceptionOnConnectError);
185 tony 45 Connect;
186     end;
187    
188 tony 263 constructor TFB30Attachment.CreateDatabase(api: TFB30ClientAPI; DatabaseName: AnsiString; aDPB: IDPB;
189 tony 45 RaiseExceptionOnError: boolean);
190     var Param: IDPBItem;
191 tony 56 sql: AnsiString;
192 tony 45 IsCreateDB: boolean;
193     begin
194 tony 263 inherited Create(api,DatabaseName,aDPB,RaiseExceptionOnError);
195     FFirebird30ClientAPI := api;
196 tony 45 IsCreateDB := true;
197     if aDPB <> nil then
198     begin
199     Param := aDPB.Find(isc_dpb_set_db_SQL_dialect);
200     if Param <> nil then
201     FSQLDialect := Param.AsByte;
202     end;
203     sql := GenerateCreateDatabaseSQL(DatabaseName,aDPB);
204 tony 263 with FFirebird30ClientAPI do
205 tony 45 begin
206     FAttachmentIntf := UtilIntf.executeCreateDatabase(StatusIntf,Length(sql),
207     PAnsiChar(sql),FSQLDialect,@IsCreateDB);
208     if FRaiseExceptionOnConnectError then Check4DataBaseError;
209     if InErrorState then
210     FAttachmentIntf := nil
211     else
212     if aDPB <> nil then
213     {Connect using known parameters}
214     begin
215     Disconnect;
216     Connect;
217 tony 117 end
218     else
219     GetODSAndConnectionInfo;
220 tony 45 end;
221     end;
222    
223 tony 263 constructor TFB30Attachment.CreateDatabase(api: TFB30ClientAPI; sql: AnsiString; aSQLDialect: integer;
224 tony 47 RaiseExceptionOnError: boolean);
225     var IsCreateDB: boolean;
226     begin
227 tony 263 inherited Create(api,'',nil,RaiseExceptionOnError);
228     FFirebird30ClientAPI := api;
229 tony 47 FSQLDialect := aSQLDialect;
230 tony 263 with FFirebird30ClientAPI do
231 tony 47 begin
232     FAttachmentIntf := UtilIntf.executeCreateDatabase(StatusIntf,Length(sql),
233     PAnsiChar(sql),aSQLDialect,@IsCreateDB);
234     if FRaiseExceptionOnConnectError then Check4DataBaseError;
235     if InErrorState then
236     FAttachmentIntf := nil;
237     end;
238 tony 117 GetODSAndConnectionInfo;
239     ExtractConnectString(sql,FDatabaseName);
240     DPBFromCreateSQL(sql);
241 tony 47 end;
242    
243 tony 45 destructor TFB30Attachment.Destroy;
244     begin
245     inherited Destroy;
246     if assigned(FAttachmentIntf) then
247     FAttachmentIntf.release;
248     end;
249    
250 tony 143 function TFB30Attachment.GetDBInfo(ReqBuffer: PByte; ReqBufLen: integer): IDBInformation;
251     begin
252 tony 263 Result := TDBInformation.Create(Firebird30ClientAPI);
253     with FFirebird30ClientAPI, Result as TDBInformation do
254 tony 143 begin
255     FAttachmentIntf.getInfo(StatusIntf, ReqBufLen, BytePtr(ReqBuffer),
256     getBufSize, BytePtr(Buffer));
257     Check4DataBaseError;
258     end
259     end;
260    
261 tony 45 procedure TFB30Attachment.Connect;
262     begin
263 tony 263 with FFirebird30ClientAPI do
264 tony 45 begin
265     FAttachmentIntf := ProviderIntf.attachDatabase(StatusIntf,PAnsiChar(FDatabaseName),
266     (DPB as TDPB).getDataLength,
267     BytePtr((DPB as TDPB).getBuffer));
268     if FRaiseExceptionOnConnectError then Check4DataBaseError;
269     if InErrorState then
270     FAttachmentIntf := nil
271     else
272 tony 117 GetODSAndConnectionInfo;
273 tony 315
274 tony 45 end;
275     end;
276    
277     procedure TFB30Attachment.Disconnect(Force: boolean);
278     begin
279     if IsConnected then
280 tony 263 with FFirebird30ClientAPI do
281 tony 45 begin
282     EndAllTransactions;
283     FAttachmentIntf.Detach(StatusIntf);
284     if not Force and InErrorState then
285     IBDataBaseError;
286     FAttachmentIntf := nil;
287     FHasDefaultCharSet := false;
288     FCodePage := CP_NONE;
289     FCharSetID := 0;
290 tony 315 FTimeZoneServices := nil;
291 tony 45 end;
292     end;
293    
294     function TFB30Attachment.IsConnected: boolean;
295     begin
296     Result := FAttachmentIntf <> nil;
297     end;
298    
299     procedure TFB30Attachment.DropDatabase;
300     begin
301     if IsConnected then
302 tony 263 with FFirebird30ClientAPI do
303 tony 45 begin
304     EndAllTransactions;
305     FAttachmentIntf.dropDatabase(StatusIntf);
306     Check4DataBaseError;
307     FAttachmentIntf := nil;
308     end;
309     end;
310    
311     function TFB30Attachment.StartTransaction(TPB: array of byte;
312     DefaultCompletion: TTransactionCompletion): ITransaction;
313     begin
314     CheckHandle;
315 tony 263 Result := TFB30Transaction.Create(FFirebird30ClientAPI,self,TPB,DefaultCompletion);
316 tony 45 end;
317    
318     function TFB30Attachment.StartTransaction(TPB: ITPB;
319     DefaultCompletion: TTransactionCompletion): ITransaction;
320     begin
321     CheckHandle;
322 tony 263 Result := TFB30Transaction.Create(FFirebird30ClientAPI,self,TPB,DefaultCompletion);
323 tony 45 end;
324    
325 tony 56 procedure TFB30Attachment.ExecImmediate(transaction: ITransaction; sql: AnsiString;
326 tony 45 aSQLDialect: integer);
327     begin
328     CheckHandle;
329 tony 263 with FFirebird30ClientAPI do
330 tony 45 begin
331     FAttachmentIntf.execute(StatusIntf,(transaction as TFB30Transaction).TransactionIntf,
332 tony 56 Length(sql),PAnsiChar(sql),aSQLDialect,nil,nil,nil,nil);
333 tony 45 Check4DataBaseError;
334     end;
335     end;
336    
337 tony 56 function TFB30Attachment.Prepare(transaction: ITransaction; sql: AnsiString;
338 tony 45 aSQLDialect: integer): IStatement;
339     begin
340     CheckHandle;
341     Result := TFB30Statement.Create(self,transaction,sql,aSQLDialect);
342     end;
343    
344     function TFB30Attachment.PrepareWithNamedParameters(transaction: ITransaction;
345 tony 270 sql: AnsiString; aSQLDialect: integer; GenerateParamNames: boolean;
346     CaseSensitiveParams: boolean): IStatement;
347 tony 45 begin
348     CheckHandle;
349     Result := TFB30Statement.CreateWithParameterNames(self,transaction,sql,aSQLDialect,
350 tony 270 GenerateParamNames,CaseSensitiveParams);
351 tony 45 end;
352    
353     function TFB30Attachment.GetEventHandler(Events: TStrings): IEvents;
354     begin
355     CheckHandle;
356     Result := TFB30Events.Create(self,Events);
357     end;
358    
359     function TFB30Attachment.CreateBlob(transaction: ITransaction;
360     BlobMetaData: IBlobMetaData; BPB: IBPB): IBlob;
361     begin
362     CheckHandle;
363     Result := TFB30Blob.Create(self,transaction as TFB30Transaction, BlobMetaData,BPB);
364     end;
365    
366     function TFB30Attachment.CreateBlob(transaction: ITransaction;
367     SubType: integer; aCharSetID: cardinal; BPB: IBPB): IBlob;
368     begin
369     CheckHandle;
370     Result := TFB30Blob.Create(self,transaction as TFB30Transaction, SubType,aCharSetID,BPB);
371     end;
372    
373     function TFB30Attachment.OpenBlob(transaction: ITransaction;
374     BlobMetaData: IBlobMetaData; BlobID: TISC_QUAD; BPB: IBPB): IBlob;
375     begin
376     CheckHandle;
377     Result := TFB30Blob.Create(self,transaction as TFB30transaction,BlobMetaData,BlobID,BPB);
378     end;
379    
380 tony 291 function TFB30Attachment.OpenArray(transaction: ITransaction;
381     ArrayMetaData: IArrayMetaData; ArrayID: TISC_QUAD): IArray;
382 tony 45 begin
383     CheckHandle;
384     Result := TFB30Array.Create(self,transaction as TFB30Transaction,
385 tony 291 ArrayMetaData,ArrayID);
386 tony 45 end;
387    
388     function TFB30Attachment.CreateArray(transaction: ITransaction;
389     ArrayMetaData: IArrayMetaData): IArray;
390     begin
391     CheckHandle;
392     Result := TFB30Array.Create(self,transaction as TFB30Transaction,ArrayMetaData);
393     end;
394    
395 tony 56 function TFB30Attachment.CreateArrayMetaData(SQLType: cardinal; tableName: AnsiString; columnName: AnsiString;
396 tony 47 Scale: integer; size: cardinal; aCharSetID: cardinal; dimensions: cardinal;
397     bounds: TArrayBounds): IArrayMetaData;
398     begin
399 tony 60 Result := TFB30ArrayMetaData.Create(self,SQLType,tableName,ColumnName,Scale,size,aCharSetID, dimensions,bounds);
400 tony 47 end;
401    
402 tony 45 function TFB30Attachment.GetBlobMetaData(Transaction: ITransaction; tableName,
403 tony 56 columnName: AnsiString): IBlobMetaData;
404 tony 45 begin
405     CheckHandle;
406     Result := TFB30BlobMetaData.Create(self,Transaction as TFB30Transaction,tableName,columnName);
407     end;
408    
409     function TFB30Attachment.GetArrayMetaData(Transaction: ITransaction; tableName,
410 tony 56 columnName: AnsiString): IArrayMetaData;
411 tony 45 begin
412     CheckHandle;
413     Result := TFB30ArrayMetaData.Create(self,Transaction as TFB30Transaction,tableName,columnName);
414     end;
415    
416 tony 266 procedure TFB30Attachment.getFBVersion(version: TStrings);
417     var bufferObj: TVersionCallback;
418     begin
419 tony 267 version.Clear;
420 tony 315 bufferObj := TVersionCallback.Create(Firebird30ClientAPI,version);
421 tony 266 try
422     with FFirebird30ClientAPI do
423 tony 267 begin
424 tony 266 UtilIntf.getFbVersion(StatusIntf,FAttachmentIntf,bufferObj);
425 tony 267 Check4DataBaseError;
426     end;
427 tony 266 finally
428     bufferObj.Free;
429     end;
430     end;
431    
432 tony 315 function TFB30Attachment.HasDecFloatSupport: boolean;
433     begin
434     Result := (FFirebird30ClientAPI.GetClientMajor >= 4) and
435     (GetODSMajorVersion >= 13);
436     end;
437    
438 tony 345 function TFB30Attachment.HasBatchMode: boolean;
439     begin
440     Result := FFirebird30ClientAPI.Firebird4orLater and
441     (GetODSMajorVersion >= 13);
442     end;
443    
444 tony 315 function TFB30Attachment.GetTimeZoneServices: ITimeZoneServices;
445     begin
446     if not HasTimeZoneSupport then
447     IBError(ibxeNotSupported,[]);
448    
449     if FTimeZoneServices = nil then
450     FTimeZoneServices := TFB30TimeZoneServices.Create(self);
451     Result := FTimeZoneServices;
452     end;
453    
454     function TFB30Attachment.HasTimeZoneSupport: boolean;
455     begin
456     Result := (FFirebird30ClientAPI.GetClientMajor >= 4) and
457     (GetODSMajorVersion >= 13);
458     end;
459    
460 tony 45 end.
461