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

# 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: Ansistring; virtual; abstract;
126 function GetSQLMessage: 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: 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 protected
198 {FB Shutdown API}
199 fb_shutdown: Tfb_shutdown;
200
201 public
202 {Taken from legacy API}
203 isc_sql_interprete: Tisc_sql_interprete;
204 isc_sqlcode: Tisc_sqlcode;
205
206 constructor Create(aFBLibrary: TFBLibrary);
207 procedure IBAlloc(var P; OldSize, NewSize: Integer);
208 procedure IBDataBaseError;
209 function LoadInterface: boolean; virtual;
210 procedure FBShutdown; virtual;
211 function GetAPI: IFirebirdAPI; virtual; abstract;
212 {$IFDEF UNIX}
213 function GetFirebirdLibList: string; virtual; abstract;
214 {$ENDIF}
215 function HasDecFloatSupport: boolean;
216 function HasInt128Support: boolean; virtual;
217 function HasLocalTZDB: boolean; virtual;
218 function HasExtendedTZSupport: boolean; virtual;
219 function HasTimeZoneSupport: boolean; virtual;
220
221 public
222 property LocalTimeZoneName: AnsiString read FLocalTimeZoneName;
223 property TZDataTimeZoneID: AnsiString read FTZDataTimeZoneID;
224 property LocalTimeOffset: integer read FLocalTimeOffset;
225 public
226 {Encode/Decode}
227 procedure EncodeInteger(aValue: int64; len: integer; buffer: PByte);
228 function DecodeInteger(bufptr: PByte; len: short): int64;
229 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 function SQLDecodeTime(bufptr: PByte): TDateTime; virtual; abstract;
233 procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); virtual; abstract;
234 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
241 {IFirebirdAPI}
242 function GetStatus: IStatus; virtual; abstract;
243 function IsLibraryLoaded: boolean;
244 function IsEmbeddedServer: boolean; virtual; abstract;
245 function GetFBLibrary: IFirebirdLibrary;
246 function GetImplementationVersion: AnsiString;
247 function GetClientMajor: integer; virtual; abstract;
248 function GetClientMinor: integer; virtual; abstract;
249 end;
250
251 IJournallingHook = interface
252 ['{7d3e45e0-3628-416a-9e22-c20474825031}']
253 procedure TransactionStart(Tr: ITransaction);
254 function TransactionEnd(TransactionID: integer; Completion: TTrCompletionState): boolean;
255 procedure TransactionRetained(Tr: ITransaction; OldTransactionID: integer; Action: TTransactionAction);
256 procedure ExecQuery(Stmt: IStatement);
257 procedure ExecImmediateJnl(sql: AnsiString; tr: ITransaction);
258 end;
259
260 implementation
261
262 uses IBUtils, Registry,
263 {$IFDEF Unix} unix, initc, dl, {$ENDIF}
264 {$IFDEF FPC}
265 {$IFDEF WINDOWS }
266 WinDirs,
267 {$ENDIF}
268 {$ELSE}
269 ShlObj,
270 {$ENDIF}
271 SysUtils;
272
273 {$IFDEF UNIX}
274 {$I 'include/uloadlibrary.inc'}
275 {$ELSE}
276 {$I 'include/wloadlibrary.inc'}
277 {$ENDIF}
278
279
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 begin
289 if assigned(OnGetLibraryName) then
290 OnGetLibraryName(Result)
291 end;
292 end;
293
294 procedure TFBLibrary.FreeFBLibrary;
295 begin
296 (FFirebirdAPI as TFBClientAPI).FBShutdown;
297 if FIBLibrary <> NilHandle then
298 FreeLibrary(FIBLibrary);
299 FIBLibrary := NilHandle;
300 FFBLibraryName := '';
301 end;
302
303 function TFBLibrary.GetLibraryName: string;
304 begin
305 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 inherited Create;
316 SetupEnvironment;
317 FFBLibraryName := aLibPathName;
318 FIBLibrary := NilHandle;
319 FFirebirdAPI := GetFirebird3API;
320 FRequestedLibName := aLibPathName;
321 if aLibPathName <> '' then
322 begin
323 SetLength(FLibraryList,Length(FLibraryList)+1);
324 FLibraryList[Length(FLibraryList)-1] := self;
325 end;
326 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 end;
349
350 destructor TFBLibrary.Destroy;
351 begin
352 FreeFBLibrary;
353 FFirebirdAPI := nil;
354 inherited Destroy;
355 end;
356
357 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 begin
365 if (FLibraryList[i] as TFBLibrary).SameLibrary(aLibPathName) then
366 begin
367 Result := FLibraryList[i];
368 Exit;
369 end;
370 end;
371 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 function TFBLibrary.SameLibrary(aLibName: string): boolean;
385 begin
386 Result := FRequestedLibName = aLibName;
387 end;
388
389 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 GetTZDataSettings;
401 end;
402
403 procedure TFBClientAPI.IBAlloc(var P; OldSize, NewSize: Integer);
404 var
405 i: Integer;
406 begin
407 ReallocMem(Pointer(P), NewSize);
408 for i := OldSize to NewSize - 1 do PAnsiChar(P)[i] := #0;
409 end;
410
411 procedure TFBClientAPI.IBDataBaseError;
412 begin
413 raise EIBInterBaseError.Create(GetStatus);
414 end;
415
416 procedure TFBClientAPI.EncodeInteger(aValue: int64; len: integer; buffer: PByte);
417 begin
418 while len > 0 do
419 begin
420 buffer^ := aValue and $FF;
421 Inc(buffer);
422 Dec(len);
423 aValue := aValue shr 8;
424 end;
425 end;
426
427 (*
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 function TFBClientAPI.DecodeInteger(bufptr: PByte; len: short): int64;
449 var shift: integer;
450 begin
451 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 end;
466
467 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 function TFBClientAPI.IsLibraryLoaded: boolean;
493 begin
494 Result := FFBLibrary.IBLibrary <> NilHandle;
495 end;
496
497 function TFBClientAPI.GetFBLibrary: IFirebirdLibrary;
498 begin
499 Result := FFBLibrary;
500 end;
501
502 function TFBClientAPI.FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
503 begin
504 {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 end;
511
512 {$IFDEF UNIX}
513
514 procedure TFBClientAPI.GetTZDataSettings;
515 var S: TStringList;
516 begin
517 FLocalTimeOffset := GetLocalTimeOffset;
518 {$if declared(Gettzname)}
519 FLocalTimeZoneName := Gettzname(tzdaylight);
520 {$else}
521 FLocalTimeZoneName := tzname[tzdaylight];
522 {$ifend}
523 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 function TFBClientAPI.GetProcAddr(ProcName: PAnsiChar): Pointer;
566 begin
567 Result := nil;
568 if assigned(FFBLibrary) and (FFBLibrary.IBLibrary <> NilHandle) then
569 Result := GetProcAddress(FFBLibrary.IBLibrary, ProcName);
570 if not Assigned(Result) then
571 raise Exception.CreateFmt(SFirebirdAPIFuncNotFound,[ProcName]);
572 end;
573
574 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 function TFBClientAPI.LoadInterface: boolean;
605 begin
606 isc_sqlcode := GetProcAddr('isc_sqlcode'); {do not localize}
607 isc_sql_interprete := GetProcAddr('isc_sql_interprete'); {do not localize}
608 fb_shutdown := GetProcAddr('fb_shutdown'); {do not localize}
609 Result := true; {don't case if these fail to load}
610 end;
611
612 procedure TFBClientAPI.FBShutdown;
613 begin
614 if assigned(fb_shutdown) then
615 fb_shutdown(0,fb_shutrsn_exit_called);
616 end;
617
618 { TFBStatus }
619
620 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 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 constructor TFBStatus.Create(aOwner: TFBClientAPI; prefix: AnsiString);
637 begin
638 inherited Create;
639 FOwner := aOwner;
640 FPrefix := prefix;
641 FIBDataBaseErrorMessages := [ShowIBMessage];
642 end;
643
644 constructor TFBStatus.Copy(src: TFBStatus);
645 begin
646 inherited Create;
647 FOwner := src.FOwner;
648 FPrefix := src.FPrefix;
649 SetIBDataBaseErrorMessages(src.GetIBDataBaseErrorMessages);
650 end;
651
652 function TFBStatus.GetIBErrorCode: TStatusCode;
653 begin
654 Result := StatusVector^[1];
655 end;
656
657 function TFBStatus.Getsqlcode: TStatusCode;
658 begin
659 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 end;
664
665 function TFBStatus.GetMessage: AnsiString;
666 var IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
667 begin
668 Result := FPrefix;
669 IBDataBaseErrorMessages := FIBDataBaseErrorMessages;
670 if SQLCodeSupported then
671 begin
672 if (ShowSQLCode in IBDataBaseErrorMessages) then
673 Result := Result + 'SQLCODE: ' + IntToStr(Getsqlcode); {do not localize}
674
675 if (ShowSQLMessage in IBDataBaseErrorMessages) then
676 begin
677 if ShowSQLCode in IBDataBaseErrorMessages then
678 Result := Result + LineEnding;
679 Result := Result + GetSQLMessage;
680 end;
681 end;
682
683 if (ShowIBMessage in IBDataBaseErrorMessages) then
684 begin
685 if Result <> FPrefix then
686 Result := Result + LineEnding;
687 Result := Result + 'Engine Code: ' + IntToStr(GetIBErrorCode) + LineEnding + GetIBMessage;
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