ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/fbintf/client/FBClientAPI.pas
Revision: 421
Committed: Sat Oct 21 14:22:28 2023 UTC (6 months, 1 week ago) by tony
Content type: text/x-pascal
File size: 22403 byte(s)
Log Message:
Release 2.6.3 Merged

File Contents

# Content
1 (*
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 {$IFDEF MSWINDOWS}
64 {$DEFINE WINDOWS}
65 {$ENDIF}
66
67 {$IFDEF FPC}
68 {$mode delphi}
69 {$codepage UTF8}
70 {$interfaces COM}
71 {$ENDIF}
72
73 interface
74
75 uses
76 Classes,
77 {$IFDEF WINDOWS}Windows, {$ENDIF}
78 {$IFDEF FPC} Dynlibs, {$ENDIF}
79 IB, IBHeader, FBActivityMonitor, FBMessages, IBExternals, FmtBCD;
80
81 {For Linux see result of GetFirebirdLibListruntime/nongui/winipc.inc method}
82 {$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 const
94 {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 IBLocalBufferLength = 512;
107 IBBigLocalBufferLength = IBLocalBufferLength * 2;
108 IBHugeLocalBufferLength = IBBigLocalBufferLength * 20;
109
110 type
111 TStatusVector = array[0..19] of NativeInt;
112 PStatusVector = ^TStatusVector;
113
114 TFBClientAPI = class;
115
116 { TFBStatus }
117
118 TFBStatus = class(TFBInterfacedObject, IStatus)
119 private
120 FIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
121 FPrefix: AnsiString;
122 function SQLCodeSupported: boolean;
123 protected
124 FOwner: TFBClientAPI;
125 function GetIBMessage(CodePage: TSystemCodePage): Ansistring; virtual; abstract;
126 function GetSQLMessage(CodePage: TSystemCodePage): Ansistring;
127 public
128 constructor Create(aOwner: TFBClientAPI; prefix: AnsiString='');
129 constructor Copy(src: TFBStatus);
130 function StatusVector: PStatusVector; virtual; abstract;
131 function Clone: IStatus; virtual; abstract;
132
133 {IStatus}
134 function InErrorState: boolean; virtual; abstract;
135 function GetIBErrorCode: TStatusCode;
136 function Getsqlcode: TStatusCode;
137 function GetMessage(CodePage: TSystemCodePage): AnsiString;
138 function CheckStatusVector(ErrorCodes: array of TFBStatusCode): Boolean;
139 function GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
140 procedure SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
141 end;
142
143 { TFBLibrary }
144
145 TFBLibrary = class(TFBInterfacedObject,IFirebirdLibrary)
146 private
147 class var FEnvSetupDone: boolean;
148 class var FLibraryList: array of IFirebirdLibrary;
149 private
150 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 function SameLibrary(aLibName: string): boolean;
168
169 public
170 {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 { TFBClientAPI }
179
180 TFBClientAPI = class(TFBInterfacedObject)
181 private
182 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 class var FIBCS: TRTLCriticalSection;
187 function FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
188 procedure GetTZDataSettings;
189 protected
190 FFBLibrary: TFBLibrary;
191 function GetProcAddr(ProcName: PAnsiChar): Pointer;
192
193 protected type
194 Tfb_shutdown = function (timeout: uint;
195 const reason: int): int;
196 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
197
198 Tfb_sqlstate = procedure(s: PAnsiChar; status_vector: PISC_STATUS);
199 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
200 protected
201 {FB Shutdown API}
202 fb_shutdown: Tfb_shutdown;
203
204 public
205 {Taken from legacy API}
206 isc_sql_interprete: Tisc_sql_interprete;
207 isc_sqlcode: Tisc_sqlcode;
208 fb_sqlstate: Tfb_sqlstate;
209
210 constructor Create(aFBLibrary: TFBLibrary);
211 procedure IBAlloc(var P; OldSize, NewSize: Integer);
212 function LoadInterface: boolean; virtual;
213 procedure FBShutdown; virtual;
214 function GetAPI: IFirebirdAPI; virtual; abstract;
215 {$IFDEF UNIX}
216 function GetFirebirdLibList: string; virtual; abstract;
217 {$ENDIF}
218 function HasDecFloatSupport: boolean;
219 function HasInt128Support: boolean; virtual;
220 function HasLocalTZDB: boolean; virtual;
221 function HasExtendedTZSupport: boolean; virtual;
222 function HasTimeZoneSupport: boolean; virtual;
223
224 public
225 property LocalTimeZoneName: AnsiString read FLocalTimeZoneName;
226 property TZDataTimeZoneID: AnsiString read FTZDataTimeZoneID;
227 property LocalTimeOffset: integer read FLocalTimeOffset;
228 public
229 {Encode/Decode}
230 procedure EncodeInteger(aValue: int64; len: integer; buffer: PByte);
231 function DecodeInteger(bufptr: PByte; len: short): int64;
232 procedure SQLEncodeDate(aDate: TDateTime; bufptr: PByte); virtual; abstract;
233 function SQLDecodeDate(byfptr: PByte): TDateTime; virtual; abstract;
234 procedure SQLEncodeTime(aTime: TDateTime; bufptr: PByte); virtual; abstract;
235 function SQLDecodeTime(bufptr: PByte): TDateTime; virtual; abstract;
236 procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); virtual; abstract;
237 function SQLDecodeDateTime(bufptr: PByte): TDateTime; virtual; abstract;
238 function Int128ToStr(bufptr: PByte; scale: integer): AnsiString; virtual;
239 procedure StrToInt128(scale: integer; aValue: AnsiString; bufptr: PByte);
240 virtual;
241 procedure SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal; bufptr: PByte); virtual;
242 function SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD; virtual;
243
244 {IFirebirdAPI}
245 function GetStatus: IStatus; virtual; abstract;
246 function IsLibraryLoaded: boolean;
247 function IsEmbeddedServer: boolean; virtual; abstract;
248 function GetFBLibrary: IFirebirdLibrary;
249 function GetImplementationVersion: AnsiString;
250 function GetClientMajor: integer; virtual; abstract;
251 function GetClientMinor: integer; virtual; abstract;
252 end;
253
254 IJournallingHook = interface
255 ['{7d3e45e0-3628-416a-9e22-c20474825031}']
256 procedure TransactionStart(Tr: ITransaction);
257 function TransactionEnd(TransactionID: integer; Completion: TTrCompletionState): boolean;
258 procedure TransactionRetained(Tr: ITransaction; OldTransactionID: integer; Action: TTransactionAction);
259 procedure ExecQuery(Stmt: IStatement);
260 procedure ExecImmediateJnl(sql: AnsiString; tr: ITransaction);
261 end;
262
263 implementation
264
265 uses IBUtils, Registry,
266 {$IFDEF Unix} unix, initc, dl, {$ENDIF}
267 {$IFDEF FPC}
268 {$IFDEF WINDOWS }
269 WinDirs,
270 {$ENDIF}
271 {$ELSE}
272 ShlObj,
273 {$ENDIF}
274 SysUtils;
275
276 {$IFDEF UNIX}
277 {$I 'include/uloadlibrary.inc'}
278 {$ELSE}
279 {$I 'include/wloadlibrary.inc'}
280 {$ENDIF}
281
282
283 { TFBLibrary }
284
285 function TFBLibrary.GetOverrideLibName: string;
286 begin
287 Result := FFBLibraryName;
288 if (Result = '') and AllowUseOfFBLIB then
289 Result := GetEnvironmentVariable('FBLIB');
290 if Result = '' then
291 begin
292 if assigned(OnGetLibraryName) then
293 OnGetLibraryName(Result)
294 end;
295 end;
296
297 procedure TFBLibrary.FreeFBLibrary;
298 begin
299 (FFirebirdAPI as TFBClientAPI).FBShutdown;
300 if FIBLibrary <> NilHandle then
301 FreeLibrary(FIBLibrary);
302 FIBLibrary := NilHandle;
303 FFBLibraryName := '';
304 end;
305
306 function TFBLibrary.GetLibraryName: string;
307 begin
308 Result := ExtractFileName(FFBLibraryName);
309 end;
310
311 function TFBLibrary.GetFirebirdAPI: IFirebirdAPI;
312 begin
313 Result := FFirebirdAPI;
314 end;
315
316 constructor TFBLibrary.Create(aLibPathName: string);
317 begin
318 inherited Create;
319 SetupEnvironment;
320 FFBLibraryName := aLibPathName;
321 FIBLibrary := NilHandle;
322 FFirebirdAPI := GetFirebird3API;
323 FRequestedLibName := aLibPathName;
324 if aLibPathName <> '' then
325 begin
326 SetLength(FLibraryList,Length(FLibraryList)+1);
327 FLibraryList[Length(FLibraryList)-1] := self;
328 end;
329 if FFirebirdAPI <> nil then
330 begin
331 {First try Firebird 3}
332 if not LoadIBLibrary or not (FFirebirdAPI as TFBClientAPI).LoadInterface then
333 FFirebirdAPI := nil;
334 end;
335
336 if FFirebirdAPI = nil then
337 begin
338 {now try Firebird 2.5. Under Unix we need to reload the library in case we
339 are to use the embedded library}
340 FFirebirdAPI := GetLegacyFirebirdAPI;
341 if FFirebirdAPI <> nil then
342 begin
343 {$IFDEF UNIX}
344 FreeFBLibrary;
345 {$ENDIF}
346 if not LoadIBLibrary or not (FFirebirdAPI as TFBClientAPI).LoadInterface then
347 FFirebirdAPI := nil;
348 end;
349 end;
350 {Note: FFirebirdAPI will be set to nil if the Firebird API fails to load}
351 end;
352
353 destructor TFBLibrary.Destroy;
354 begin
355 FreeFBLibrary;
356 FFirebirdAPI := nil;
357 inherited Destroy;
358 end;
359
360 class function TFBLibrary.GetFBLibrary(aLibPathName: string): IFirebirdLibrary;
361 var i: integer;
362 begin
363 Result := nil;
364 if aLibPathName <> '' then
365 begin
366 for i := 0 to Length(FLibraryList) - 1 do
367 begin
368 if (FLibraryList[i] as TFBLibrary).SameLibrary(aLibPathName) then
369 begin
370 Result := FLibraryList[i];
371 Exit;
372 end;
373 end;
374 Result := Create(aLibPathName);
375 end;
376
377 end;
378
379 class procedure TFBLibrary.FreeLibraries;
380 var i: integer;
381 begin
382 for i := 0 to Length(FLibraryList) - 1 do
383 FLibraryList[i] := nil;
384 SetLength(FLibraryList,0);
385 end;
386
387 function TFBLibrary.SameLibrary(aLibName: string): boolean;
388 begin
389 Result := FRequestedLibName = aLibName;
390 end;
391
392 function TFBLibrary.GetHandle: TLibHandle;
393 begin
394 Result := FIBLibrary;
395 end;
396
397 { TFBClientAPI }
398
399 constructor TFBClientAPI.Create(aFBLibrary: TFBLibrary);
400 begin
401 inherited Create;
402 FFBLibrary := aFBLibrary;
403 GetTZDataSettings;
404 end;
405
406 procedure TFBClientAPI.IBAlloc(var P; OldSize, NewSize: Integer);
407 var
408 i: Integer;
409 begin
410 ReallocMem(Pointer(P), NewSize);
411 for i := OldSize to NewSize - 1 do PAnsiChar(P)[i] := #0;
412 end;
413
414 procedure TFBClientAPI.EncodeInteger(aValue: int64; len: integer; buffer: PByte);
415 begin
416 while len > 0 do
417 begin
418 buffer^ := aValue and $FF;
419 Inc(buffer);
420 Dec(len);
421 aValue := aValue shr 8;
422 end;
423 end;
424
425 (*
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 function TFBClientAPI.DecodeInteger(bufptr: PByte; len: short): int64;
447 var shift: integer;
448 begin
449 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 end;
464
465 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 function TFBClientAPI.IsLibraryLoaded: boolean;
491 begin
492 Result := FFBLibrary.IBLibrary <> NilHandle;
493 end;
494
495 function TFBClientAPI.GetFBLibrary: IFirebirdLibrary;
496 begin
497 Result := FFBLibrary;
498 end;
499
500 function TFBClientAPI.FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
501 begin
502 {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 end;
509
510 {$IFDEF UNIX}
511
512 procedure TFBClientAPI.GetTZDataSettings;
513 var S: TStringList;
514 begin
515 FLocalTimeOffset := GetLocalTimeOffset;
516 {$if declared(Gettzname)}
517 FLocalTimeZoneName := Gettzname(tzdaylight);
518 {$else}
519 FLocalTimeZoneName := tzname[tzdaylight];
520 {$ifend}
521 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 function TFBClientAPI.GetProcAddr(ProcName: PAnsiChar): Pointer;
564 begin
565 Result := nil;
566 if assigned(FFBLibrary) and (FFBLibrary.IBLibrary <> NilHandle) then
567 Result := GetProcAddress(FFBLibrary.IBLibrary, ProcName);
568 if not Assigned(Result) then
569 raise Exception.CreateFmt(SFirebirdAPIFuncNotFound,[ProcName]);
570 end;
571
572 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 function TFBClientAPI.LoadInterface: boolean;
603 begin
604 isc_sqlcode := GetProcAddr('isc_sqlcode'); {do not localize}
605 isc_sql_interprete := GetProcAddr('isc_sql_interprete'); {do not localize}
606 fb_shutdown := GetProcAddr('fb_shutdown'); {do not localize}
607 fb_sqlstate := GetProcAddr('fb_sqlstate'); {do not localize}
608 Result := true; {don't case if these fail to load}
609 end;
610
611 procedure TFBClientAPI.FBShutdown;
612 begin
613 if assigned(fb_shutdown) then
614 fb_shutdown(0,fb_shutrsn_exit_called);
615 end;
616
617 { TFBStatus }
618
619 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 function TFBStatus.GetSQLMessage(CodePage: TSystemCodePage): 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 := PCharToAnsiString(local_buffer,CodePage);
632 end;
633 end;
634
635 constructor TFBStatus.Create(aOwner: TFBClientAPI; prefix: AnsiString);
636 begin
637 inherited Create;
638 FOwner := aOwner;
639 FPrefix := prefix;
640 FIBDataBaseErrorMessages := [ShowIBMessage];
641 end;
642
643 constructor TFBStatus.Copy(src: TFBStatus);
644 begin
645 inherited Create;
646 FOwner := src.FOwner;
647 FPrefix := src.FPrefix;
648 SetIBDataBaseErrorMessages(src.GetIBDataBaseErrorMessages);
649 end;
650
651 function TFBStatus.GetIBErrorCode: TStatusCode;
652 begin
653 Result := StatusVector^[1];
654 end;
655
656 function TFBStatus.Getsqlcode: TStatusCode;
657 begin
658 if (FOwner <> nil) and assigned(FOwner.isc_sqlcode) then
659 Result := FOwner.isc_sqlcode(PISC_STATUS(StatusVector))
660 else
661 Result := -999; {generic SQL Code}
662 end;
663
664 function TFBStatus.GetMessage(CodePage: TSystemCodePage): AnsiString;
665 var IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
666 begin
667 Result := FPrefix;
668 IBDataBaseErrorMessages := FIBDataBaseErrorMessages;
669 if SQLCodeSupported then
670 begin
671 if (ShowSQLCode in IBDataBaseErrorMessages) then
672 Result := Result + 'SQLCODE: ' + IntToStr(Getsqlcode); {do not localize}
673
674 if (ShowSQLMessage in IBDataBaseErrorMessages) then
675 begin
676 if ShowSQLCode in IBDataBaseErrorMessages then
677 Result := Result + LineEnding;
678 Result := Result + GetSQLMessage(CodePage);
679 end;
680 end;
681
682 if (ShowIBMessage in IBDataBaseErrorMessages) then
683 begin
684 if Result <> FPrefix then
685 Result := Result + LineEnding;
686 Result := Result + 'Engine Code: ' + IntToStr(GetIBErrorCode) + LineEnding
687 + GetIBMessage(CodePage);
688 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 p := PISC_STATUS(PAnsiChar(p) + (i * SizeOf(ISC_STATUS)));
701 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 EnterCriticalSection(TFBClientAPI.FIBCS);
727 try
728 result := FIBDataBaseErrorMessages;
729 finally
730 LeaveCriticalSection(TFBClientAPI.FIBCS);
731 end;
732 end;
733
734 procedure TFBStatus.SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
735 begin
736 EnterCriticalSection(TFBClientAPI.FIBCS);
737 try
738 FIBDataBaseErrorMessages := Value;
739 finally
740 LeaveCriticalSection(TFBClientAPI.FIBCS);
741 end;
742 end;
743
744 initialization
745 TFBLibrary.FEnvSetupDone := false;
746 {$IFNDEF FPC}
747 InitializeCriticalSection(TFBClientAPI.FIBCS);
748 {$ELSE}
749 InitCriticalSection(TFBClientAPI.FIBCS);
750 {$ENDIF}
751
752 finalization
753 TFBLibrary.FreeLibraries;
754 {$IFNDEF FPC}
755 DeleteCriticalSection(TFBClientAPI.FIBCS);
756 {$ELSE}
757 DoneCriticalSection(TFBClientAPI.FIBCS);
758 {$ENDIF}
759 end.
760

Properties

Name Value
svn:eol-style native