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: 56
Committed: Mon Mar 6 10:20:02 2017 UTC (7 years, 1 month ago) by tony
Content type: text/x-pascal
File size: 11034 byte(s)
Log Message:
Committing updates for Trunk

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