ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/FBClientAPI.pas
Revision: 385
Committed: Mon Jan 17 15:56:35 2022 UTC (2 years, 10 months ago) by tony
Content type: text/x-pascal
File size: 21702 byte(s)
Log Message:
Return nil result for UDR procedures when an exception occurs

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

Properties

Name Value
svn:eol-style native