ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBClientAPI.pas
Revision: 386
Committed: Tue Jan 18 12:05:35 2022 UTC (2 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 21974 byte(s)
Log Message:
Silent exceptions bug fixed

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. Although predominantly
4     * a new development they include source code taken from IBX and may be
5     * considered a derived product. This software thus also includes the copyright
6     * notice and license conditions from IBX.
7     *
8     * Except for those parts dervied from IBX, contents of this file are subject
9     * to the Initial Developer's Public License Version 1.0 (the "License"); you
10     * may not use this file except in compliance with the License. You may obtain a
11     * copy of the License here:
12     *
13     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
14     *
15     * Software distributed under the License is distributed on an "AS
16     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17     * implied. See the License for the specific language governing rights
18     * and limitations under the License.
19     *
20     * The Initial Developer of the Original Code is Tony Whyman.
21     *
22     * The Original Code is (C) 2016 Tony Whyman, MWA Software
23     * (http://www.mwasoftware.co.uk).
24     *
25     * All Rights Reserved.
26     *
27     * Contributor(s): ______________________________________.
28     *
29     *)
30     {************************************************************************}
31     { }
32     { Borland Delphi Visual Component Library }
33     { InterBase Express core components }
34     { }
35     { Copyright (c) 1998-2000 Inprise Corporation }
36     { }
37     { InterBase Express is based in part on the product }
38     { Free IB Components, written by Gregory H. Deatz for }
39     { Hoagland, Longo, Moran, Dunst & Doukas Company. }
40     { Free IB Components is used under license. }
41     { }
42     { The contents of this file are subject to the InterBase }
43     { Public License Version 1.0 (the "License"); you may not }
44     { use this file except in compliance with the License. You }
45     { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
46     { Software distributed under the License is distributed on }
47     { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
48     { express or implied. See the License for the specific language }
49     { governing rights and limitations under the License. }
50     { The Original Code was created by InterBase Software Corporation }
51     { and its successors. }
52     { Portions created by Inprise Corporation are Copyright (C) Inprise }
53     { Corporation. All Rights Reserved. }
54     { Contributor(s): Jeff Overcash }
55     { }
56     { IBX For Lazarus (Firebird Express) }
57     { Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk }
58     { Portions created by MWA Software are copyright McCallum Whyman }
59     { Associates Ltd 2011 - 2015 }
60     { }
61     {************************************************************************}
62     unit FBClientAPI;
63 tony 56 {$IFDEF MSWINDOWS}
64     {$DEFINE WINDOWS}
65     {$ENDIF}
66 tony 45
67     {$IFDEF FPC}
68     {$mode delphi}
69     {$codepage UTF8}
70     {$interfaces COM}
71     {$ENDIF}
72    
73     interface
74    
75     uses
76 tony 56 Classes,
77     {$IFDEF WINDOWS}Windows, {$ENDIF}
78     {$IFDEF FPC} Dynlibs, {$ENDIF}
79 tony 315 IB, IBHeader, FBActivityMonitor, FBMessages, IBExternals, FmtBCD;
80 tony 45
81 tony 319 {For Linux see result of GetFirebirdLibListruntime/nongui/winipc.inc method}
82 tony 45 {$IFDEF DARWIN}
83     const
84     FIREBIRD_SO2 = 'libfbclient.dylib';
85     {$ENDIF}
86     {$IFDEF WINDOWS}
87     const
88     IBASE_DLL = 'gds32.dll';
89     FIREBIRD_CLIENT = 'fbclient.dll'; {do not localize}
90     FIREBIRD_EMBEDDED = 'fbembed.dll';
91     {$ENDIF}
92    
93 tony 308 const
94 tony 315 {fb_shutdown reasons}
95     fb_shutrsn_svc_stopped = -1;
96     fb_shutrsn_no_connection = -2;
97     fb_shutrsn_app_stopped = -3;
98     fb_shutrsn_signal = -5;
99     fb_shutrsn_services = -6;
100     fb_shutrsn_exit_called = -7;
101    
102     const
103     DefaultTimeZoneFile = '/etc/timezone';
104    
105     const
106 tony 308 IBLocalBufferLength = 512;
107     IBBigLocalBufferLength = IBLocalBufferLength * 2;
108     IBHugeLocalBufferLength = IBBigLocalBufferLength * 20;
109    
110 tony 45 type
111     TStatusVector = array[0..19] of NativeInt;
112     PStatusVector = ^TStatusVector;
113    
114     TFBClientAPI = class;
115    
116     { TFBStatus }
117    
118 tony 386 TFBStatus = class(TFBInterfacedObject, IStatus)
119 tony 45 private
120     FIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
121 tony 345 FPrefix: AnsiString;
122 tony 385 function SQLCodeSupported: boolean;
123 tony 45 protected
124     FOwner: TFBClientAPI;
125 tony 371 function GetIBMessage: Ansistring; virtual; abstract;
126     function GetSQLMessage: Ansistring;
127 tony 45 public
128 tony 345 constructor Create(aOwner: TFBClientAPI; prefix: AnsiString='');
129 tony 45 function StatusVector: PStatusVector; virtual; abstract;
130 tony 386 procedure Assign(src: TFBStatus); virtual;
131     function Clone: IStatus; virtual; abstract;
132 tony 45
133     {IStatus}
134 tony 345 function GetIBErrorCode: TStatusCode;
135     function Getsqlcode: TStatusCode;
136 tony 56 function GetMessage: AnsiString;
137 tony 45 function CheckStatusVector(ErrorCodes: array of TFBStatusCode): Boolean;
138     function GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
139     procedure SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
140     end;
141    
142 tony 263 { TFBLibrary }
143    
144     TFBLibrary = class(TFBInterfacedObject,IFirebirdLibrary)
145     private
146     class var FEnvSetupDone: boolean;
147     class var FLibraryList: array of IFirebirdLibrary;
148 tony 315 private
149 tony 263 FFirebirdAPI: IFirebirdAPI;
150     FRequestedLibName: string;
151     function LoadIBLibrary: boolean;
152     protected
153     FFBLibraryName: string;
154     FIBLibrary: TLibHandle;
155     procedure FreeFBLibrary;
156     function GetOverrideLibName: string;
157     class procedure SetupEnvironment;
158     protected
159     function GetFirebird3API: IFirebirdAPI; virtual; abstract;
160     function GetLegacyFirebirdAPI: IFirebirdAPI; virtual; abstract;
161     public
162     constructor Create(aLibPathName: string='');
163     destructor Destroy; override;
164     class function GetFBLibrary(aLibPathName: string): IFirebirdLibrary;
165     class procedure FreeLibraries;
166 tony 315 function SameLibrary(aLibName: string): boolean;
167 tony 263
168 tony 315 public
169 tony 263 {IFirebirdLibrary}
170     function GetHandle: TLibHandle;
171     function GetLibraryName: string;
172     function GetLibraryFilePath: string;
173     function GetFirebirdAPI: IFirebirdAPI;
174     property IBLibrary: TLibHandle read FIBLibrary;
175     end;
176    
177 tony 45 { TFBClientAPI }
178    
179     TFBClientAPI = class(TFBInterfacedObject)
180     private
181 tony 315 FLocalTimeZoneName: AnsiString; {Informal Time Zone Name from tzname e.g. GMT or BST}
182     FTZDataTimeZoneID: AnsiString; {TZData DB ID e.g. Europe/London}
183     FLocalTimeOffset: integer;
184     FIsDaylightSavingsTime: boolean;
185 tony 56 class var FIBCS: TRTLCriticalSection;
186 tony 315 function FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
187     procedure GetTZDataSettings;
188 tony 45 protected
189 tony 263 FFBLibrary: TFBLibrary;
190 tony 56 function GetProcAddr(ProcName: PAnsiChar): Pointer;
191 tony 315
192     protected type
193     Tfb_shutdown = function (timeout: uint;
194     const reason: int): int;
195     {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
196     protected
197     {FB Shutdown API}
198     fb_shutdown: Tfb_shutdown;
199    
200 tony 45 public
201     {Taken from legacy API}
202 tony 371 isc_sql_interprete: Tisc_sql_interprete;
203 tony 45 isc_sqlcode: Tisc_sqlcode;
204    
205 tony 263 constructor Create(aFBLibrary: TFBLibrary);
206 tony 45 procedure IBAlloc(var P; OldSize, NewSize: Integer);
207     procedure IBDataBaseError;
208 tony 263 function LoadInterface: boolean; virtual;
209 tony 315 procedure FBShutdown; virtual;
210 tony 263 function GetAPI: IFirebirdAPI; virtual; abstract;
211     {$IFDEF UNIX}
212     function GetFirebirdLibList: string; virtual; abstract;
213     {$ENDIF}
214 tony 315 function HasDecFloatSupport: boolean;
215     function HasInt128Support: boolean; virtual;
216     function HasLocalTZDB: boolean; virtual;
217     function HasExtendedTZSupport: boolean; virtual;
218     function HasTimeZoneSupport: boolean; virtual;
219 tony 45
220 tony 315 public
221     property LocalTimeZoneName: AnsiString read FLocalTimeZoneName;
222     property TZDataTimeZoneID: AnsiString read FTZDataTimeZoneID;
223     property LocalTimeOffset: integer read FLocalTimeOffset;
224     public
225 tony 45 {Encode/Decode}
226 tony 371 procedure EncodeInteger(aValue: int64; len: integer; buffer: PByte);
227 tony 345 function DecodeInteger(bufptr: PByte; len: short): int64;
228 tony 315 procedure SQLEncodeDate(aDate: TDateTime; bufptr: PByte); virtual; abstract;
229     function SQLDecodeDate(byfptr: PByte): TDateTime; virtual; abstract;
230     procedure SQLEncodeTime(aTime: TDateTime; bufptr: PByte); virtual; abstract;
231 tony 56 function SQLDecodeTime(bufptr: PByte): TDateTime; virtual; abstract;
232     procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); virtual; abstract;
233 tony 315 function SQLDecodeDateTime(bufptr: PByte): TDateTime; virtual; abstract;
234     function Int128ToStr(bufptr: PByte; scale: integer): AnsiString; virtual;
235     procedure StrToInt128(scale: integer; aValue: AnsiString; bufptr: PByte);
236     virtual;
237     procedure SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal; bufptr: PByte); virtual;
238     function SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD; virtual;
239 tony 45
240     {IFirebirdAPI}
241     function GetStatus: IStatus; virtual; abstract;
242     function IsLibraryLoaded: boolean;
243     function IsEmbeddedServer: boolean; virtual; abstract;
244 tony 263 function GetFBLibrary: IFirebirdLibrary;
245 tony 308 function GetImplementationVersion: AnsiString;
246     function GetClientMajor: integer; virtual; abstract;
247     function GetClientMinor: integer; virtual; abstract;
248 tony 363 end;
249 tony 45
250 tony 363 IJournallingHook = interface
251     ['{7d3e45e0-3628-416a-9e22-c20474825031}']
252     procedure TransactionStart(Tr: ITransaction);
253     function TransactionEnd(TransactionID: integer; Action: TTransactionAction): boolean;
254     procedure TransactionRetained(Tr: ITransaction; OldTransactionID: integer; Action: TTransactionAction);
255     procedure ExecQuery(Stmt: IStatement);
256     end;
257    
258 tony 45 implementation
259    
260 tony 263 uses IBUtils, Registry,
261 tony 315 {$IFDEF Unix} unix, initc, dl, {$ENDIF}
262 tony 56 {$IFDEF FPC}
263 tony 45 {$IFDEF WINDOWS }
264 tony 56 WinDirs,
265 tony 45 {$ENDIF}
266 tony 56 {$ELSE}
267     ShlObj,
268     {$ENDIF}
269 tony 45 SysUtils;
270    
271     {$IFDEF UNIX}
272 tony 56 {$I 'include/uloadlibrary.inc'}
273 tony 45 {$ELSE}
274 tony 56 {$I 'include/wloadlibrary.inc'}
275 tony 45 {$ENDIF}
276    
277 tony 263
278     { TFBLibrary }
279    
280     function TFBLibrary.GetOverrideLibName: string;
281     begin
282     Result := FFBLibraryName;
283     if (Result = '') and AllowUseOfFBLIB then
284     Result := GetEnvironmentVariable('FBLIB');
285     if Result = '' then
286 tony 45 begin
287 tony 263 if assigned(OnGetLibraryName) then
288     OnGetLibraryName(Result)
289 tony 45 end;
290 tony 263 end;
291 tony 45
292 tony 263 procedure TFBLibrary.FreeFBLibrary;
293     begin
294 tony 315 (FFirebirdAPI as TFBClientAPI).FBShutdown;
295 tony 263 if FIBLibrary <> NilHandle then
296     FreeLibrary(FIBLibrary);
297     FIBLibrary := NilHandle;
298 tony 315 FFBLibraryName := '';
299 tony 263 end;
300 tony 45
301 tony 263 function TFBLibrary.GetLibraryName: string;
302 tony 45 begin
303 tony 263 Result := ExtractFileName(FFBLibraryName);
304     end;
305    
306     function TFBLibrary.GetFirebirdAPI: IFirebirdAPI;
307     begin
308     Result := FFirebirdAPI;
309     end;
310    
311     constructor TFBLibrary.Create(aLibPathName: string);
312     begin
313 tony 45 inherited Create;
314 tony 263 SetupEnvironment;
315     FFBLibraryName := aLibPathName;
316     FIBLibrary := NilHandle;
317     FFirebirdAPI := GetFirebird3API;
318     FRequestedLibName := aLibPathName;
319     if aLibPathName <> '' then
320 tony 45 begin
321 tony 263 SetLength(FLibraryList,Length(FLibraryList)+1);
322     FLibraryList[Length(FLibraryList)-1] := self;
323 tony 45 end;
324 tony 263 if FFirebirdAPI <> nil then
325     begin
326     {First try Firebird 3}
327     if not LoadIBLibrary or not (FFirebirdAPI as TFBClientAPI).LoadInterface then
328     FFirebirdAPI := nil;
329     end;
330    
331     if FFirebirdAPI = nil then
332     begin
333     {now try Firebird 2.5. Under Unix we need to reload the library in case we
334     are to use the embedded library}
335     FFirebirdAPI := GetLegacyFirebirdAPI;
336     if FFirebirdAPI <> nil then
337     begin
338     {$IFDEF UNIX}
339     FreeFBLibrary;
340     {$ENDIF}
341     if not LoadIBLibrary or not (FFirebirdAPI as TFBClientAPI).LoadInterface then
342     FFirebirdAPI := nil;
343     end;
344     end;
345     {Note: FFirebirdAPI will be set to nil if the Firebird API fails to load}
346 tony 45 end;
347    
348 tony 263 destructor TFBLibrary.Destroy;
349 tony 45 begin
350 tony 315 FreeFBLibrary;
351 tony 263 FFirebirdAPI := nil;
352 tony 45 inherited Destroy;
353     end;
354    
355 tony 263 class function TFBLibrary.GetFBLibrary(aLibPathName: string): IFirebirdLibrary;
356     var i: integer;
357     begin
358     Result := nil;
359     if aLibPathName <> '' then
360     begin
361     for i := 0 to Length(FLibraryList) - 1 do
362 tony 315 begin
363     if (FLibraryList[i] as TFBLibrary).SameLibrary(aLibPathName) then
364 tony 263 begin
365     Result := FLibraryList[i];
366     Exit;
367     end;
368 tony 315 end;
369 tony 263 Result := Create(aLibPathName);
370     end;
371    
372     end;
373    
374     class procedure TFBLibrary.FreeLibraries;
375     var i: integer;
376     begin
377     for i := 0 to Length(FLibraryList) - 1 do
378     FLibraryList[i] := nil;
379     SetLength(FLibraryList,0);
380     end;
381    
382 tony 315 function TFBLibrary.SameLibrary(aLibName: string): boolean;
383     begin
384     Result := FRequestedLibName = aLibName;
385     end;
386    
387 tony 263 function TFBLibrary.GetHandle: TLibHandle;
388     begin
389     Result := FIBLibrary;
390     end;
391    
392     { TFBClientAPI }
393    
394     constructor TFBClientAPI.Create(aFBLibrary: TFBLibrary);
395     begin
396     inherited Create;
397     FFBLibrary := aFBLibrary;
398 tony 315 GetTZDataSettings;
399 tony 263 end;
400    
401 tony 45 procedure TFBClientAPI.IBAlloc(var P; OldSize, NewSize: Integer);
402     var
403     i: Integer;
404     begin
405     ReallocMem(Pointer(P), NewSize);
406 tony 56 for i := OldSize to NewSize - 1 do PAnsiChar(P)[i] := #0;
407 tony 45 end;
408    
409     procedure TFBClientAPI.IBDataBaseError;
410     begin
411     raise EIBInterBaseError.Create(GetStatus);
412     end;
413    
414 tony 371 procedure TFBClientAPI.EncodeInteger(aValue: int64; len: integer; buffer: PByte);
415 tony 45 begin
416     while len > 0 do
417     begin
418 tony 56 buffer^ := aValue and $FF;
419 tony 45 Inc(buffer);
420     Dec(len);
421     aValue := aValue shr 8;
422     end;
423     end;
424    
425 tony 371 (*
426     DecodeInteger is Translated from
427    
428     SINT64 API_ROUTINE isc_portable_integer(const UCHAR* ptr, SSHORT length)
429     if (!ptr || length <= 0 || length > 8)
430     return 0;
431    
432     SINT64 value = 0;
433     int shift = 0;
434    
435     while (--length > 0)
436     {
437     value += ((SINT64) *ptr++) << shift;
438     shift += 8;
439     }
440    
441     value += ((SINT64)(SCHAR) *ptr) << shift;
442    
443     return value;
444     *)
445    
446 tony 345 function TFBClientAPI.DecodeInteger(bufptr: PByte; len: short): int64;
447 tony 371 var shift: integer;
448 tony 345 begin
449 tony 371 Result := 0;
450     if (BufPtr = nil) or (len <= 0) or (len > 8) then
451     Exit;
452    
453     shift := 0;
454     dec(len);
455     while len > 0 do
456     begin
457     Result := Result + (int64(bufptr^) shl shift);
458     Inc(bufptr);
459     shift := shift + 8;
460     dec(len);
461     end;
462     Result := Result + (int64(bufptr^) shl shift);
463 tony 345 end;
464    
465 tony 315 function TFBClientAPI.Int128ToStr(bufptr: PByte; scale: integer): AnsiString;
466     begin
467     if not HasInt128Support then
468     IBError(ibxeNotSupported,[]);
469     end;
470    
471     procedure TFBClientAPI.StrToInt128(scale: integer; aValue: AnsiString; bufptr: PByte);
472     begin
473     if not HasInt128Support then
474     IBError(ibxeNotSupported,[]);
475     end;
476    
477     procedure TFBClientAPI.SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal;
478     bufptr: PByte);
479     begin
480     if not HasDecFloatSupport then
481     IBError(ibxeNotSupported,[]);
482     end;
483    
484     function TFBClientAPI.SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD;
485     begin
486     if not HasDecFloatSupport then
487     IBError(ibxeNotSupported,[]);
488     end;
489    
490 tony 45 function TFBClientAPI.IsLibraryLoaded: boolean;
491     begin
492 tony 263 Result := FFBLibrary.IBLibrary <> NilHandle;
493 tony 45 end;
494    
495 tony 263 function TFBClientAPI.GetFBLibrary: IFirebirdLibrary;
496     begin
497     Result := FFBLibrary;
498     end;
499    
500 tony 315 function TFBClientAPI.FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
501 tony 308 begin
502 tony 315 {aDate/aTime are in TTimestamp format but aTime is decimilliseconds}
503     aDate := aDate - DateDelta;
504     if aDate < 0 then
505     Result := trunc(aDate) - abs(frac(aTime / (MSecsPerDay*10)))
506     else
507     Result := trunc(aDate) + abs(frac(aTime / (MSecsPerDay*10)));
508 tony 308 end;
509    
510 tony 315 {$IFDEF UNIX}
511 tony 359
512 tony 315 procedure TFBClientAPI.GetTZDataSettings;
513     var S: TStringList;
514     begin
515     FLocalTimeOffset := GetLocalTimeOffset;
516 tony 359 {$if declared(Gettzname)}
517     FLocalTimeZoneName := Gettzname(tzdaylight);
518     {$else}
519     FLocalTimeZoneName := tzname[tzdaylight];
520     {$ifend}
521 tony 315 FIsDaylightSavingsTime := tzdaylight;
522     if FileExists(DefaultTimeZoneFile) then
523     begin
524     S := TStringList.Create;
525     try
526     S.LoadFromFile(DefaultTimeZoneFile);
527     if S.Count > 0 then
528     FTZDataTimeZoneID := S[0];
529     finally
530     S.Free;
531     end;
532     end;
533     end;
534     {$ENDIF}
535    
536     {$IFDEF WINDOWS}
537     procedure TFBClientAPI.GetTZDataSettings;
538     var TZInfo: TTimeZoneInformation;
539     begin
540     FIsDaylightSavingsTime := false;
541     {is there any way of working out the default TZData DB time zone ID under Windows?}
542     case GetTimeZoneInformation(TZInfo) of
543     TIME_ZONE_ID_UNKNOWN:
544     begin
545     FLocalTimeZoneName := '';
546     FLocalTimeOffset := 0;
547     end;
548     TIME_ZONE_ID_STANDARD:
549     begin
550     FLocalTimeZoneName := strpas(PWideChar(@TZInfo.StandardName));
551     FLocalTimeOffset := TZInfo.Bias;
552     end;
553     TIME_ZONE_ID_DAYLIGHT:
554     begin
555     FLocalTimeZoneName := strpas(PWideChar(@TZInfo.DaylightName));
556     FLocalTimeOffset := TZInfo.DayLightBias;
557     FIsDaylightSavingsTime := true;
558     end;
559     end;
560     end;
561     {$ENDIF}
562    
563 tony 56 function TFBClientAPI.GetProcAddr(ProcName: PAnsiChar): Pointer;
564 tony 45 begin
565 tony 347 Result := nil;
566     if assigned(FFBLibrary) and (FFBLibrary.IBLibrary <> NilHandle) then
567     Result := GetProcAddress(FFBLibrary.IBLibrary, ProcName);
568 tony 45 if not Assigned(Result) then
569     raise Exception.CreateFmt(SFirebirdAPIFuncNotFound,[ProcName]);
570     end;
571    
572 tony 315 function TFBClientAPI.HasDecFloatSupport: boolean;
573     begin
574     Result := GetClientMajor >= 4;
575     end;
576    
577     function TFBClientAPI.HasInt128Support: boolean;
578     begin
579     Result := false;
580     end;
581    
582     function TFBClientAPI.HasLocalTZDB: boolean;
583     begin
584     Result := false;
585     end;
586    
587     function TFBClientAPI.HasExtendedTZSupport: boolean;
588     begin
589     Result := false;
590     end;
591    
592     function TFBClientAPI.HasTimeZoneSupport: boolean;
593     begin
594     Result := false;
595     end;
596    
597     function TFBClientAPI.GetImplementationVersion: AnsiString;
598     begin
599     Result := Format('%d.%d',[GetClientMajor,GetClientMinor]);
600     end;
601    
602 tony 263 function TFBClientAPI.LoadInterface: boolean;
603 tony 45 begin
604     isc_sqlcode := GetProcAddr('isc_sqlcode'); {do not localize}
605     isc_sql_interprete := GetProcAddr('isc_sql_interprete'); {do not localize}
606 tony 315 fb_shutdown := GetProcAddr('fb_shutdown'); {do not localize}
607 tony 371 Result := true; {don't case if these fail to load}
608 tony 45 end;
609    
610 tony 315 procedure TFBClientAPI.FBShutdown;
611     begin
612     if assigned(fb_shutdown) then
613     fb_shutdown(0,fb_shutrsn_exit_called);
614     end;
615    
616 tony 45 { TFBStatus }
617    
618 tony 385 function TFBStatus.SQLCodeSupported: boolean;
619     begin
620     Result:= (FOwner <> nil) and assigned(FOwner.isc_sqlcode) and assigned(FOwner.isc_sql_interprete);
621     end;
622    
623 tony 371 function TFBStatus.GetSQLMessage: Ansistring;
624     var local_buffer: array[0..IBHugeLocalBufferLength - 1] of AnsiChar;
625     begin
626     Result := '';
627     if (FOwner <> nil) and assigned(FOwner.isc_sql_interprete) then
628     begin
629     FOwner.isc_sql_interprete(Getsqlcode, local_buffer, sizeof(local_buffer));
630     Result := strpas(local_buffer);
631     end;
632     end;
633    
634 tony 345 constructor TFBStatus.Create(aOwner: TFBClientAPI; prefix: AnsiString);
635 tony 45 begin
636     inherited Create;
637     FOwner := aOwner;
638 tony 345 FPrefix := prefix;
639 tony 385 FIBDataBaseErrorMessages := [ShowIBMessage];
640 tony 45 end;
641    
642 tony 386 procedure TFBStatus.Assign(src: TFBStatus);
643     begin
644     FOwner := src.FOwner;
645     FPrefix := src.FPrefix;
646     SetIBDataBaseErrorMessages(src.GetIBDataBaseErrorMessages);
647     end;
648    
649 tony 345 function TFBStatus.GetIBErrorCode: TStatusCode;
650 tony 45 begin
651     Result := StatusVector^[1];
652     end;
653    
654 tony 345 function TFBStatus.Getsqlcode: TStatusCode;
655 tony 45 begin
656 tony 371 if (FOwner <> nil) and assigned(FOwner.isc_sqlcode) then
657     Result := FOwner.isc_sqlcode(PISC_STATUS(StatusVector))
658     else
659     Result := -999; {generic SQL Code}
660 tony 45 end;
661    
662 tony 56 function TFBStatus.GetMessage: AnsiString;
663 tony 371 var IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
664 tony 45 begin
665 tony 345 Result := FPrefix;
666 tony 45 IBDataBaseErrorMessages := FIBDataBaseErrorMessages;
667 tony 385 if SQLCodeSupported then
668     begin
669     if (ShowSQLCode in IBDataBaseErrorMessages) then
670     Result := Result + 'SQLCODE: ' + IntToStr(Getsqlcode); {do not localize}
671 tony 45
672 tony 385 if (ShowSQLMessage in IBDataBaseErrorMessages) then
673     begin
674     if ShowSQLCode in IBDataBaseErrorMessages then
675     Result := Result + LineEnding;
676     Result := Result + GetSQLMessage;
677     end;
678 tony 45 end;
679    
680     if (ShowIBMessage in IBDataBaseErrorMessages) then
681     begin
682 tony 385 if Result <> FPrefix then
683 tony 308 Result := Result + LineEnding;
684 tony 385 Result := Result + 'Engine Code: ' + IntToStr(GetIBErrorCode) + LineEnding + GetIBMessage;
685 tony 45 end;
686     if (Result <> '') and (Result[Length(Result)] = '.') then
687     Delete(Result, Length(Result), 1);
688     end;
689    
690     function TFBStatus.CheckStatusVector(ErrorCodes: array of TFBStatusCode
691     ): Boolean;
692     var
693     p: PISC_STATUS;
694     i: Integer;
695     procedure NextP(i: Integer);
696     begin
697 tony 56 p := PISC_STATUS(PAnsiChar(p) + (i * SizeOf(ISC_STATUS)));
698 tony 45 end;
699     begin
700     p := PISC_STATUS(StatusVector);
701     result := False;
702     while (p^ <> 0) and (not result) do
703     case p^ of
704     3: NextP(3);
705     1, 4:
706     begin
707     NextP(1);
708     i := 0;
709     while (i <= High(ErrorCodes)) and (not result) do
710     begin
711     result := p^ = ErrorCodes[i];
712     Inc(i);
713     end;
714     NextP(1);
715     end;
716     else
717     NextP(2);
718     end;
719     end;
720    
721     function TFBStatus.GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
722     begin
723 tony 56 EnterCriticalSection(TFBClientAPI.FIBCS);
724 tony 45 try
725     result := FIBDataBaseErrorMessages;
726     finally
727 tony 56 LeaveCriticalSection(TFBClientAPI.FIBCS);
728 tony 45 end;
729     end;
730    
731     procedure TFBStatus.SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
732     begin
733 tony 56 EnterCriticalSection(TFBClientAPI.FIBCS);
734 tony 45 try
735     FIBDataBaseErrorMessages := Value;
736     finally
737 tony 56 LeaveCriticalSection(TFBClientAPI.FIBCS);
738 tony 45 end;
739     end;
740 tony 60
741 tony 45 initialization
742 tony 263 TFBLibrary.FEnvSetupDone := false;
743 tony 56 {$IFNDEF FPC}
744     InitializeCriticalSection(TFBClientAPI.FIBCS);
745     {$ELSE}
746     InitCriticalSection(TFBClientAPI.FIBCS);
747     {$ENDIF}
748 tony 45
749     finalization
750 tony 263 TFBLibrary.FreeLibraries;
751 tony 56 {$IFNDEF FPC}
752     DeleteCriticalSection(TFBClientAPI.FIBCS);
753     {$ELSE}
754     DoneCriticalSection(TFBClientAPI.FIBCS);
755     {$ENDIF}
756 tony 45 end.
757    

Properties

Name Value
svn:eol-style native