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, 8 months ago) by tony
Content type: text/x-pascal
File size: 11034 byte(s)
Log Message:
Committing updates for Trunk

File Contents

# Content
1 (*
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 {$IFDEF MSWINDOWS}
29 {$DEFINE WINDOWS}
30 {$ENDIF}
31
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 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 {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 function GetServiceManager(ServerName: AnsiString; Protocol: TProtocol; SPB: ISPB): IServiceManager;
105
106 {Information}
107 function HasServiceAPI: boolean;
108 function HasRollbackRetaining: boolean;
109 function IsEmbeddedServer: boolean; override;
110 function GetImplementationVersion: AnsiString;
111
112 {Firebird 3 API}
113 function HasMasterIntf: boolean;
114 function GetIMaster: TObject;
115
116 {Encode/Decode}
117 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
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 uses FBParamBlock, FB30Attachment, {$IFDEF FPC}dynlibs{$ELSE} windows{$ENDIF},
136 FBMessages, FB30Services, FB30Transaction;
137
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 Plugins: AnsiString;
174 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 function TFB30ClientAPI.OpenDatabase(DatabaseName: AnsiString; DPB: IDPB;
265 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 function TFB30ClientAPI.CreateDatabase(DatabaseName: AnsiString; DPB: IDPB;
273 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 function TFB30ClientAPI.CreateDatabase(sql: AnsiString; aSQLDialect: integer;
281 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 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 function TFB30ClientAPI.GetServiceManager(ServerName: AnsiString;
306 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 function TFB30ClientAPI.GetImplementationVersion: AnsiString;
337 begin
338 Result := Format('3.%d',[UtilIntf.GetClientVersion]);
339 end;
340
341 function TFB30ClientAPI.DecodeInteger(bufptr: PByte; len: short): integer;
342 var P: PByte;
343 begin
344 Result := 0;
345 P := Bufptr + len - 1;
346 while P >= bufptr do
347 begin
348 Result := (Result shl 8 ) or P^;
349 Dec(P);
350 end;
351 end;
352
353 procedure TFB30ClientAPI.SQLEncodeDate(aDate: TDateTime; bufptr: PByte);
354 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 function TFB30ClientAPI.SQLDecodeDate(bufptr: PByte): TDateTime;
362 var
363 Yr, Mn, Dy: cardinal;
364 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 procedure TFB30ClientAPI.SQLEncodeTime(aTime: TDateTime; bufptr: PByte);
376 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 function TFB30ClientAPI.SQLDecodeTime(bufptr: PByte): TDateTime;
384 var
385 Hr, Mt, S, Ms: cardinal;
386 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 procedure TFB30ClientAPI.SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte);
398 begin
399 SQLEncodeDate(aDateTime,bufPtr);
400 Inc(bufptr,sizeof(ISC_DATE));
401 SQLEncodeTime(aDateTime,bufPtr);
402 end;
403
404 function TFB30ClientAPI.SQLDecodeDateTime(bufptr: PByte): TDateTime;
405 begin
406 Result := SQLDecodeDate(bufPtr);
407 Inc(bufptr,sizeof(ISC_DATE));
408 Result := Result + SQLDecodeTime(bufPtr);
409 end;
410
411 end.
412
413