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

# 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 function StatusVector: PStatusVector; virtual; abstract;
130 procedure Assign(src: TFBStatus); virtual;
131 function Clone: IStatus; virtual; abstract;
132
133 {IStatus}
134 function GetIBErrorCode: TStatusCode;
135 function Getsqlcode: TStatusCode;
136 function GetMessage: AnsiString;
137 function CheckStatusVector(ErrorCodes: array of TFBStatusCode): Boolean;
138 function GetIBDataBaseErrorMessages: TIBDataBaseErrorMessages;
139 procedure SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
140 end;
141
142 { TFBLibrary }
143
144 TFBLibrary = class(TFBInterfacedObject,IFirebirdLibrary)
145 private
146 class var FEnvSetupDone: boolean;
147 class var FLibraryList: array of IFirebirdLibrary;
148 private
149 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 function SameLibrary(aLibName: string): boolean;
167
168 public
169 {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 { TFBClientAPI }
178
179 TFBClientAPI = class(TFBInterfacedObject)
180 private
181 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 class var FIBCS: TRTLCriticalSection;
186 function FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
187 procedure GetTZDataSettings;
188 protected
189 FFBLibrary: TFBLibrary;
190 function GetProcAddr(ProcName: PAnsiChar): Pointer;
191
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 public
201 {Taken from legacy API}
202 isc_sql_interprete: Tisc_sql_interprete;
203 isc_sqlcode: Tisc_sqlcode;
204
205 constructor Create(aFBLibrary: TFBLibrary);
206 procedure IBAlloc(var P; OldSize, NewSize: Integer);
207 procedure IBDataBaseError;
208 function LoadInterface: boolean; virtual;
209 procedure FBShutdown; virtual;
210 function GetAPI: IFirebirdAPI; virtual; abstract;
211 {$IFDEF UNIX}
212 function GetFirebirdLibList: string; virtual; abstract;
213 {$ENDIF}
214 function HasDecFloatSupport: boolean;
215 function HasInt128Support: boolean; virtual;
216 function HasLocalTZDB: boolean; virtual;
217 function HasExtendedTZSupport: boolean; virtual;
218 function HasTimeZoneSupport: boolean; virtual;
219
220 public
221 property LocalTimeZoneName: AnsiString read FLocalTimeZoneName;
222 property TZDataTimeZoneID: AnsiString read FTZDataTimeZoneID;
223 property LocalTimeOffset: integer read FLocalTimeOffset;
224 public
225 {Encode/Decode}
226 procedure EncodeInteger(aValue: int64; len: integer; buffer: PByte);
227 function DecodeInteger(bufptr: PByte; len: short): int64;
228 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 function SQLDecodeTime(bufptr: PByte): TDateTime; virtual; abstract;
232 procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); virtual; abstract;
233 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
240 {IFirebirdAPI}
241 function GetStatus: IStatus; virtual; abstract;
242 function IsLibraryLoaded: boolean;
243 function IsEmbeddedServer: boolean; virtual; abstract;
244 function GetFBLibrary: IFirebirdLibrary;
245 function GetImplementationVersion: AnsiString;
246 function GetClientMajor: integer; virtual; abstract;
247 function GetClientMinor: integer; virtual; abstract;
248 end;
249
250 IJournallingHook = interface
251 ['{7d3e45e0-3628-416a-9e22-c20474825031}']
252 procedure TransactionStart(Tr: ITransaction);
253 function TransactionEnd(TransactionID: integer; Completion: TTrCompletionState): boolean;
254 procedure TransactionRetained(Tr: ITransaction; OldTransactionID: integer; Action: TTransactionAction);
255 procedure ExecQuery(Stmt: IStatement);
256 procedure ExecImmediateJnl(sql: AnsiString; tr: ITransaction);
257 end;
258
259 implementation
260
261 uses IBUtils, Registry,
262 {$IFDEF Unix} unix, initc, dl, {$ENDIF}
263 {$IFDEF FPC}
264 {$IFDEF WINDOWS }
265 WinDirs,
266 {$ENDIF}
267 {$ELSE}
268 ShlObj,
269 {$ENDIF}
270 SysUtils;
271
272 {$IFDEF UNIX}
273 {$I 'include/uloadlibrary.inc'}
274 {$ELSE}
275 {$I 'include/wloadlibrary.inc'}
276 {$ENDIF}
277
278
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 begin
288 if assigned(OnGetLibraryName) then
289 OnGetLibraryName(Result)
290 end;
291 end;
292
293 procedure TFBLibrary.FreeFBLibrary;
294 begin
295 (FFirebirdAPI as TFBClientAPI).FBShutdown;
296 if FIBLibrary <> NilHandle then
297 FreeLibrary(FIBLibrary);
298 FIBLibrary := NilHandle;
299 FFBLibraryName := '';
300 end;
301
302 function TFBLibrary.GetLibraryName: string;
303 begin
304 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 inherited Create;
315 SetupEnvironment;
316 FFBLibraryName := aLibPathName;
317 FIBLibrary := NilHandle;
318 FFirebirdAPI := GetFirebird3API;
319 FRequestedLibName := aLibPathName;
320 if aLibPathName <> '' then
321 begin
322 SetLength(FLibraryList,Length(FLibraryList)+1);
323 FLibraryList[Length(FLibraryList)-1] := self;
324 end;
325 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 end;
348
349 destructor TFBLibrary.Destroy;
350 begin
351 FreeFBLibrary;
352 FFirebirdAPI := nil;
353 inherited Destroy;
354 end;
355
356 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 begin
364 if (FLibraryList[i] as TFBLibrary).SameLibrary(aLibPathName) then
365 begin
366 Result := FLibraryList[i];
367 Exit;
368 end;
369 end;
370 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 function TFBLibrary.SameLibrary(aLibName: string): boolean;
384 begin
385 Result := FRequestedLibName = aLibName;
386 end;
387
388 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 GetTZDataSettings;
400 end;
401
402 procedure TFBClientAPI.IBAlloc(var P; OldSize, NewSize: Integer);
403 var
404 i: Integer;
405 begin
406 ReallocMem(Pointer(P), NewSize);
407 for i := OldSize to NewSize - 1 do PAnsiChar(P)[i] := #0;
408 end;
409
410 procedure TFBClientAPI.IBDataBaseError;
411 begin
412 raise EIBInterBaseError.Create(GetStatus);
413 end;
414
415 procedure TFBClientAPI.EncodeInteger(aValue: int64; len: integer; buffer: PByte);
416 begin
417 while len > 0 do
418 begin
419 buffer^ := aValue and $FF;
420 Inc(buffer);
421 Dec(len);
422 aValue := aValue shr 8;
423 end;
424 end;
425
426 (*
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 function TFBClientAPI.DecodeInteger(bufptr: PByte; len: short): int64;
448 var shift: integer;
449 begin
450 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 end;
465
466 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 function TFBClientAPI.IsLibraryLoaded: boolean;
492 begin
493 Result := FFBLibrary.IBLibrary <> NilHandle;
494 end;
495
496 function TFBClientAPI.GetFBLibrary: IFirebirdLibrary;
497 begin
498 Result := FFBLibrary;
499 end;
500
501 function TFBClientAPI.FBTimeStampToDateTime(aDate, aTime: longint): TDateTime;
502 begin
503 {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 end;
510
511 {$IFDEF UNIX}
512
513 procedure TFBClientAPI.GetTZDataSettings;
514 var S: TStringList;
515 begin
516 FLocalTimeOffset := GetLocalTimeOffset;
517 {$if declared(Gettzname)}
518 FLocalTimeZoneName := Gettzname(tzdaylight);
519 {$else}
520 FLocalTimeZoneName := tzname[tzdaylight];
521 {$ifend}
522 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 function TFBClientAPI.GetProcAddr(ProcName: PAnsiChar): Pointer;
565 begin
566 Result := nil;
567 if assigned(FFBLibrary) and (FFBLibrary.IBLibrary <> NilHandle) then
568 Result := GetProcAddress(FFBLibrary.IBLibrary, ProcName);
569 if not Assigned(Result) then
570 raise Exception.CreateFmt(SFirebirdAPIFuncNotFound,[ProcName]);
571 end;
572
573 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 function TFBClientAPI.LoadInterface: boolean;
604 begin
605 isc_sqlcode := GetProcAddr('isc_sqlcode'); {do not localize}
606 isc_sql_interprete := GetProcAddr('isc_sql_interprete'); {do not localize}
607 fb_shutdown := GetProcAddr('fb_shutdown'); {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: 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 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 procedure TFBStatus.Assign(src: TFBStatus);
644 begin
645 FOwner := src.FOwner;
646 FPrefix := src.FPrefix;
647 SetIBDataBaseErrorMessages(src.GetIBDataBaseErrorMessages);
648 end;
649
650 function TFBStatus.GetIBErrorCode: TStatusCode;
651 begin
652 Result := StatusVector^[1];
653 end;
654
655 function TFBStatus.Getsqlcode: TStatusCode;
656 begin
657 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 end;
662
663 function TFBStatus.GetMessage: AnsiString;
664 var IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
665 begin
666 Result := FPrefix;
667 IBDataBaseErrorMessages := FIBDataBaseErrorMessages;
668 if SQLCodeSupported then
669 begin
670 if (ShowSQLCode in IBDataBaseErrorMessages) then
671 Result := Result + 'SQLCODE: ' + IntToStr(Getsqlcode); {do not localize}
672
673 if (ShowSQLMessage in IBDataBaseErrorMessages) then
674 begin
675 if ShowSQLCode in IBDataBaseErrorMessages then
676 Result := Result + LineEnding;
677 Result := Result + GetSQLMessage;
678 end;
679 end;
680
681 if (ShowIBMessage in IBDataBaseErrorMessages) then
682 begin
683 if Result <> FPrefix then
684 Result := Result + LineEnding;
685 Result := Result + 'Engine Code: ' + IntToStr(GetIBErrorCode) + LineEnding + GetIBMessage;
686 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 p := PISC_STATUS(PAnsiChar(p) + (i * SizeOf(ISC_STATUS)));
699 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 EnterCriticalSection(TFBClientAPI.FIBCS);
725 try
726 result := FIBDataBaseErrorMessages;
727 finally
728 LeaveCriticalSection(TFBClientAPI.FIBCS);
729 end;
730 end;
731
732 procedure TFBStatus.SetIBDataBaseErrorMessages(Value: TIBDataBaseErrorMessages);
733 begin
734 EnterCriticalSection(TFBClientAPI.FIBCS);
735 try
736 FIBDataBaseErrorMessages := Value;
737 finally
738 LeaveCriticalSection(TFBClientAPI.FIBCS);
739 end;
740 end;
741
742 initialization
743 TFBLibrary.FEnvSetupDone := false;
744 {$IFNDEF FPC}
745 InitializeCriticalSection(TFBClientAPI.FIBCS);
746 {$ELSE}
747 InitCriticalSection(TFBClientAPI.FIBCS);
748 {$ENDIF}
749
750 finalization
751 TFBLibrary.FreeLibraries;
752 {$IFNDEF FPC}
753 DeleteCriticalSection(TFBClientAPI.FIBCS);
754 {$ELSE}
755 DoneCriticalSection(TFBClientAPI.FIBCS);
756 {$ENDIF}
757 end.
758

Properties

Name Value
svn:eol-style native