ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/udr/client/3.0/FB30ClientAPI.pas
Revision: 379
Committed: Mon Jan 10 10:08:03 2022 UTC (2 years, 3 months ago) by tony
Content type: text/x-pascal
File size: 22177 byte(s)
Log Message:
set line ending property

File Contents

# Content
1 (*
2 * Firebird Interface (fbintf). The fbintf components provide a set of
3 * Pascal language bindings for the Firebird API.
4 *
5 * The contents of this file are subject to the Initial Developer's
6 * Public License Version 1.0 (the "License"); you may not use this
7 * file except in compliance with the License. You may obtain a copy
8 * of the License here:
9 *
10 * http://www.firebirdsql.org/index.php?op=doc&id=idpl
11 *
12 * Software distributed under the License is distributed on an "AS
13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing rights
15 * and limitations under the License.
16 *
17 * The Initial Developer of the Original Code is Tony Whyman.
18 *
19 * The Original Code is (C) 2016 Tony Whyman, MWA Software
20 * (http://www.mwasoftware.co.uk).
21 *
22 * All Rights Reserved.
23 *
24 * Contributor(s): ______________________________________.
25 *
26 *)
27 unit FB30ClientAPI;
28 {$IFDEF MSWINDOWS}
29 {$DEFINE WINDOWS}
30 {$ENDIF}
31
32 {$IFDEF FPC}
33 {$mode delphi}
34 {$interfaces COM}
35 {$ENDIF}
36
37 interface
38
39 uses
40 Classes, SysUtils, FBClientAPI, Firebird, IB, IBExternals, FmtBCD, FBClientLib,
41 FBActivityMonitor;
42
43 type
44
45 { TFB30Status }
46
47 TFB30Status = class(TFBStatus,IStatus)
48 protected
49 FStatus: Firebird.IStatus;
50 FDirty: boolean;
51 function GetIBMessage: Ansistring; override;
52 public
53 destructor Destroy; override;
54 procedure Init;
55 procedure FreeHandle;
56 function InErrorState: boolean;
57 function Warning: boolean;
58 function GetStatus: Firebird.IStatus;
59 function StatusVector: PStatusVector; override;
60 property Dirty: boolean read FDirty;
61 end;
62
63 { TFB30StatusObject }
64
65 TFB30StatusObject = class(TFB30Status)
66 public
67 constructor Create(aOwner: TFBClientAPI; status: Firebird.IStatus; prefix: Ansistring='');
68 end;
69
70 Tfb_get_master_interface = function: IMaster;
71 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF}
72
73 { TFB30ClientAPI }
74
75 TFB30ClientAPI = class(TFBClientAPI,IFirebirdAPI,IFBIMasterProvider)
76 private
77 FMaster: Firebird.IMaster;
78 FUtil: Firebird.IUtil;
79 FProvider: Firebird.IProvider;
80 FConfigManager: Firebird.IConfigManager;
81 FStatus: TFB30Status;
82 FIsEmbeddedServer: boolean;
83 FStatusIntf: IStatus; {Keep a reference to the interface - automatic destroy
84 when this class is freed and last reference to IStatus
85 goes out of scope.}
86 procedure CheckPlugins;
87 public
88 constructor Create(aFBLibrary: TFBLibrary); overload;
89 constructor Create(aMaster: Firebird.IMaster); overload;
90 destructor Destroy; override;
91
92 function StatusIntf: Firebird.IStatus;
93 procedure Check4DataBaseError; overload;
94 procedure Check4DataBaseError(st: Firebird.IStatus); overload;
95 function FormatStatus(Status: Firebird.IStatus): AnsiString;
96 function InErrorState: boolean;
97 function LoadInterface: boolean; override;
98 procedure FBShutdown; override;
99 function GetAPI: IFirebirdAPI; override;
100 function Firebird4orLater: boolean;
101 {$IFDEF UNIX}
102 function GetFirebirdLibList: string; override;
103 {$ENDIF}
104
105 public
106 {IFirebirdAPI}
107 function GetStatus: IStatus; override;
108 function AllocateDPB: IDPB;
109 function AllocateTPB: ITPB;
110
111 {Database connections}
112 function OpenDatabase(DatabaseName: AnsiString; DPB: IDPB; RaiseExceptionOnConnectError: boolean=true): IAttachment;
113 function CreateDatabase(DatabaseName: AnsiString; DPB: IDPB; RaiseExceptionOnError: boolean=true): IAttachment; overload;
114 function CreateDatabase(sql: AnsiString; aSQLDialect: integer; RaiseExceptionOnError: boolean=true): IAttachment; overload;
115 {Start Transaction against multiple databases}
116 function StartTransaction(Attachments: array of IAttachment;
117 TPB: array of byte; DefaultCompletion: TTransactionCompletion; aName: AnsiString=''): ITransaction; overload;
118 function StartTransaction(Attachments: array of IAttachment;
119 TPB: ITPB; DefaultCompletion: TTransactionCompletion; aName: AnsiString=''): ITransaction; overload;
120
121 {Service Manager}
122 function AllocateSPB: ISPB;
123 function GetServiceManager(ServerName: AnsiString; Protocol: TProtocol; SPB: ISPB): IServiceManager; overload;
124 function GetServiceManager(ServerName: AnsiString; Port: Ansistring; Protocol: TProtocol; SPB: ISPB): IServiceManager; overload;
125
126 {Information}
127 function HasServiceAPI: boolean;
128 function HasRollbackRetaining: boolean;
129 function IsEmbeddedServer: boolean; override;
130 function GetClientMajor: integer; override;
131 function GetClientMinor: integer; override;
132 function HasLocalTZDB: boolean; override;
133 function HasTimeZoneSupport: boolean; override;
134 function HasExtendedTZSupport: boolean; override;
135 function HasInt128Support: boolean; override;
136 function HasScollableCursors: boolean;
137
138 {Firebird 3 API}
139 function HasMasterIntf: boolean;
140 function GetIMaster: TObject;
141
142 {IFBIMasterProvider}
143 function GetIMasterIntf: Firebird.IMaster;
144
145 {Encode/Decode}
146 procedure SQLEncodeDate(aDate: TDateTime; bufptr: PByte); override;
147 function SQLDecodeDate(bufptr: PByte): TDateTime; override;
148 procedure SQLEncodeTime(aTime: TDateTime; bufptr: PByte); override;
149 function SQLDecodeTime(bufptr: PByte): TDateTime; override;
150 procedure SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte); override;
151 function SQLDecodeDateTime(bufptr: PByte): TDateTime; override;
152
153 {Firebird 4 Extensions}
154 procedure SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal; bufptr: PByte);
155 override;
156 function SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD; override;
157 function Int128ToStr(bufptr: PByte; scale: integer): AnsiString; override;
158 procedure StrToInt128(scale: integer; aValue: AnsiString; bufptr: PByte); override;
159
160 {Firebird Interfaces}
161 property MasterIntf: Firebird.IMaster read FMaster;
162 property UtilIntf: Firebird.IUtil read FUtil;
163 property ProviderIntf: Firebird.IProvider read FProvider;
164
165 end;
166
167 { TXPBParameterBlock }
168
169 TXPBParameterBlock = class(TFBInterfacedObject)
170 private
171 FBuilder: Firebird.IXpbBuilder;
172 FFirebird30ClientAPI: TFB30ClientAPI;
173 public
174 constructor Create(api: TFB30ClientAPI; kind: cardinal);
175 destructor Destroy; override;
176 function getBuffer: PByte;
177 function getDataLength: cardinal;
178 procedure insertInt(tag: Byte; value: Integer);
179 property Builder: Firebird.IXpbBuilder read FBuilder;
180 public
181 procedure PrintBuf;
182 end;
183
184 implementation
185
186 uses FB30Attachment, {$IFDEF FPC}dynlibs{$ELSE} windows{$ENDIF},
187 FBMessages, FB30Services, FB30Transaction, IBUtils, DateUtils,
188 FBAttachment, FBTransaction, FBServices;
189
190 type
191 PISC_DATE = ^ISC_DATE;
192 PISC_TIME = ^ISC_TIME;
193
194 { TXPBParameterBlock }
195
196 constructor TXPBParameterBlock.Create(api: TFB30ClientAPI; kind: cardinal);
197 begin
198 inherited Create;
199 FFirebird30ClientAPI := api;
200 with FFirebird30ClientAPI do
201 begin
202 FBuilder := UtilIntf.getXpbBuilder(StatusIntf,kind,nil,0);
203 Check4DataBaseError;
204 end;
205 end;
206
207 destructor TXPBParameterBlock.Destroy;
208 begin
209 if FBuilder <> nil then
210 begin
211 FBuilder.dispose;
212 FBuilder := nil;
213 end;
214 inherited Destroy;
215 end;
216
217 function TXPBParameterBlock.getBuffer: PByte;
218 begin
219 with FFirebird30ClientAPI do
220 begin
221 Result := PByte(FBuilder.getBuffer(StatusIntf));
222 Check4DataBaseError;
223 end;
224 end;
225
226 function TXPBParameterBlock.getDataLength: cardinal;
227 begin
228 with FFirebird30ClientAPI do
229 begin
230 Result := FBuilder.getBufferLength(StatusIntf);
231 Check4DataBaseError;
232 end;
233 end;
234
235 procedure TXPBParameterBlock.insertInt(tag: Byte; value: Integer);
236 begin
237 with FFirebird30ClientAPI do
238 begin
239 Builder.insertInt(StatusIntf,tag,value);
240 Check4DataBaseError;
241 end;
242 end;
243
244 procedure TXPBParameterBlock.PrintBuf;
245 var i: integer;
246 buffer: PByte;
247 begin
248 write(ClassName,': (',getDataLength,') ');
249 buffer := getBuffer;
250 for i := 0 to getDataLength - 1 do
251 begin
252 write(Format('%x ',[buffer^]));
253 Inc(buffer);
254 end;
255 writeln
256 end;
257
258 { TFB30StatusObject }
259
260 constructor TFB30StatusObject.Create(aOwner: TFBClientAPI;
261 status: Firebird.IStatus; prefix: Ansistring);
262 begin
263 inherited Create(aOwner,prefix);
264 FStatus := status.clone;
265 end;
266
267 { TFB30Status }
268
269 function TFB30Status.GetIBMessage: Ansistring;
270 begin
271 Result := (FOwner as TFB30ClientAPI).FormatStatus(FStatus);
272 end;
273
274 destructor TFB30Status.Destroy;
275 begin
276 FreeHandle;
277 inherited Destroy;
278 end;
279
280 procedure TFB30Status.Init;
281 begin
282 if assigned(FStatus) and Dirty then
283 begin
284 FStatus.Init;
285 FDirty := false;
286 end;
287 end;
288
289 procedure TFB30Status.FreeHandle;
290 begin
291 if FStatus <> nil then
292 begin
293 FStatus.dispose;
294 FStatus := nil;
295 end;
296 end;
297
298 function TFB30Status.InErrorState: boolean;
299 begin
300 with GetStatus do
301 Result := ((getState and STATE_ERRORS) <> 0);
302 if Result then
303 FDirty := true;
304 end;
305
306 function TFB30Status.Warning: boolean;
307 begin
308 with GetStatus do
309 Result := ((getState and STATE_WARNINGS) <> 0);
310 if Result then
311 FDirty := true;
312 end;
313
314 function TFB30Status.GetStatus: Firebird.IStatus;
315 begin
316 if FStatus = nil then
317 with FOwner do
318 FStatus := (FOwner as TFB30ClientAPI).MasterIntf.GetStatus;
319 Result := FStatus;
320 end;
321
322 function TFB30Status.StatusVector: PStatusVector;
323 begin
324 Result := PStatusVector(GetStatus.getErrors);
325 end;
326
327 { TFB30ClientAPI }
328
329 procedure TFB30ClientAPI.CheckPlugins;
330 var FBConf: Firebird.IFirebirdConf;
331 Plugins: AnsiString;
332 PluginsList: TStringList;
333 begin
334 FIsEmbeddedServer := false;
335 FBConf := FConfigManager.getFirebirdConf;
336 try
337 Plugins := FBConf.asString(FBConf.getKey('Providers'));
338 finally
339 FBConf.release;
340 end;
341 if Plugins = '' then Exit;
342
343 PluginsList := TStringList.Create;
344 try
345 PluginsList.CommaText := Plugins;
346 FIsEmbeddedServer := (PluginsList.IndexOf('Engine12') <> -1) or {Firebird 3}
347 (PluginsList.IndexOf('Engine13') <> -1); {Firebird 4}
348 finally
349 PluginsList.Free;
350 end;
351 end;
352
353 function TFB30ClientAPI.Firebird4orLater: boolean;
354 begin
355 Result := (GetClientMajor > 4) or (
356 (GetClientMajor = 4) and (UtilIntf.vtable.version >= 4)
357 and (UtilIntf.vtable.version <> 21) {ignore FB4 Beta1}
358 and (UtilIntf.vtable.version <> 24)) {ignore FB4 Beta2}
359 end;
360
361 {$IFDEF UNIX}
362 function TFB30ClientAPI.GetFirebirdLibList: string;
363 begin
364 Result := 'libfbclient.so:libfbclient.so.2';
365 end;
366 {$ENDIF}
367
368 function TFB30ClientAPI.LoadInterface: boolean;
369 var
370 fb_get_master_interface: Tfb_get_master_interface;
371 begin
372 Result := inherited LoadInterface;
373 if (FMaster = nil) and (GetFBLibrary <> nil) then {get from library}
374 begin
375 fb_get_master_interface := GetProcAddress(GetFBLibrary.GetHandle, 'fb_get_master_interface'); {do not localize}
376 if assigned(fb_get_master_interface) then
377 FMaster := fb_get_master_interface;
378 end;
379 if FMaster <> nil then
380 begin
381 FUtil := FMaster.getUtilInterface;
382 FProvider := FMaster.getDispatcher;
383 FConfigManager := FMaster.getConfigManager;
384 CheckPlugins;
385 end;
386 Result := Result and HasMasterIntf;
387 end;
388
389 procedure TFB30ClientAPI.FBShutdown;
390 begin
391 if assigned(fb_shutdown) then
392 begin
393 FStatus.FreeHandle;
394 if assigned(FProvider) then
395 begin
396 FProvider.release;
397 FProvider := nil;
398 end;
399 end;
400 inherited;
401 end;
402
403 function TFB30ClientAPI.GetAPI: IFirebirdAPI;
404 begin
405 Result := self;
406 end;
407
408 constructor TFB30ClientAPI.Create(aFBLibrary: TFBLibrary);
409 begin
410 inherited Create(aFBLibrary);
411 FStatus := TFB30Status.Create(self);
412 FStatusIntf := FStatus;
413 end;
414
415 constructor TFB30ClientAPI.Create(aMaster: Firebird.IMaster);
416 begin
417 inherited Create(nil);
418 FMaster := aMaster;
419 FStatus := TFB30Status.Create(self);
420 FStatusIntf := FStatus;
421 if FMaster <> nil then
422 begin
423 FUtil := FMaster.getUtilInterface;
424 FProvider := FMaster.getDispatcher;
425 FConfigManager := FMaster.getConfigManager;
426 CheckPlugins;
427 end;
428 end;
429
430 destructor TFB30ClientAPI.Destroy;
431 begin
432 FStatus.FreeHandle;
433 if assigned(FProvider) then
434 FProvider.release;
435 inherited Destroy;
436 end;
437
438 function TFB30ClientAPI.StatusIntf: Firebird.IStatus;
439 begin
440 Result := FStatus.GetStatus;
441 Result.Init;
442 end;
443
444 procedure TFB30ClientAPI.Check4DataBaseError;
445 begin
446 if FStatus.InErrorState then
447 IBDataBaseError;
448 end;
449
450 procedure TFB30ClientAPI.Check4DataBaseError(st: Firebird.IStatus);
451 begin
452 if ((st.getState and st.STATE_ERRORS) <> 0) then
453 raise EIBInterBaseError.Create(TFB30StatusObject.Create(self,st));
454 end;
455
456 function TFB30ClientAPI.FormatStatus(Status: Firebird.IStatus): AnsiString;
457 var local_buffer: array[0..IBHugeLocalBufferLength - 1] of AnsiChar;
458 begin
459 Result := '';
460 if UtilIntf.formatStatus(@local_buffer,sizeof(local_buffer) - 1,Status) > 0 then
461 Result := strpas(local_buffer);
462 end;
463
464 function TFB30ClientAPI.InErrorState: boolean;
465 begin
466 Result := FStatus.InErrorState;
467 end;
468
469 function TFB30ClientAPI.GetStatus: IStatus;
470 begin
471 Result := FStatusIntf;
472 end;
473
474 function TFB30ClientAPI.AllocateDPB: IDPB;
475 begin
476 Result := TDPB.Create(self);
477 end;
478
479 function TFB30ClientAPI.AllocateTPB: ITPB;
480 begin
481 Result := TTPB.Create(self);
482 end;
483
484 function TFB30ClientAPI.OpenDatabase(DatabaseName: AnsiString; DPB: IDPB;
485 RaiseExceptionOnConnectError: boolean): IAttachment;
486 begin
487 Result := TFB30Attachment.Create(self,DatabaseName, DPB, RaiseExceptionOnConnectError);
488 if not Result.IsConnected then
489 Result := nil;
490 end;
491
492 function TFB30ClientAPI.CreateDatabase(DatabaseName: AnsiString; DPB: IDPB;
493 RaiseExceptionOnError: boolean): IAttachment;
494 begin
495 Result := TFB30Attachment.CreateDatabase(self,DatabaseName,DPB, RaiseExceptionOnError);
496 if not Result.IsConnected then
497 Result := nil;
498 end;
499
500 function TFB30ClientAPI.CreateDatabase(sql: AnsiString; aSQLDialect: integer;
501 RaiseExceptionOnError: boolean): IAttachment;
502 begin
503 Result := TFB30Attachment.CreateDatabase(self,sql,aSQLDialect, RaiseExceptionOnError);
504 if not Result.IsConnected then
505 Result := nil;
506 end;
507
508 function TFB30ClientAPI.StartTransaction(Attachments: array of IAttachment;
509 TPB: array of byte; DefaultCompletion: TTransactionCompletion; aName: AnsiString): ITransaction;
510 begin
511 Result := TFB30Transaction.Create(self,Attachments,TPB,DefaultCompletion,aName);
512 end;
513
514 function TFB30ClientAPI.StartTransaction(Attachments: array of IAttachment;
515 TPB: ITPB; DefaultCompletion: TTransactionCompletion; aName: AnsiString): ITransaction;
516 begin
517 Result := TFB30Transaction.Create(self,Attachments,TPB,DefaultCompletion,aName);
518 end;
519
520 function TFB30ClientAPI.AllocateSPB: ISPB;
521 begin
522 Result := TSPB.Create(self);
523 end;
524
525 function TFB30ClientAPI.GetServiceManager(ServerName: AnsiString;
526 Protocol: TProtocol; SPB: ISPB): IServiceManager;
527 begin
528 Result := TFB30ServiceManager.Create(self,ServerName,Protocol,SPB);
529 end;
530
531 function TFB30ClientAPI.GetServiceManager(ServerName: AnsiString;
532 Port: Ansistring; Protocol: TProtocol; SPB: ISPB): IServiceManager;
533 begin
534 Result := TFB30ServiceManager.Create(self,ServerName,Protocol,SPB,Port);
535 end;
536
537 function TFB30ClientAPI.HasServiceAPI: boolean;
538 begin
539 Result := true;
540 end;
541
542 function TFB30ClientAPI.HasMasterIntf: boolean;
543 begin
544 Result := MasterIntf <> nil;
545 end;
546
547 function TFB30ClientAPI.GetIMaster: TObject;
548 begin
549 Result := FMaster;
550 end;
551
552 function TFB30ClientAPI.GetIMasterIntf: Firebird.IMaster;
553 begin
554 Result := FMaster;
555 end;
556
557 function TFB30ClientAPI.HasRollbackRetaining: boolean;
558 begin
559 Result := true;
560 end;
561
562 function TFB30ClientAPI.IsEmbeddedServer: boolean;
563 begin
564 Result := FIsEmbeddedServer;
565 end;
566
567 function TFB30ClientAPI.GetClientMajor: integer;
568 begin
569 Result := UtilIntf.GetClientVersion div 256;
570 end;
571
572 function TFB30ClientAPI.GetClientMinor: integer;
573 begin
574 Result := UtilIntf.GetClientVersion mod 256;
575 end;
576
577 procedure TFB30ClientAPI.SQLEncodeDate(aDate: TDateTime; bufptr: PByte);
578 var
579 Yr, Mn, Dy: Word;
580 begin
581 DecodeDate(aDate, Yr, Mn, Dy);
582 PISC_Date(Bufptr)^ := UtilIntf.encodeDate(Yr, Mn, Dy);
583 end;
584
585 function TFB30ClientAPI.SQLDecodeDate(bufptr: PByte): TDateTime;
586 var
587 Yr, Mn, Dy: cardinal;
588 begin
589 UtilIntf.decodeDate(PISC_DATE(bufptr)^,@Yr, @Mn, @Dy);
590 try
591 result := EncodeDate(Yr, Mn,Dy);
592 except
593 on E: EConvertError do begin
594 IBError(ibxeInvalidDataConversion, [nil]);
595 end;
596 end;
597 end;
598
599 procedure TFB30ClientAPI.SQLEncodeTime(aTime: TDateTime; bufptr: PByte);
600 var
601 Hr, Mt, S: word;
602 DMs: cardinal;
603 begin
604 FBDecodeTime(aTime,Hr, Mt, S, DMs);
605 PISC_TIME(bufptr)^ := UtilIntf.encodeTime(Hr, Mt, S, DMs);
606 end;
607
608 function TFB30ClientAPI.SQLDecodeTime(bufptr: PByte): TDateTime;
609 var
610 Hr, Mt, S, DMs: cardinal;
611 begin
612 UtilIntf.decodeTime(PISC_TIME(bufptr)^,@Hr, @Mt, @S, @DMs);
613 try
614 Result := FBEncodeTime(Hr, Mt, S, DMs);
615 except
616 on E: EConvertError do begin
617 IBError(ibxeInvalidDataConversion, [nil]);
618 end;
619 end;
620 end;
621
622 procedure TFB30ClientAPI.SQLEncodeDateTime(aDateTime: TDateTime; bufptr: PByte);
623 begin
624 SQLEncodeDate(aDateTime,bufPtr);
625 Inc(bufptr,sizeof(ISC_DATE));
626 SQLEncodeTime(aDateTime,bufPtr);
627 end;
628
629 function TFB30ClientAPI.SQLDecodeDateTime(bufptr: PByte): TDateTime;
630 begin
631 Result := SQLDecodeDate(bufPtr);
632 Inc(bufptr,sizeof(ISC_DATE));
633 Result := Result + SQLDecodeTime(bufPtr);
634 end;
635
636 procedure TFB30ClientAPI.SQLDecFloatEncode(aValue: tBCD; SQLType: cardinal;
637 bufptr: PByte);
638 var DecFloat16: IDecFloat16;
639 DecFloat34: IDecFloat34;
640 sign: integer;
641 exp: integer;
642 buffer: array [1..34] of byte;
643
644 procedure UnpackBuffer(width: integer);
645 var i,j: integer;
646 begin
647 Fillchar(buffer,sizeof(buffer),0);
648 if BCDPrecision(aValue) > width then
649 IBError(ibxeBCDTooBig,[BCDPrecision(aValue),width]);
650 j := 1 + (width - aValue.Precision);
651 for i := 0 to (aValue.Precision - 1) div 2 do
652 if j <= width then
653 begin
654 buffer[j] := (aValue.Fraction[i] and $f0) shr 4;
655 Inc(j);
656 if j <= width then
657 begin
658 buffer[j] := (aValue.Fraction[i] and $0f);
659 Inc(j);
660 end;
661 end;
662 {writeln('Precision = ',aValue.Precision,' Places = ',aValue.SignSpecialPlaces and $2f);
663 write('BCD Buffer = ');
664 for i := 1 to 34 do
665 write(buffer[i],' ');
666 writeln; }
667 end;
668
669 begin
670 inherited SQLDecFloatEncode(aValue, SQLType, bufptr);
671 sign := (aValue.SignSpecialPlaces and $80) shr 7;
672 exp := -(aValue.SignSpecialPlaces and $2f);
673
674 case SQLType of
675 SQL_DEC16:
676 begin
677 UnPackbuffer(16);
678 DecFloat16 := UtilIntf.getDecFloat16(StatusIntf);
679 Check4DataBaseError;
680 DecFloat16.fromBcd(sign,@buffer,exp,FB_DEC16Ptr(bufptr));
681 Check4DataBaseError;
682 end;
683
684 SQL_DEC34:
685 begin
686 UnPackbuffer(34);
687 DecFloat34 := UtilIntf.getDecFloat34(StatusIntf);
688 Check4DataBaseError;
689 DecFloat34.fromBcd(sign,@buffer,exp,FB_DEC34Ptr(bufptr));
690 Check4DataBaseError;
691 end;
692
693 else
694 IBError(ibxeInvalidDataConversion,[]);
695 end;
696 end;
697
698 function TFB30ClientAPI.SQLDecFloatDecode(SQLType: cardinal; bufptr: PByte): tBCD;
699
700 var DecFloat16: IDecFloat16;
701 DecFloat34: IDecFloat34;
702 sign: integer;
703 exp: integer;
704 buffer: array [1..38] of byte;
705
706 procedure packbuffer(buflen: integer);
707 var i,j: integer;
708 begin
709 { write('Decode: BCD Buffer = ');
710 for i := 1 to 34 do
711 write(buffer[i],' ');
712 writeln; }
713 {pack buffer}
714 i := 1;
715 while (i <= buflen) and (buffer[i] = 0) do {skip leading zeroes}
716 inc(i);
717
718 j := 0;
719 Result.Precision := 0;
720 while i <= buflen do
721 begin
722 inc(Result.Precision);
723 if odd(Result.Precision) then
724 Result.Fraction[j] := (buffer[i] and $0f) shl 4
725 else
726 begin
727 Result.Fraction[j] := Result.Fraction[j] or (buffer[i] and $0f);
728 Inc(j);
729 end;
730 inc(i);
731 end;
732 end;
733
734 begin
735 Result := inherited SQLDecFloatDecode(SQLType, bufptr);
736 FillChar(Result, sizeof(tBCD),0);
737 case SQLType of
738 SQL_DEC16:
739 begin
740 DecFloat16 := UtilIntf.getDecFloat16(StatusIntf);
741 Check4DataBaseError;
742 DecFloat16.toBcd(FB_DEC16Ptr(bufptr),@sign,@buffer,@exp);
743 Check4DataBaseError;
744 packbuffer(16);
745 end;
746
747 SQL_DEC34:
748 begin
749 DecFloat34 := UtilIntf.getDecFloat34(StatusIntf);
750 Check4DataBaseError;
751 DecFloat34.toBcd(FB_DEC34Ptr(bufptr),@sign,@buffer,@exp);
752 Check4DataBaseError;
753 packbuffer(34);
754 end;
755
756 else
757 IBError(ibxeInvalidDataConversion,[]);
758 end;
759 Result.SignSpecialPlaces := (-exp and $2f);
760 if sign <> 0 then
761 Result.SignSpecialPlaces := Result.SignSpecialPlaces or $80;
762 end;
763
764 procedure TFB30ClientAPI.StrToInt128(scale: integer; aValue: AnsiString;
765 bufptr: PByte);
766 begin
767 inherited StrToInt128(scale,aValue,bufPtr);
768
769 UtilIntf.getInt128(StatusIntf).fromString(StatusIntf,scale,PAnsiChar(aValue),FB_I128Ptr(bufptr));
770 Check4DatabaseError;
771 end;
772
773 function TFB30ClientAPI.Int128ToStr(bufptr: PByte; scale: integer
774 ): AnsiString;
775 const
776 bufLength = 64;
777 var Buffer: array[ 0.. bufLength] of AnsiChar;
778 begin
779 Result := inherited Int128ToStr(bufPtr,scale);
780
781 UtilIntf.getInt128(StatusIntf).toString(StatusIntf,FB_I128Ptr(bufptr),scale,buflength,PAnsiChar(@Buffer));
782 Check4DatabaseError;
783 Result := strpas(PAnsiChar(@Buffer));
784 end;
785
786 function TFB30ClientAPI.HasLocalTZDB: boolean;
787 const
788 bufLength = 128;
789 var Buffer: ISC_TIME_TZ;
790 Hr, Mt, S, DMs: cardinal;
791 tzBuffer: array[ 0.. bufLength] of AnsiChar;
792 begin
793 Result := HasTimeZoneSupport;
794 if Result then
795 begin
796 Buffer.utc_time := 0;
797 Buffer.time_zone := TimeZoneID_GMT;
798 UtilIntf.decodeTimeTz(StatusIntf, ISC_TIME_TZPtr(@Buffer),@Hr, @Mt, @S, @DMs,bufLength,PAnsiChar(@tzBuffer));
799 Check4DataBaseError;
800 Result := strpas(PAnsiChar(@tzBuffer)) <> 'GMT*';
801 end;
802 end;
803
804 function TFB30ClientAPI.HasTimeZoneSupport: boolean;
805 begin
806 Result := Firebird4orLater;
807 end;
808
809 function TFB30ClientAPI.HasExtendedTZSupport: boolean;
810 begin
811 Result := Firebird4orLater;
812 end;
813
814 function TFB30ClientAPI.HasInt128Support: boolean;
815 begin
816 Result := Firebird4orLater;
817 end;
818
819 function TFB30ClientAPI.HasScollableCursors: boolean;
820 begin
821 Result := true;
822 end;
823
824 end.
825
826

Properties

Name Value
svn:eol-style native