ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBClientAPI.pas
Revision: 385
Committed: Mon Jan 17 15:56:35 2022 UTC (2 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 21702 byte(s)
Log Message:
Return nil result for UDR procedures when an exception occurs

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     TFBStatus = class(TFBInterfacedObject)
119     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    
131     {IStatus}
132 tony 345 function GetIBErrorCode: TStatusCode;
133     function Getsqlcode: TStatusCode;
134 tony 56 function GetMessage: AnsiString;
135 tony 45 function CheckStatusVector(ErrorCodes: array of TFBStatusCode): Boolean;
136     function GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
137     procedure SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
138     end;
139    
140 tony 263 { TFBLibrary }
141    
142     TFBLibrary = class(TFBInterfacedObject,IFirebirdLibrary)
143     private
144     class var FEnvSetupDone: boolean;
145     class var FLibraryList: array of IFirebirdLibrary;
146 tony 315 private
147 tony 263 FFirebirdAPI: IFirebirdAPI;
148     FRequestedLibName: string;
149     function LoadIBLibrary: boolean;
150     protected
151     FFBLibraryName: string;
152     FIBLibrary: TLibHandle;
153     procedure FreeFBLibrary;
154     function GetOverrideLibName: string;
155     class procedure SetupEnvironment;
156     protected
157     function GetFirebird3API: IFirebirdAPI; virtual; abstract;
158     function GetLegacyFirebirdAPI: IFirebirdAPI; virtual; abstract;
159     public
160     constructor Create(aLibPathName: string='');
161     destructor Destroy; override;
162     class function GetFBLibrary(aLibPathName: string): IFirebirdLibrary;
163     class procedure FreeLibraries;
164 tony 315 function SameLibrary(aLibName: string): boolean;
165 tony 263
166 tony 315 public
167 tony 263 {IFirebirdLibrary}
168     function GetHandle: TLibHandle;
169     function GetLibraryName: string;
170     function GetLibraryFilePath: string;
171     function GetFirebirdAPI: IFirebirdAPI;
172     property IBLibrary: TLibHandle read FIBLibrary;
173     end;
174    
175 tony 45 { TFBClientAPI }
176    
177     TFBClientAPI = class(TFBInterfacedObject)
178     private
179 tony 315 FLocalTimeZoneName: AnsiString; {Informal Time Zone Name from tzname e.g. GMT or BST}
180     FTZDataTimeZoneID: AnsiString; {TZData DB ID e.g. Europe/London}
181     FLocalTimeOffset: integer;
182     FIsDaylightSavingsTime: boolean;
183 tony 56 class var FIBCS: TRTLCriticalSection;
184 tony 315 function FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
185     procedure GetTZDataSettings;
186 tony 45 protected
187 tony 263 FFBLibrary: TFBLibrary;
188 tony 56 function GetProcAddr(ProcName: PAnsiChar): Pointer;
189 tony 315
190     protected type
191     Tfb_shutdown = function (timeout: uint;
192     const reason: int): int;
193     {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
194     protected
195     {FB Shutdown API}
196     fb_shutdown: Tfb_shutdown;
197    
198 tony 45 public
199     {Taken from legacy API}
200 tony 371 isc_sql_interprete: Tisc_sql_interprete;
201 tony 45 isc_sqlcode: Tisc_sqlcode;
202    
203 tony 263 constructor Create(aFBLibrary: TFBLibrary);
204 tony 45 procedure IBAlloc(var P; OldSize, NewSize: Integer);
205     procedure IBDataBaseError;
206 tony 263 function LoadInterface: boolean; virtual;
207 tony 315 procedure FBShutdown; virtual;
208 tony 263 function GetAPI: IFirebirdAPI; virtual; abstract;
209     {$IFDEF UNIX}
210     function GetFirebirdLibList: string; virtual; abstract;
211     {$ENDIF}
212 tony 315 function HasDecFloatSupport: boolean;
213     function HasInt128Support: boolean; virtual;
214     function HasLocalTZDB: boolean; virtual;
215     function HasExtendedTZSupport: boolean; virtual;
216     function HasTimeZoneSupport: boolean; virtual;
217 tony 45
218 tony 315 public
219     property LocalTimeZoneName: AnsiString read FLocalTimeZoneName;
220     property TZDataTimeZoneID: AnsiString read FTZDataTimeZoneID;
221     property LocalTimeOffset: integer read FLocalTimeOffset;
222     public
223 tony 45 {Encode/Decode}
224 tony 371 procedure EncodeInteger(aValue: int64; len: integer; buffer: PByte);
225 tony 345 function DecodeInteger(bufptr: PByte; len: short): int64;
226 tony 315 procedure SQLEncodeDate(aDate: TDateTime; bufptr: PByte); virtual; abstract;
227     function SQLDecodeDate(byfptr: PByte): TDateTime; virtual; abstract;
228     procedure SQLEncodeTime(aTime: TDateTime; bufptr: PByte); virtual; abstract;
229 tony 56 function SQLDecodeTime(bufptr: PByte): TDateTime; virtual; abstract;
230     procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); virtual; abstract;
231 tony 315 function SQLDecodeDateTime(bufptr: PByte): TDateTime; virtual; abstract;
232     function Int128ToStr(bufptr: PByte; scale: integer): AnsiString; virtual;
233     procedure StrToInt128(scale: integer; aValue: AnsiString; bufptr: PByte);
234     virtual;
235     procedure SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal; bufptr: PByte); virtual;
236     function SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD; virtual;
237 tony 45
238     {IFirebirdAPI}
239     function GetStatus: IStatus; virtual; abstract;
240     function IsLibraryLoaded: boolean;
241     function IsEmbeddedServer: boolean; virtual; abstract;
242 tony 263 function GetFBLibrary: IFirebirdLibrary;
243 tony 308 function GetImplementationVersion: AnsiString;
244     function GetClientMajor: integer; virtual; abstract;
245     function GetClientMinor: integer; virtual; abstract;
246 tony 363 end;
247 tony 45
248 tony 363 IJournallingHook = interface
249     ['{7d3e45e0-3628-416a-9e22-c20474825031}']
250     procedure TransactionStart(Tr: ITransaction);
251     function TransactionEnd(TransactionID: integer; Action: TTransactionAction): boolean;
252     procedure TransactionRetained(Tr: ITransaction; OldTransactionID: integer; Action: TTransactionAction);
253     procedure ExecQuery(Stmt: IStatement);
254     end;
255    
256 tony 45 implementation
257    
258 tony 263 uses IBUtils, Registry,
259 tony 315 {$IFDEF Unix} unix, initc, dl, {$ENDIF}
260 tony 56 {$IFDEF FPC}
261 tony 45 {$IFDEF WINDOWS }
262 tony 56 WinDirs,
263 tony 45 {$ENDIF}
264 tony 56 {$ELSE}
265     ShlObj,
266     {$ENDIF}
267 tony 45 SysUtils;
268    
269     {$IFDEF UNIX}
270 tony 56 {$I 'include/uloadlibrary.inc'}
271 tony 45 {$ELSE}
272 tony 56 {$I 'include/wloadlibrary.inc'}
273 tony 45 {$ENDIF}
274    
275 tony 263
276     { TFBLibrary }
277    
278     function TFBLibrary.GetOverrideLibName: string;
279     begin
280     Result := FFBLibraryName;
281     if (Result = '') and AllowUseOfFBLIB then
282     Result := GetEnvironmentVariable('FBLIB');
283     if Result = '' then
284 tony 45 begin
285 tony 263 if assigned(OnGetLibraryName) then
286     OnGetLibraryName(Result)
287 tony 45 end;
288 tony 263 end;
289 tony 45
290 tony 263 procedure TFBLibrary.FreeFBLibrary;
291     begin
292 tony 315 (FFirebirdAPI as TFBClientAPI).FBShutdown;
293 tony 263 if FIBLibrary <> NilHandle then
294     FreeLibrary(FIBLibrary);
295     FIBLibrary := NilHandle;
296 tony 315 FFBLibraryName := '';
297 tony 263 end;
298 tony 45
299 tony 263 function TFBLibrary.GetLibraryName: string;
300 tony 45 begin
301 tony 263 Result := ExtractFileName(FFBLibraryName);
302     end;
303    
304     function TFBLibrary.GetFirebirdAPI: IFirebirdAPI;
305     begin
306     Result := FFirebirdAPI;
307     end;
308    
309     constructor TFBLibrary.Create(aLibPathName: string);
310     begin
311 tony 45 inherited Create;
312 tony 263 SetupEnvironment;
313     FFBLibraryName := aLibPathName;
314     FIBLibrary := NilHandle;
315     FFirebirdAPI := GetFirebird3API;
316     FRequestedLibName := aLibPathName;
317     if aLibPathName <> '' then
318 tony 45 begin
319 tony 263 SetLength(FLibraryList,Length(FLibraryList)+1);
320     FLibraryList[Length(FLibraryList)-1] := self;
321 tony 45 end;
322 tony 263 if FFirebirdAPI <> nil then
323     begin
324     {First try Firebird 3}
325     if not LoadIBLibrary or not (FFirebirdAPI as TFBClientAPI).LoadInterface then
326     FFirebirdAPI := nil;
327     end;
328    
329     if FFirebirdAPI = nil then
330     begin
331     {now try Firebird 2.5. Under Unix we need to reload the library in case we
332     are to use the embedded library}
333     FFirebirdAPI := GetLegacyFirebirdAPI;
334     if FFirebirdAPI <> nil then
335     begin
336     {$IFDEF UNIX}
337     FreeFBLibrary;
338     {$ENDIF}
339     if not LoadIBLibrary or not (FFirebirdAPI as TFBClientAPI).LoadInterface then
340     FFirebirdAPI := nil;
341     end;
342     end;
343     {Note: FFirebirdAPI will be set to nil if the Firebird API fails to load}
344 tony 45 end;
345    
346 tony 263 destructor TFBLibrary.Destroy;
347 tony 45 begin
348 tony 315 FreeFBLibrary;
349 tony 263 FFirebirdAPI := nil;
350 tony 45 inherited Destroy;
351     end;
352    
353 tony 263 class function TFBLibrary.GetFBLibrary(aLibPathName: string): IFirebirdLibrary;
354     var i: integer;
355     begin
356     Result := nil;
357     if aLibPathName <> '' then
358     begin
359     for i := 0 to Length(FLibraryList) - 1 do
360 tony 315 begin
361     if (FLibraryList[i] as TFBLibrary).SameLibrary(aLibPathName) then
362 tony 263 begin
363     Result := FLibraryList[i];
364     Exit;
365     end;
366 tony 315 end;
367 tony 263 Result := Create(aLibPathName);
368     end;
369    
370     end;
371    
372     class procedure TFBLibrary.FreeLibraries;
373     var i: integer;
374     begin
375     for i := 0 to Length(FLibraryList) - 1 do
376     FLibraryList[i] := nil;
377     SetLength(FLibraryList,0);
378     end;
379    
380 tony 315 function TFBLibrary.SameLibrary(aLibName: string): boolean;
381     begin
382     Result := FRequestedLibName = aLibName;
383     end;
384    
385 tony 263 function TFBLibrary.GetHandle: TLibHandle;
386     begin
387     Result := FIBLibrary;
388     end;
389    
390     { TFBClientAPI }
391    
392     constructor TFBClientAPI.Create(aFBLibrary: TFBLibrary);
393     begin
394     inherited Create;
395     FFBLibrary := aFBLibrary;
396 tony 315 GetTZDataSettings;
397 tony 263 end;
398    
399 tony 45 procedure TFBClientAPI.IBAlloc(var P; OldSize, NewSize: Integer);
400     var
401     i: Integer;
402     begin
403     ReallocMem(Pointer(P), NewSize);
404 tony 56 for i := OldSize to NewSize - 1 do PAnsiChar(P)[i] := #0;
405 tony 45 end;
406    
407     procedure TFBClientAPI.IBDataBaseError;
408     begin
409     raise EIBInterBaseError.Create(GetStatus);
410     end;
411    
412 tony 371 procedure TFBClientAPI.EncodeInteger(aValue: int64; len: integer; buffer: PByte);
413 tony 45 begin
414     while len > 0 do
415     begin
416 tony 56 buffer^ := aValue and $FF;
417 tony 45 Inc(buffer);
418     Dec(len);
419     aValue := aValue shr 8;
420     end;
421     end;
422    
423 tony 371 (*
424     DecodeInteger is Translated from
425    
426     SINT64 API_ROUTINE isc_portable_integer(const UCHAR* ptr, SSHORT length)
427     if (!ptr || length <= 0 || length > 8)
428     return 0;
429    
430     SINT64 value = 0;
431     int shift = 0;
432    
433     while (--length > 0)
434     {
435     value += ((SINT64) *ptr++) << shift;
436     shift += 8;
437     }
438    
439     value += ((SINT64)(SCHAR) *ptr) << shift;
440    
441     return value;
442     *)
443    
444 tony 345 function TFBClientAPI.DecodeInteger(bufptr: PByte; len: short): int64;
445 tony 371 var shift: integer;
446 tony 345 begin
447 tony 371 Result := 0;
448     if (BufPtr = nil) or (len <= 0) or (len > 8) then
449     Exit;
450    
451     shift := 0;
452     dec(len);
453     while len > 0 do
454     begin
455     Result := Result + (int64(bufptr^) shl shift);
456     Inc(bufptr);
457     shift := shift + 8;
458     dec(len);
459     end;
460     Result := Result + (int64(bufptr^) shl shift);
461 tony 345 end;
462    
463 tony 315 function TFBClientAPI.Int128ToStr(bufptr: PByte; scale: integer): AnsiString;
464     begin
465     if not HasInt128Support then
466     IBError(ibxeNotSupported,[]);
467     end;
468    
469     procedure TFBClientAPI.StrToInt128(scale: integer; aValue: AnsiString; bufptr: PByte);
470     begin
471     if not HasInt128Support then
472     IBError(ibxeNotSupported,[]);
473     end;
474    
475     procedure TFBClientAPI.SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal;
476     bufptr: PByte);
477     begin
478     if not HasDecFloatSupport then
479     IBError(ibxeNotSupported,[]);
480     end;
481    
482     function TFBClientAPI.SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD;
483     begin
484     if not HasDecFloatSupport then
485     IBError(ibxeNotSupported,[]);
486     end;
487    
488 tony 45 function TFBClientAPI.IsLibraryLoaded: boolean;
489     begin
490 tony 263 Result := FFBLibrary.IBLibrary <> NilHandle;
491 tony 45 end;
492    
493 tony 263 function TFBClientAPI.GetFBLibrary: IFirebirdLibrary;
494     begin
495     Result := FFBLibrary;
496     end;
497    
498 tony 315 function TFBClientAPI.FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
499 tony 308 begin
500 tony 315 {aDate/aTime are in TTimestamp format but aTime is decimilliseconds}
501     aDate := aDate - DateDelta;
502     if aDate < 0 then
503     Result := trunc(aDate) - abs(frac(aTime / (MSecsPerDay*10)))
504     else
505     Result := trunc(aDate) + abs(frac(aTime / (MSecsPerDay*10)));
506 tony 308 end;
507    
508 tony 315 {$IFDEF UNIX}
509 tony 359
510 tony 315 procedure TFBClientAPI.GetTZDataSettings;
511     var S: TStringList;
512     begin
513     FLocalTimeOffset := GetLocalTimeOffset;
514 tony 359 {$if declared(Gettzname)}
515     FLocalTimeZoneName := Gettzname(tzdaylight);
516     {$else}
517     FLocalTimeZoneName := tzname[tzdaylight];
518     {$ifend}
519 tony 315 FIsDaylightSavingsTime := tzdaylight;
520     if FileExists(DefaultTimeZoneFile) then
521     begin
522     S := TStringList.Create;
523     try
524     S.LoadFromFile(DefaultTimeZoneFile);
525     if S.Count > 0 then
526     FTZDataTimeZoneID := S[0];
527     finally
528     S.Free;
529     end;
530     end;
531     end;
532     {$ENDIF}
533    
534     {$IFDEF WINDOWS}
535     procedure TFBClientAPI.GetTZDataSettings;
536     var TZInfo: TTimeZoneInformation;
537     begin
538     FIsDaylightSavingsTime := false;
539     {is there any way of working out the default TZData DB time zone ID under Windows?}
540     case GetTimeZoneInformation(TZInfo) of
541     TIME_ZONE_ID_UNKNOWN:
542     begin
543     FLocalTimeZoneName := '';
544     FLocalTimeOffset := 0;
545     end;
546     TIME_ZONE_ID_STANDARD:
547     begin
548     FLocalTimeZoneName := strpas(PWideChar(@TZInfo.StandardName));
549     FLocalTimeOffset := TZInfo.Bias;
550     end;
551     TIME_ZONE_ID_DAYLIGHT:
552     begin
553     FLocalTimeZoneName := strpas(PWideChar(@TZInfo.DaylightName));
554     FLocalTimeOffset := TZInfo.DayLightBias;
555     FIsDaylightSavingsTime := true;
556     end;
557     end;
558     end;
559     {$ENDIF}
560    
561 tony 56 function TFBClientAPI.GetProcAddr(ProcName: PAnsiChar): Pointer;
562 tony 45 begin
563 tony 347 Result := nil;
564     if assigned(FFBLibrary) and (FFBLibrary.IBLibrary <> NilHandle) then
565     Result := GetProcAddress(FFBLibrary.IBLibrary, ProcName);
566 tony 45 if not Assigned(Result) then
567     raise Exception.CreateFmt(SFirebirdAPIFuncNotFound,[ProcName]);
568     end;
569    
570 tony 315 function TFBClientAPI.HasDecFloatSupport: boolean;
571     begin
572     Result := GetClientMajor >= 4;
573     end;
574    
575     function TFBClientAPI.HasInt128Support: boolean;
576     begin
577     Result := false;
578     end;
579    
580     function TFBClientAPI.HasLocalTZDB: boolean;
581     begin
582     Result := false;
583     end;
584    
585     function TFBClientAPI.HasExtendedTZSupport: boolean;
586     begin
587     Result := false;
588     end;
589    
590     function TFBClientAPI.HasTimeZoneSupport: boolean;
591     begin
592     Result := false;
593     end;
594    
595     function TFBClientAPI.GetImplementationVersion: AnsiString;
596     begin
597     Result := Format('%d.%d',[GetClientMajor,GetClientMinor]);
598     end;
599    
600 tony 263 function TFBClientAPI.LoadInterface: boolean;
601 tony 45 begin
602     isc_sqlcode := GetProcAddr('isc_sqlcode'); {do not localize}
603     isc_sql_interprete := GetProcAddr('isc_sql_interprete'); {do not localize}
604 tony 315 fb_shutdown := GetProcAddr('fb_shutdown'); {do not localize}
605 tony 371 Result := true; {don't case if these fail to load}
606 tony 45 end;
607    
608 tony 315 procedure TFBClientAPI.FBShutdown;
609     begin
610     if assigned(fb_shutdown) then
611     fb_shutdown(0,fb_shutrsn_exit_called);
612     end;
613    
614 tony 45 { TFBStatus }
615    
616 tony 385 function TFBStatus.SQLCodeSupported: boolean;
617     begin
618     Result:= (FOwner <> nil) and assigned(FOwner.isc_sqlcode) and assigned(FOwner.isc_sql_interprete);
619     end;
620    
621 tony 371 function TFBStatus.GetSQLMessage: Ansistring;
622     var local_buffer: array[0..IBHugeLocalBufferLength - 1] of AnsiChar;
623     begin
624     Result := '';
625     if (FOwner <> nil) and assigned(FOwner.isc_sql_interprete) then
626     begin
627     FOwner.isc_sql_interprete(Getsqlcode, local_buffer, sizeof(local_buffer));
628     Result := strpas(local_buffer);
629     end;
630     end;
631    
632 tony 345 constructor TFBStatus.Create(aOwner: TFBClientAPI; prefix: AnsiString);
633 tony 45 begin
634     inherited Create;
635     FOwner := aOwner;
636 tony 345 FPrefix := prefix;
637 tony 385 FIBDataBaseErrorMessages := [ShowIBMessage];
638 tony 45 end;
639    
640 tony 345 function TFBStatus.GetIBErrorCode: TStatusCode;
641 tony 45 begin
642     Result := StatusVector^[1];
643     end;
644    
645 tony 345 function TFBStatus.Getsqlcode: TStatusCode;
646 tony 45 begin
647 tony 371 if (FOwner <> nil) and assigned(FOwner.isc_sqlcode) then
648     Result := FOwner.isc_sqlcode(PISC_STATUS(StatusVector))
649     else
650     Result := -999; {generic SQL Code}
651 tony 45 end;
652    
653 tony 56 function TFBStatus.GetMessage: AnsiString;
654 tony 371 var IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
655 tony 45 begin
656 tony 345 Result := FPrefix;
657 tony 45 IBDataBaseErrorMessages := FIBDataBaseErrorMessages;
658 tony 385 if SQLCodeSupported then
659     begin
660     if (ShowSQLCode in IBDataBaseErrorMessages) then
661     Result := Result + 'SQLCODE: ' + IntToStr(Getsqlcode); {do not localize}
662 tony 45
663 tony 385 if (ShowSQLMessage in IBDataBaseErrorMessages) then
664     begin
665     if ShowSQLCode in IBDataBaseErrorMessages then
666     Result := Result + LineEnding;
667     Result := Result + GetSQLMessage;
668     end;
669 tony 45 end;
670    
671     if (ShowIBMessage in IBDataBaseErrorMessages) then
672     begin
673 tony 385 if Result <> FPrefix then
674 tony 308 Result := Result + LineEnding;
675 tony 385 Result := Result + 'Engine Code: ' + IntToStr(GetIBErrorCode) + LineEnding + GetIBMessage;
676 tony 45 end;
677     if (Result <> '') and (Result[Length(Result)] = '.') then
678     Delete(Result, Length(Result), 1);
679     end;
680    
681     function TFBStatus.CheckStatusVector(ErrorCodes: array of TFBStatusCode
682     ): Boolean;
683     var
684     p: PISC_STATUS;
685     i: Integer;
686     procedure NextP(i: Integer);
687     begin
688 tony 56 p := PISC_STATUS(PAnsiChar(p) + (i * SizeOf(ISC_STATUS)));
689 tony 45 end;
690     begin
691     p := PISC_STATUS(StatusVector);
692     result := False;
693     while (p^ <> 0) and (not result) do
694     case p^ of
695     3: NextP(3);
696     1, 4:
697     begin
698     NextP(1);
699     i := 0;
700     while (i <= High(ErrorCodes)) and (not result) do
701     begin
702     result := p^ = ErrorCodes[i];
703     Inc(i);
704     end;
705     NextP(1);
706     end;
707     else
708     NextP(2);
709     end;
710     end;
711    
712     function TFBStatus.GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
713     begin
714 tony 56 EnterCriticalSection(TFBClientAPI.FIBCS);
715 tony 45 try
716     result := FIBDataBaseErrorMessages;
717     finally
718 tony 56 LeaveCriticalSection(TFBClientAPI.FIBCS);
719 tony 45 end;
720     end;
721    
722     procedure TFBStatus.SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
723     begin
724 tony 56 EnterCriticalSection(TFBClientAPI.FIBCS);
725 tony 45 try
726     FIBDataBaseErrorMessages := Value;
727     finally
728 tony 56 LeaveCriticalSection(TFBClientAPI.FIBCS);
729 tony 45 end;
730     end;
731 tony 60
732 tony 45 initialization
733 tony 263 TFBLibrary.FEnvSetupDone := false;
734 tony 56 {$IFNDEF FPC}
735     InitializeCriticalSection(TFBClientAPI.FIBCS);
736     {$ELSE}
737     InitCriticalSection(TFBClientAPI.FIBCS);
738     {$ENDIF}
739 tony 45
740     finalization
741 tony 263 TFBLibrary.FreeLibraries;
742 tony 56 {$IFNDEF FPC}
743     DeleteCriticalSection(TFBClientAPI.FIBCS);
744     {$ELSE}
745     DoneCriticalSection(TFBClientAPI.FIBCS);
746     {$ENDIF}
747 tony 45 end.
748    

Properties

Name Value
svn:eol-style native