ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBClientAPI.pas
Revision: 387
Committed: Wed Jan 19 13:34:42 2022 UTC (2 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 22047 byte(s)
Log Message:
Transactions started within a UDR are not forcibly closed if still active immediately prior to UDR exit

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

Properties

Name Value
svn:eol-style native