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

# 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; overload;
105 function GetServiceManager(ServerName: AnsiString; Port: Ansistring; Protocol: TProtocol; SPB: ISPB): IServiceManager; overload;
106
107 {Information}
108 function HasServiceAPI: boolean;
109 function HasRollbackRetaining: boolean;
110 function IsEmbeddedServer: boolean; override;
111 function GetImplementationVersion: AnsiString;
112
113 {Firebird 3 API}
114 function HasMasterIntf: boolean;
115 function GetIMaster: TObject;
116
117 {Encode/Decode}
118 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
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 uses FBParamBlock, FB30Attachment, {$IFDEF FPC}dynlibs{$ELSE} windows{$ENDIF},
137 FBMessages, FB30Services, FB30Transaction;
138
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 Plugins: AnsiString;
175 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 function TFB30ClientAPI.OpenDatabase(DatabaseName: AnsiString; DPB: IDPB;
266 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 function TFB30ClientAPI.CreateDatabase(DatabaseName: AnsiString; DPB: IDPB;
274 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 function TFB30ClientAPI.CreateDatabase(sql: AnsiString; aSQLDialect: integer;
282 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 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 function TFB30ClientAPI.GetServiceManager(ServerName: AnsiString;
307 Protocol: TProtocol; SPB: ISPB): IServiceManager;
308 begin
309 Result := TFB30ServiceManager.Create(ServerName,Protocol,SPB);
310 end;
311
312 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 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 function TFB30ClientAPI.GetImplementationVersion: AnsiString;
344 begin
345 Result := Format('3.%d',[UtilIntf.GetClientVersion]);
346 end;
347
348 function TFB30ClientAPI.DecodeInteger(bufptr: PByte; len: short): integer;
349 var P: PByte;
350 begin
351 Result := 0;
352 P := Bufptr + len - 1;
353 while P >= bufptr do
354 begin
355 Result := (Result shl 8 ) or P^;
356 Dec(P);
357 end;
358 end;
359
360 procedure TFB30ClientAPI.SQLEncodeDate(aDate: TDateTime; bufptr: PByte);
361 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 function TFB30ClientAPI.SQLDecodeDate(bufptr: PByte): TDateTime;
369 var
370 Yr, Mn, Dy: cardinal;
371 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 procedure TFB30ClientAPI.SQLEncodeTime(aTime: TDateTime; bufptr: PByte);
383 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 function TFB30ClientAPI.SQLDecodeTime(bufptr: PByte): TDateTime;
391 var
392 Hr, Mt, S, Ms: cardinal;
393 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 procedure TFB30ClientAPI.SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte);
405 begin
406 SQLEncodeDate(aDateTime,bufPtr);
407 Inc(bufptr,sizeof(ISC_DATE));
408 SQLEncodeTime(aDateTime,bufPtr);
409 end;
410
411 function TFB30ClientAPI.SQLDecodeDateTime(bufptr: PByte): TDateTime;
412 begin
413 Result := SQLDecodeDate(bufPtr);
414 Inc(bufptr,sizeof(ISC_DATE));
415 Result := Result + SQLDecodeTime(bufPtr);
416 end;
417
418 end.
419
420