ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/client/3.0/FB30ClientAPI.pas
Revision: 143
Committed: Fri Feb 23 12:11:21 2018 UTC (6 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 11395 byte(s)
Log Message:
Fixes Merged

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 FB30ClientAPI;
28 tony 56 {$IFDEF MSWINDOWS}
29     {$DEFINE WINDOWS}
30     {$ENDIF}
31 tony 45
32     {$IFDEF FPC}
33     {$mode delphi}
34     {$interfaces COM}
35     {$ENDIF}
36    
37     interface
38    
39     uses
40     Classes, SysUtils, FBClientAPI, Firebird, IB, IBExternals;
41    
42     type
43    
44     { TFB30Status }
45    
46     TFB30Status = class(TFBStatus,IStatus)
47     private
48     FStatus: Firebird.IStatus;
49     public
50     procedure Init;
51     function InErrorState: boolean;
52     function GetStatus: Firebird.IStatus;
53     function StatusVector: PStatusVector; override;
54     end;
55    
56     Tfb_get_master_interface = function: IMaster;
57     {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
58    
59     { TFB30ClientAPI }
60    
61     TFB30ClientAPI = class(TFBClientAPI,IFirebirdAPI)
62     private
63     FMaster: Firebird.IMaster;
64     FUtil: Firebird.IUtil;
65     FProvider: Firebird.IProvider;
66     FConfigManager: Firebird.IConfigManager;
67     FStatus: TFB30Status;
68     FIsEmbeddedServer: boolean;
69     FStatusIntf: IStatus; {Keep a reference to the interface - automatic destroy
70     when this class is freed and last reference to IStatus
71     goes out of scope.}
72     procedure CheckPlugins;
73     protected
74     {$IFDEF UNIX}
75     function GetFirebirdLibList: string; override;
76     {$ENDIF}
77     procedure LoadInterface; override;
78     public
79     constructor Create;
80     destructor Destroy; override;
81    
82     function StatusIntf: Firebird.IStatus;
83     procedure Check4DataBaseError;
84     function InErrorState: boolean;
85    
86     public
87     {IFirebirdAPI}
88     function GetStatus: IStatus; override;
89     function AllocateDPB: IDPB;
90     function AllocateTPB: ITPB;
91    
92     {Database connections}
93 tony 56 function OpenDatabase(DatabaseName: AnsiString; DPB: IDPB; RaiseExceptionOnConnectError: boolean=true): IAttachment;
94     function CreateDatabase(DatabaseName: AnsiString; DPB: IDPB; RaiseExceptionOnError: boolean=true): IAttachment; overload;
95     function CreateDatabase(sql: AnsiString; aSQLDialect: integer; RaiseExceptionOnError: boolean=true): IAttachment; overload;
96 tony 45 {Start Transaction against multiple databases}
97     function StartTransaction(Attachments: array of IAttachment;
98     TPB: array of byte; DefaultCompletion: TTransactionCompletion): ITransaction; overload;
99     function StartTransaction(Attachments: array of IAttachment;
100     TPB: ITPB; DefaultCompletion: TTransactionCompletion): ITransaction; overload;
101    
102     {Service Manager}
103     function AllocateSPB: ISPB;
104 tony 143 function GetServiceManager(ServerName: AnsiString; Protocol: TProtocol; SPB: ISPB): IServiceManager; overload;
105     function GetServiceManager(ServerName: AnsiString; Port: Ansistring; Protocol: TProtocol; SPB: ISPB): IServiceManager; overload;
106 tony 45
107     {Information}
108     function HasServiceAPI: boolean;
109     function HasRollbackRetaining: boolean;
110     function IsEmbeddedServer: boolean; override;
111 tony 56 function GetImplementationVersion: AnsiString;
112 tony 45
113     {Firebird 3 API}
114     function HasMasterIntf: boolean;
115     function GetIMaster: TObject;
116    
117     {Encode/Decode}
118 tony 56 function DecodeInteger(bufptr: PByte; len: short): integer; override;
119     procedure SQLEncodeDate(aDate: TDateTime; bufptr: PByte); override;
120     function SQLDecodeDate(bufptr: PByte): TDateTime; override;
121     procedure SQLEncodeTime(aTime: TDateTime; bufptr: PByte); override;
122     function SQLDecodeTime(bufptr: PByte): TDateTime; override;
123     procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); override;
124     function SQLDecodeDateTime(bufptr: PByte): TDateTime; override;
125 tony 45
126     {Firebird Interfaces}
127     property MasterIntf: Firebird.IMaster read FMaster;
128     property UtilIntf: Firebird.IUtil read FUtil;
129     property ProviderIntf: Firebird.IProvider read FProvider;
130     end;
131    
132     var Firebird30ClientAPI: TFB30ClientAPI;
133    
134     implementation
135    
136 tony 56 uses FBParamBlock, FB30Attachment, {$IFDEF FPC}dynlibs{$ELSE} windows{$ENDIF},
137     FBMessages, FB30Services, FB30Transaction;
138 tony 45
139     type
140     PISC_DATE = ^ISC_DATE;
141     PISC_TIME = ^ISC_TIME;
142    
143     { TFB30Status }
144    
145     procedure TFB30Status.Init;
146     begin
147     if assigned(FStatus) then
148     FStatus.Init;
149     end;
150    
151     function TFB30Status.InErrorState: boolean;
152     begin
153     with GetStatus do
154     Result := ((getState and STATE_ERRORS) <> 0);
155     end;
156    
157     function TFB30Status.GetStatus: Firebird.IStatus;
158     begin
159     if FStatus = nil then
160     with FOwner do
161     FStatus := (FOwner as TFB30ClientAPI).MasterIntf.GetStatus;
162     Result := FStatus;
163     end;
164    
165     function TFB30Status.StatusVector: PStatusVector;
166     begin
167     Result := PStatusVector(GetStatus.getErrors);
168     end;
169    
170     { TFB30ClientAPI }
171    
172     procedure TFB30ClientAPI.CheckPlugins;
173     var FBConf: Firebird.IFirebirdConf;
174 tony 56 Plugins: AnsiString;
175 tony 45 PluginsList: TStringList;
176     begin
177     FIsEmbeddedServer := false;
178     FBConf := FConfigManager.getFirebirdConf;
179     try
180     Plugins := FBConf.asString(FBConf.getKey('Providers'));
181     finally
182     FBConf.release;
183     end;
184     if Plugins = '' then Exit;
185    
186     PluginsList := TStringList.Create;
187     try
188     PluginsList.CommaText := Plugins;
189     FIsEmbeddedServer := PluginsList.IndexOf('Engine12') <> -1;
190     finally
191     PluginsList.Free;
192     end;
193     end;
194    
195     {$IFDEF UNIX}
196     function TFB30ClientAPI.GetFirebirdLibList: string;
197     begin
198     Result := 'libfbclient.so:libfbclient.so.2';
199     end;
200     {$ENDIF}
201    
202     procedure TFB30ClientAPI.LoadInterface;
203     var
204     fb_get_master_interface: Tfb_get_master_interface;
205     begin
206     inherited LoadInterface;
207     fb_get_master_interface := GetProcAddress(IBLibrary, 'fb_get_master_interface'); {do not localize}
208     if assigned(fb_get_master_interface) then
209     begin
210     FMaster := fb_get_master_interface;
211     FUtil := FMaster.getUtilInterface;
212     FProvider := FMaster.getDispatcher;
213     FConfigManager := FMaster.getConfigManager;
214     CheckPlugins;
215     end;
216     end;
217    
218     constructor TFB30ClientAPI.Create;
219     begin
220     inherited;
221     FStatus := TFB30Status.Create(self);
222     FStatusIntf := FStatus;
223     Firebird30ClientAPI := self;
224     end;
225    
226     destructor TFB30ClientAPI.Destroy;
227     begin
228     if assigned(FProvider) then
229     FProvider.release;
230     inherited Destroy;
231     end;
232    
233     function TFB30ClientAPI.StatusIntf: Firebird.IStatus;
234     begin
235     Result := FStatus.GetStatus;
236     Result.Init;
237     end;
238    
239     procedure TFB30ClientAPI.Check4DataBaseError;
240     begin
241     if FStatus.InErrorState then
242     IBDataBaseError;
243     end;
244    
245     function TFB30ClientAPI.InErrorState: boolean;
246     begin
247     Result := FStatus.InErrorState;
248     end;
249    
250     function TFB30ClientAPI.GetStatus: IStatus;
251     begin
252     Result := FStatusIntf;
253     end;
254    
255     function TFB30ClientAPI.AllocateDPB: IDPB;
256     begin
257     Result := TDPB.Create;
258     end;
259    
260     function TFB30ClientAPI.AllocateTPB: ITPB;
261     begin
262     Result := TTPB.Create;
263     end;
264    
265 tony 56 function TFB30ClientAPI.OpenDatabase(DatabaseName: AnsiString; DPB: IDPB;
266 tony 45 RaiseExceptionOnConnectError: boolean): IAttachment;
267     begin
268     Result := TFB30Attachment.Create(DatabaseName, DPB, RaiseExceptionOnConnectError);
269     if not Result.IsConnected then
270     Result := nil;
271     end;
272    
273 tony 56 function TFB30ClientAPI.CreateDatabase(DatabaseName: AnsiString; DPB: IDPB;
274 tony 45 RaiseExceptionOnError: boolean): IAttachment;
275     begin
276     Result := TFB30Attachment.CreateDatabase(DatabaseName,DPB, RaiseExceptionOnError);
277     if not Result.IsConnected then
278     Result := nil;
279     end;
280    
281 tony 56 function TFB30ClientAPI.CreateDatabase(sql: AnsiString; aSQLDialect: integer;
282 tony 47 RaiseExceptionOnError: boolean): IAttachment;
283     begin
284     Result := TFB30Attachment.CreateDatabase(sql,aSQLDialect, RaiseExceptionOnError);
285     if not Result.IsConnected then
286     Result := nil;
287     end;
288    
289 tony 45 function TFB30ClientAPI.StartTransaction(Attachments: array of IAttachment;
290     TPB: array of byte; DefaultCompletion: TTransactionCompletion): ITransaction;
291     begin
292     Result := TFB30Transaction.Create(Attachments,TPB,DefaultCompletion);
293     end;
294    
295     function TFB30ClientAPI.StartTransaction(Attachments: array of IAttachment;
296     TPB: ITPB; DefaultCompletion: TTransactionCompletion): ITransaction;
297     begin
298     Result := TFB30Transaction.Create(Attachments,TPB,DefaultCompletion);
299     end;
300    
301     function TFB30ClientAPI.AllocateSPB: ISPB;
302     begin
303     Result := TSPB.Create;
304     end;
305    
306 tony 56 function TFB30ClientAPI.GetServiceManager(ServerName: AnsiString;
307 tony 45 Protocol: TProtocol; SPB: ISPB): IServiceManager;
308     begin
309     Result := TFB30ServiceManager.Create(ServerName,Protocol,SPB);
310     end;
311    
312 tony 143 function TFB30ClientAPI.GetServiceManager(ServerName: AnsiString;
313     Port: Ansistring; Protocol: TProtocol; SPB: ISPB): IServiceManager;
314     begin
315     Result := TFB30ServiceManager.Create(ServerName,Protocol,SPB,Port);
316     end;
317    
318 tony 45 function TFB30ClientAPI.HasServiceAPI: boolean;
319     begin
320     Result := true;
321     end;
322    
323     function TFB30ClientAPI.HasMasterIntf: boolean;
324     begin
325     Result := MasterIntf <> nil;
326     end;
327    
328     function TFB30ClientAPI.GetIMaster: TObject;
329     begin
330     Result := FMaster;
331     end;
332    
333     function TFB30ClientAPI.HasRollbackRetaining: boolean;
334     begin
335     Result := true;
336     end;
337    
338     function TFB30ClientAPI.IsEmbeddedServer: boolean;
339     begin
340     Result := FIsEmbeddedServer;
341     end;
342    
343 tony 56 function TFB30ClientAPI.GetImplementationVersion: AnsiString;
344 tony 45 begin
345     Result := Format('3.%d',[UtilIntf.GetClientVersion]);
346     end;
347    
348 tony 56 function TFB30ClientAPI.DecodeInteger(bufptr: PByte; len: short): integer;
349     var P: PByte;
350 tony 45 begin
351     Result := 0;
352     P := Bufptr + len - 1;
353     while P >= bufptr do
354     begin
355 tony 56 Result := (Result shl 8 ) or P^;
356 tony 45 Dec(P);
357     end;
358     end;
359    
360 tony 56 procedure TFB30ClientAPI.SQLEncodeDate(aDate: TDateTime; bufptr: PByte);
361 tony 45 var
362     Yr, Mn, Dy: Word;
363     begin
364     DecodeDate(aDate, Yr, Mn, Dy);
365     PISC_Date(Bufptr)^ := UtilIntf.encodeDate(Yr, Mn, Dy);
366     end;
367    
368 tony 56 function TFB30ClientAPI.SQLDecodeDate(bufptr: PByte): TDateTime;
369 tony 45 var
370 tony 56 Yr, Mn, Dy: cardinal;
371 tony 45 begin
372     UtilIntf.decodeDate(PISC_DATE(bufptr)^,@Yr, @Mn, @Dy);
373     try
374     result := EncodeDate(Yr, Mn,Dy);
375     except
376     on E: EConvertError do begin
377     IBError(ibxeInvalidDataConversion, [nil]);
378     end;
379     end;
380     end;
381    
382 tony 56 procedure TFB30ClientAPI.SQLEncodeTime(aTime: TDateTime; bufptr: PByte);
383 tony 45 var
384     Hr, Mt, S, Ms: Word;
385     begin
386     DecodeTime(aTime, Hr, Mt, S, Ms);
387     PISC_TIME(bufptr)^ := UtilIntf.encodeTime(Hr, Mt, S, Ms*10);
388     end;
389    
390 tony 56 function TFB30ClientAPI.SQLDecodeTime(bufptr: PByte): TDateTime;
391 tony 45 var
392 tony 56 Hr, Mt, S, Ms: cardinal;
393 tony 45 begin
394     UtilIntf.decodeTime(PISC_TIME(bufptr)^,@Hr, @Mt, @S, @Ms);
395     try
396     Result := EncodeTime(Hr, Mt, S, Ms div 10);
397     except
398     on E: EConvertError do begin
399     IBError(ibxeInvalidDataConversion, [nil]);
400     end;
401     end;
402     end;
403    
404 tony 56 procedure TFB30ClientAPI.SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte);
405 tony 45 begin
406     SQLEncodeDate(aDateTime,bufPtr);
407     Inc(bufptr,sizeof(ISC_DATE));
408     SQLEncodeTime(aDateTime,bufPtr);
409     end;
410    
411 tony 56 function TFB30ClientAPI.SQLDecodeDateTime(bufptr: PByte): TDateTime;
412 tony 45 begin
413     Result := SQLDecodeDate(bufPtr);
414     Inc(bufptr,sizeof(ISC_DATE));
415 tony 56 Result := Result + SQLDecodeTime(bufPtr);
416 tony 45 end;
417    
418     end.
419    
420 tony 56