ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBClientAPI.pas
Revision: 390
Committed: Sat Jan 22 16:15:12 2022 UTC (2 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 22113 byte(s)
Log Message:
In Firebird 3 and later API: the status vector is now a thread var

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

Properties

Name Value
svn:eol-style native